diff options
358 files changed, 3353 insertions, 1744 deletions
diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 3a9d8408b3c..aedc15a54c2 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -41,7 +41,10 @@ for larger features an implementation could be broken up into multiple PRs. - [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring instructions?) - [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide]) -- [ ] Formatting for new syntax has been added to the [Style Guide] ([nightly-style-procedure]) +- [ ] Style updates for any new syntax ([nightly-style-procedure]) + - [ ] Style team decision on new formatting + - [ ] Formatting for new syntax has been added to the [Style Guide] + - [ ] (non-blocking) Formatting has been implemented in `rustfmt` - [ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide]) [stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr diff --git a/Cargo.lock b/Cargo.lock index 901113bbff5..41288c55fe5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3218,17 +3218,6 @@ dependencies = [ ] [[package]] -name = "rustc-rayon" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd9fb077db982d7ceb42a90471e5a69a990b58f71e06f0d8340bb2cf35eb751" -dependencies = [ - "either", - "indexmap", - "rustc-rayon-core", -] - -[[package]] name = "rustc-rayon-core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3599,7 +3588,7 @@ dependencies = [ "parking_lot", "portable-atomic", "rustc-hash 2.1.1", - "rustc-rayon", + "rustc-rayon-core", "rustc-stable-hash", "rustc_arena", "rustc_graphviz", @@ -3945,7 +3934,6 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "rustc-rayon", "rustc-rayon-core", "rustc_abi", "rustc_ast", @@ -4409,7 +4397,6 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", - "rustc_index", "rustc_macros", "rustc_metadata", "rustc_middle", @@ -4456,6 +4443,7 @@ dependencies = [ "bitflags", "getopts", "libc", + "rand 0.9.0", "rustc_abi", "rustc_ast", "rustc_data_structures", diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index 04c81629323..323a8fab6d5 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -13,12 +13,12 @@ pub mod typetree; #[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)] pub struct StrippedCfgItem<ModId = DefId> { pub parent_module: ModId, - pub name: Ident, + pub ident: Ident, pub cfg: MetaItem, } impl<ModId> StrippedCfgItem<ModId> { pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> { - StrippedCfgItem { parent_module: f(self.parent_module), name: self.name, cfg: self.cfg } + StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg } } } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 9899ee03a51..2296b05f69b 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -47,7 +47,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; use rustc_middle::ty::{Asyncness, ResolverAstLowering}; -use rustc_span::{Ident, Span}; +use rustc_span::{Ident, Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; @@ -234,12 +234,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::FnSig { decl, header, span } } - fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) { + fn generate_param(&mut self, idx: usize, span: Span) -> (hir::Param<'hir>, NodeId) { let pat_node_id = self.next_node_id(); let pat_id = self.lower_node_id(pat_node_id); + let ident = Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}"))); let pat = self.arena.alloc(hir::Pat { hir_id: pat_id, - kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None), + kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, ident, None), span, default_binding_modes: false, }); @@ -247,9 +248,9 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id) } - fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> { + fn generate_arg(&mut self, idx: usize, param_id: HirId, span: Span) -> hir::Expr<'hir> { let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment { - ident: Ident::empty(), + ident: Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}"))), hir_id: self.next_id(), res: Res::Local(param_id), args: None, @@ -273,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count); for idx in 0..param_count { - let (param, pat_node_id) = this.generate_param(span); + let (param, pat_node_id) = this.generate_param(idx, span); parameters.push(param); let arg = if let Some(block) = block @@ -289,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id); this.lower_target_expr(&block) } else { - this.generate_arg(param.pat.hir_id, span) + this.generate_arg(idx, param.pat.hir_id, span) }; args.push(arg); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 958a6917dff..59099e5a554 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -645,7 +645,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None), - this.lower_fn_params_to_names(fdec), + this.lower_fn_params_to_idents(fdec), ) }); @@ -833,7 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. - let names = self.lower_fn_params_to_names(&sig.decl); + let idents = self.lower_fn_params_to_idents(&sig.decl); let (generics, sig) = self.lower_method_sig( generics, sig, @@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( *ident, generics, - hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), + hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(idents)), false, ) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6aa6a18ee9a..22a293d9b50 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1247,7 +1247,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None), - param_names: self.lower_fn_params_to_names(&f.decl), + param_idents: self.lower_fn_params_to_idents(&f.decl), })) } TyKind::UnsafeBinder(f) => { @@ -1494,7 +1494,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] { + fn lower_fn_params_to_idents(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Missing => None, PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), @@ -2034,7 +2034,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> { - match c.value.kind { + // We cannot just match on `ExprKind::Underscore` as `(_)` is represented as + // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer` + match c.value.peel_parens().kind { ExprKind::Underscore => { if !self.tcx.features().generic_arg_infer() { feature_err( diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs index 4c42dd1f202..bc7f22766a5 100644 --- a/compiler/rustc_ast_pretty/src/pprust/tests.rs +++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs @@ -7,12 +7,12 @@ use super::*; fn fun_to_string( decl: &ast::FnDecl, header: ast::FnHeader, - name: Ident, + ident: Ident, generics: &ast::Generics, ) -> String { to_string(|s| { s.head(""); - s.print_fn(decl, header, Some(name), generics); + s.print_fn(decl, header, Some(ident), generics); s.end(); // Close the head box. s.end(); // Close the outer box. }) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 1f4eb0c449f..8a8ecc3b96e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2500,11 +2500,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); let ty::Tuple(params) = tupled_params.kind() else { return }; - // Find the first argument with a matching type, get its name - let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map( - |(param_ty, name)| { + // Find the first argument with a matching type and get its identifier. + let Some(this_name) = params.iter().zip(tcx.hir_body_param_idents(closure.body)).find_map( + |(param_ty, ident)| { // FIXME: also support deref for stuff like `Rc` arguments - if param_ty.peel_refs() == local_ty { name } else { None } + if param_ty.peel_refs() == local_ty { ident } else { None } }, ) else { return; @@ -3774,7 +3774,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - self.infcx.tcx.fn_arg_names(method_did)[0], + self.infcx.tcx.fn_arg_idents(method_did)[0], ) { err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index eb664f1d4f2..f9f63ae92a8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1026,7 +1026,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - self.infcx.tcx.fn_arg_names(method_did)[0], + self.infcx.tcx.fn_arg_idents(method_did)[0], ); return FnSelfUse { diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 351413dea49..4161829480d 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -234,7 +234,7 @@ mod llvm_enzyme { let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind { ast::MetaItemKind::List(ref vec) => vec.clone(), _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); return vec![item]; } }; diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 8862965c053..a91f2d38a93 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -20,14 +20,14 @@ use crate::errors; struct ProcMacroDerive { id: NodeId, trait_name: Symbol, - function_name: Ident, + function_ident: Ident, span: Span, attrs: Vec<Symbol>, } struct ProcMacroDef { id: NodeId, - function_name: Ident, + function_ident: Ident, span: Span, } @@ -95,7 +95,7 @@ impl<'a> CollectProcMacros<'a> { fn collect_custom_derive( &mut self, item: &'a ast::Item, - function_name: Ident, + function_ident: Ident, attr: &'a ast::Attribute, ) { let Some((trait_name, proc_attrs)) = @@ -109,7 +109,7 @@ impl<'a> CollectProcMacros<'a> { id: item.id, span: item.span, trait_name, - function_name, + function_ident, attrs: proc_attrs, })); } else { @@ -123,12 +123,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { + fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_ident: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Attr(ProcMacroDef { id: item.id, span: item.span, - function_name, + function_ident, })); } else { let msg = if !self.in_root { @@ -141,12 +141,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { + fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_ident: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Bang(ProcMacroDef { id: item.id, span: item.span, - function_name, + function_ident, })); } else { let msg = if !self.in_root { @@ -303,7 +303,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> { ProcMacro::Derive(m) => m.span, ProcMacro::Attr(m) | ProcMacro::Bang(m) => m.span, }; - let local_path = |cx: &ExtCtxt<'_>, name| cx.expr_path(cx.path(span, vec![name])); + let local_path = |cx: &ExtCtxt<'_>, ident| cx.expr_path(cx.path(span, vec![ident])); let proc_macro_ty_method_path = |cx: &ExtCtxt<'_>, method| { cx.expr_path(cx.path( span.with_ctxt(harness_span.ctxt()), @@ -327,7 +327,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> { .map(|&s| cx.expr_str(span, s)) .collect::<ThinVec<_>>(), ), - local_path(cx, cd.function_name), + local_path(cx, cd.function_ident), ], ) } @@ -345,8 +345,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> { harness_span, proc_macro_ty_method_path(cx, ident), thin_vec![ - cx.expr_str(span, ca.function_name.name), - local_path(cx, ca.function_name), + cx.expr_str(span, ca.function_ident.name), + local_path(cx, ca.function_ident), ], ) } diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 444dc441286..00136ac4a57 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -169,8 +169,11 @@ fn produce_final_output_artifacts( if codegen_results.modules.len() == 1 { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&codegen_results.modules[0].name[..]); - let path = crate_output.temp_path(output_type, module_name); + let path = crate_output.temp_path_for_cgu( + output_type, + &codegen_results.modules[0].name, + sess.invocation_temp.as_deref(), + ); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -183,22 +186,16 @@ fn produce_final_output_artifacts( ensure_removed(sess.dcx(), &path); } } else { - let extension = crate_output - .temp_path(output_type, None) - .extension() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -351,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> { fn emit_cgu( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, name: String, module: UnwindModule<ObjectModule>, @@ -366,6 +364,7 @@ fn emit_cgu( let module_regular = emit_module( output_filenames, + invocation_temp, prof, product.object, ModuleKind::Regular, @@ -391,6 +390,7 @@ fn emit_cgu( fn emit_module( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, @@ -409,7 +409,7 @@ fn emit_module( object.set_section_data(comment_section, producer, 1); } - let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); + let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp); let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -449,8 +449,11 @@ fn reuse_workproduct_for_cgu( cgu: &CodegenUnit<'_>, ) -> Result<ModuleCodegenResult, String> { let work_product = cgu.previous_work_product(tcx); - let obj_out_regular = - tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Object, + cgu.name().as_str(), + tcx.sess.invocation_temp.as_deref(), + ); let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), @@ -595,13 +598,19 @@ fn module_codegen( let global_asm_object_file = profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| { - crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) + crate::global_asm::compile_global_asm( + &global_asm_config, + &cgu_name, + &cx.global_asm, + cx.invocation_temp.as_deref(), + ) })?; let codegen_result = profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| { emit_cgu( &global_asm_config.output_filenames, + cx.invocation_temp.as_deref(), &profiler, cgu_name, module, @@ -626,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled .as_str() .to_string(); - let tmp_file = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + let tmp_file = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Metadata, + &metadata_cgu_name, + tcx.sess.invocation_temp.as_deref(), + ); let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); @@ -657,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> { match emit_module( tcx.output_filenames(()), + tcx.sess.invocation_temp.as_deref(), &tcx.sess.prof, product.object, ModuleKind::Allocator, @@ -728,26 +741,27 @@ pub(crate) fn run_aot( let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len())); - let modules = tcx.sess.time("codegen mono items", || { - let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { - let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph - .with_task( + let modules: Vec<_> = + tcx.sess.time("codegen mono items", || { + let modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { + let dep_node = cgu.codegen_dep_node(tcx); + let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())), module_codegen, Some(rustc_middle::dep_graph::hash_result), - ) - .0 - }); - modules.extend( - done_cgus + ); + IntoDynSyncSend(module) + }); + modules .into_iter() - .map(|(_, cgu)| OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))), - ); - modules - }); + .map(|module| module.0) + .chain(done_cgus.into_iter().map(|(_, cgu)| { + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) + })) + .collect() + }); let allocator_module = emit_allocator_module(tcx); diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 9ea92c300f8..79cefb05de3 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, + invocation_temp: Option<&str>, ) -> Result<Option<PathBuf>, String> { if global_asm.is_empty() { return Ok(None); @@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm( global_asm.push('\n'); let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)), + config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp), ".asm", ); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index e7afaff3b42..9d9e790289c 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -124,6 +124,7 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> { /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx { output_filenames: Arc<OutputFilenames>, + invocation_temp: Option<String>, should_write_ir: bool, global_asm: String, inline_asm_index: usize, @@ -142,6 +143,7 @@ impl CodegenCx { }; CodegenCx { output_filenames: tcx.output_filenames(()).clone(), + invocation_temp: tcx.sess.invocation_temp.clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), inline_asm_index: 0, diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 6d5df2b0043..3b48adb7e91 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -104,7 +104,7 @@ pub(crate) fn maybe_create_entry_wrapper( let termination_trait = tcx.require_lang_item(LangItem::Termination, None); let report = tcx .associated_items(termination_trait) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, Ident::from_str("report"), AssocKind::Fn, diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index 51c5ba73e32..16c895322e8 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen( { let context = &module.module_llvm.context; - let module_name = module.name.clone(); - let should_combine_object_files = module.module_llvm.should_combine_object_files; - let module_name = Some(&module_name[..]); - // NOTE: Only generate object files with GIMPLE when this environment variable is set for // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit). // TODO(antoyo): remove this environment variable. let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Bitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); + let obj_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.bitcode_needed() { if fat_lto { @@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen( } if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::LlvmAssembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Assembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -238,6 +250,7 @@ pub(crate) unsafe fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, + cgcx.invocation_temp.as_deref(), )) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 76d431a4975..18d221d232e 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -119,14 +119,18 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar tcx.output_filenames(()).split_dwarf_path( tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, - Some(mod_name), + mod_name, + tcx.sess.invocation_temp.as_deref(), ) } else { None }; - let output_obj_file = - Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name))); + let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Object, + mod_name, + tcx.sess.invocation_temp.as_deref(), + )); let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; target_machine_factory( @@ -330,8 +334,11 @@ pub(crate) fn save_temp_bitcode( return; } let ext = format!("{name}.bc"); - let cgu = Some(&module.name[..]); - let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); + let path = cgcx.output_filenames.temp_path_ext_for_cgu( + &ext, + &module.name, + cgcx.invocation_temp.as_deref(), + ); write_bitcode_to_file(module, &path) } @@ -694,11 +701,12 @@ pub(crate) unsafe fn optimize( let llcx = &*module.module_llvm.llcx; let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); - if config.emit_no_opt_bc { - let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); + let out = cgcx.output_filenames.temp_path_ext_for_cgu( + "no-opt.bc", + &module.name, + cgcx.invocation_temp.as_deref(), + ); write_bitcode_to_file(module, &out) } @@ -743,8 +751,11 @@ pub(crate) unsafe fn optimize( if let Some(thin_lto_buffer) = thin_lto_buffer { let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) }; module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec()); - let bc_summary_out = - cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name); + let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::ThinLinkBitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.emit_thin_lto_summary && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name() { @@ -801,8 +812,6 @@ pub(crate) unsafe fn codegen( let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; let tm = &*module.module_llvm.tm; - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::Codegen); @@ -814,8 +823,16 @@ pub(crate) unsafe fn codegen( // copy it to the .o file, and delete the bitcode if it wasn't // otherwise requested. - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Bitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); + let obj_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.bitcode_needed() { if config.emit_bc || config.emit_obj == EmitObj::Bitcode { @@ -857,7 +874,11 @@ pub(crate) unsafe fn codegen( if config.emit_ir { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::LlvmAssembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); let out_c = path_to_c_string(&out); extern "C" fn demangle_callback( @@ -899,7 +920,11 @@ pub(crate) unsafe fn codegen( if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Assembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); // We can't use the same module for asm and object code output, // because that triggers various errors like invalid IR or broken @@ -929,7 +954,9 @@ pub(crate) unsafe fn codegen( .prof .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); - let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name); + let dwo_out = cgcx + .output_filenames + .temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref()); let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) { // Don't change how DWARF is emitted when disabled. (SplitDebuginfo::Off, _) => None, @@ -994,6 +1021,7 @@ pub(crate) unsafe fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, + cgcx.invocation_temp.as_deref(), )) } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 457e5452ce9..a6f277e4455 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -4,8 +4,8 @@ use std::borrow::Borrow; use libc::{c_char, c_uint}; use rustc_abi as abi; +use rustc_abi::HasDataLayout; use rustc_abi::Primitive::Pointer; -use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; @@ -269,7 +269,8 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { } Scalar::Ptr(ptr, _size) => { let (prov, offset) = ptr.into_parts(); - let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) { + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let base_addr = match global_alloc { GlobalAlloc::Memory(alloc) => { // For ZSTs directly codegen an aligned pointer. // This avoids generating a zero-sized constant value and actually needing a @@ -301,12 +302,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { format!("alloc_{hash:032x}").as_bytes(), ); } - (value, AddressSpace::DATA) + value } } - GlobalAlloc::Function { instance, .. } => { - (self.get_fn_addr(instance), self.data_layout().instruction_address_space) - } + GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance), GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx @@ -319,14 +318,15 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { .unwrap_memory(); let init = const_alloc_to_llvm(self, alloc, /*static*/ false); let value = self.static_addr_of_impl(init, alloc.inner().align, None); - (value, AddressSpace::DATA) + value } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); assert!(!self.tcx.is_thread_local_static(def_id)); - (self.get_static(def_id), AddressSpace::DATA) + self.get_static(def_id) } }; + let base_addr_space = global_alloc.address_space(self); let llval = unsafe { llvm::LLVMConstInBoundsGEP2( self.type_i8(), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 2eaaf127e41..1eb8f367c54 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -910,7 +910,8 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( && let Some(f) = output_filenames.split_dwarf_path( tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, - Some(codegen_unit_name), + codegen_unit_name, + tcx.sess.invocation_temp.as_deref(), ) { // We get a path relative to the working directory from split_dwarf_path Some(tcx.sess.source_map().path_mapping().to_real_filename(f)) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 67135fcc308..d1d6bcebd33 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1421,7 +1421,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), indices)); } - if name == sym::simd_insert { + if name == sym::simd_insert || name == sym::simd_insert_dyn { require!( in_elem == arg_tys[2], InvalidMonomorphization::InsertedType { @@ -1432,40 +1432,49 @@ fn generic_simd_intrinsic<'ll, 'tcx>( out_ty: arg_tys[2] } ); - let idx = bx - .const_to_opt_u128(args[1].immediate(), false) - .expect("typeck should have ensure that this is a const"); - if idx >= in_len.into() { - return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { - span, - name, - arg_idx: 1, - total_len: in_len.into(), - }); - } - return Ok(bx.insert_element( - args[0].immediate(), - args[2].immediate(), - bx.const_i32(idx as i32), - )); + + let index_imm = if name == sym::simd_insert { + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + } + bx.const_i32(idx as i32) + } else { + args[1].immediate() + }; + + return Ok(bx.insert_element(args[0].immediate(), args[2].immediate(), index_imm)); } - if name == sym::simd_extract { + if name == sym::simd_extract || name == sym::simd_extract_dyn { require!( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); - let idx = bx - .const_to_opt_u128(args[1].immediate(), false) - .expect("typeck should have ensure that this is a const"); - if idx >= in_len.into() { - return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { - span, - name, - arg_idx: 1, - total_len: in_len.into(), - }); - } - return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32))); + let index_imm = if name == sym::simd_extract { + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + } + bx.const_i32(idx as i32) + } else { + args[1].immediate() + }; + + return Ok(bx.extract_element(args[0].immediate(), index_imm)); } if name == sym::simd_select { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1d05c4eee4d..8de68925cab 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -112,8 +112,12 @@ pub fn link_binary( codegen_results.crate_info.local_crate_name, ); let crate_name = format!("{}", codegen_results.crate_info.local_crate_name); - let out_filename = - output.file_for_writing(outputs, OutputType::Exe, Some(crate_name.as_str())); + let out_filename = output.file_for_writing( + outputs, + OutputType::Exe, + &crate_name, + sess.invocation_temp.as_deref(), + ); match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index e816e71379a..0fd4ed8475b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -306,14 +306,18 @@ impl TargetMachineFactoryConfig { cgcx.output_filenames.split_dwarf_path( cgcx.split_debuginfo, cgcx.split_dwarf_kind, - Some(module_name), + module_name, + cgcx.invocation_temp.as_deref(), ) } else { None }; - let output_obj_file = - Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name))); + let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + module_name, + cgcx.invocation_temp.as_deref(), + )); TargetMachineFactoryConfig { split_dwarf_file, output_obj_file } } } @@ -344,6 +348,7 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub crate_types: Vec<CrateType>, pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>, pub output_filenames: Arc<OutputFilenames>, + pub invocation_temp: Option<String>, pub regular_module_config: Arc<ModuleConfig>, pub metadata_module_config: Arc<ModuleConfig>, pub allocator_module_config: Arc<ModuleConfig>, @@ -582,8 +587,11 @@ fn produce_final_output_artifacts( if let [module] = &compiled_modules.modules[..] { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&module.name[..]); - let path = crate_output.temp_path(output_type, module_name); + let path = crate_output.temp_path_for_cgu( + output_type, + &module.name, + sess.invocation_temp.as_deref(), + ); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -596,22 +604,15 @@ fn produce_final_output_artifacts( ensure_removed(sess.dcx(), &path); } } else { - let extension = crate_output - .temp_path(output_type, None) - .extension() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(errors::IgnoringEmitPath { extension }); + sess.dcx() + .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(errors::IgnoringOutput { extension }); + sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -967,7 +968,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { let dwarf_obj_out = cgcx .output_filenames - .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, Some(&module.name)) + .split_dwarf_path( + cgcx.split_debuginfo, + cgcx.split_dwarf_kind, + &module.name, + cgcx.invocation_temp.as_deref(), + ) .expect( "saved dwarf object in work product but `split_dwarf_path` returned `None`", ); @@ -977,7 +983,11 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( let mut load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; - let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name)); + let output_path = cgcx.output_filenames.temp_path_for_cgu( + output_type, + &module.name, + cgcx.invocation_temp.as_deref(), + ); load_from_incr_comp_dir(output_path, &saved_file) } else { None @@ -1222,6 +1232,7 @@ fn start_executing_work<B: ExtraBackendMethods>( split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, pointer_size: tcx.data_layout.pointer_size, + invocation_temp: sess.invocation_temp.clone(), }; // This is the "main loop" of parallel work happening for parallel codegen. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1985b3b7170..12b7a487455 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -10,7 +10,7 @@ use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_n use rustc_attr_parsing::OptimizeAttr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; -use rustc_data_structures::sync::par_map; +use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; @@ -640,8 +640,11 @@ pub fn codegen_crate<B: ExtraBackendMethods>( let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); tcx.sess.time("write_compressed_metadata", || { - let file_name = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + let file_name = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Metadata, + &metadata_cgu_name, + tcx.sess.invocation_temp.as_deref(), + ); let data = create_compressed_metadata_file( tcx.sess, &metadata, @@ -757,7 +760,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( let pre_compiled_cgus = par_map(cgus, |(i, _)| { let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); - (i, module) + (i, IntoDynSyncSend(module)) }); total_codegen_time += start_time.elapsed(); @@ -777,7 +780,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( match cgu_reuse { CguReuse::No => { let (module, cost) = if let Some(cgu) = pre_compiled_cgus.remove(&i) { - cgu + cgu.0 } else { let start_time = Instant::now(); let module = backend.compile_codegen_unit(tcx, cgu.name()); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index b33de8802d8..42cea5c86d4 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -277,13 +277,13 @@ pub struct BinaryOutputToTty { #[derive(Diagnostic)] #[diag(codegen_ssa_ignoring_emit_path)] pub struct IgnoringEmitPath { - pub extension: String, + pub extension: &'static str, } #[derive(Diagnostic)] #[diag(codegen_ssa_ignoring_output)] pub struct IgnoringOutput { - pub extension: String, + pub extension: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 67217927a87..153935f2531 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -105,13 +105,19 @@ impl<M> ModuleCodegen<M> { emit_asm: bool, emit_ir: bool, outputs: &OutputFilenames, + invocation_temp: Option<&str>, ) -> CompiledModule { - let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); - let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name))); - let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); - let assembly = emit_asm.then(|| outputs.temp_path(OutputType::Assembly, Some(&self.name))); - let llvm_ir = - emit_ir.then(|| outputs.temp_path(OutputType::LlvmAssembly, Some(&self.name))); + let object = emit_obj + .then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp)); + let dwarf_object = + emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp)); + let bytecode = emit_bc + .then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp)); + let assembly = emit_asm + .then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp)); + let llvm_ir = emit_ir.then(|| { + outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp) + }); CompiledModule { name: self.name.clone(), diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index fcaf2750507..f48c73b13b9 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -14,7 +14,7 @@ indexmap = "2.4.0" jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "12.0.1" rustc-hash = "2.0.0" -rustc-rayon = { version = "0.5.1", features = ["indexmap"] } +rustc-rayon-core = { version = "0.5.0" } rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 64c64bfa3c2..744ae9b6fe2 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -180,6 +180,12 @@ impl<T> FromDyn<T> { } #[inline(always)] + pub fn derive<O>(&self, val: O) -> FromDyn<O> { + // We already did the check for `sync::is_dyn_thread_safe()` when creating `Self` + FromDyn(val) + } + + #[inline(always)] pub fn into_inner(self) -> T { self.0 } @@ -200,6 +206,13 @@ impl<T> std::ops::Deref for FromDyn<T> { } } +impl<T> std::ops::DerefMut for FromDyn<T> { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + // A wrapper to convert a struct that is already a `Send` or `Sync` into // an instance of `DynSend` and `DynSync`, since the compiler cannot infer // it automatically in some cases. (e.g. Box<dyn Send / Sync>) diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs index 9720b22ea7d..6338afb92c3 100644 --- a/compiler/rustc_data_structures/src/sync/freeze.rs +++ b/compiler/rustc_data_structures/src/sync/freeze.rs @@ -88,7 +88,7 @@ impl<T> FreezeLock<T> { #[inline] #[track_caller] pub fn write(&self) -> FreezeWriteGuard<'_, T> { - self.try_write().expect("still mutable") + self.try_write().expect("data should not be frozen if we're still attempting to mutate it") } #[inline] diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 8ef8a3f3585..ba3c85ef5b1 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -7,7 +7,6 @@ use std::any::Any; use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; use parking_lot::Mutex; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; use crate::FatalErrorMarker; use crate::sync::{DynSend, DynSync, FromDyn, IntoDynSyncSend, mode}; @@ -97,11 +96,11 @@ macro_rules! parallel { // This function only works when `mode::is_dyn_thread_safe()`. pub fn scope<'scope, OP, R>(op: OP) -> R where - OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend, + OP: FnOnce(&rayon_core::Scope<'scope>) -> R + DynSend, R: DynSend, { let op = FromDyn::from(op); - rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() + rayon_core::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() } #[inline] @@ -114,7 +113,7 @@ where let oper_a = FromDyn::from(oper_a); let oper_b = FromDyn::from(oper_b); let (a, b) = parallel_guard(|guard| { - rayon::join( + rayon_core::join( move || guard.run(move || FromDyn::from(oper_a.into_inner()())), move || guard.run(move || FromDyn::from(oper_b.into_inner()())), ) @@ -125,56 +124,103 @@ where } } -pub fn par_for_each_in<I, T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>>( +fn par_slice<I: DynSend>( + items: &mut [I], + guard: &ParallelGuard, + for_each: impl Fn(&mut I) + DynSync + DynSend, +) { + struct State<'a, F> { + for_each: FromDyn<F>, + guard: &'a ParallelGuard, + group: usize, + } + + fn par_rec<I: DynSend, F: Fn(&mut I) + DynSync + DynSend>( + items: &mut [I], + state: &State<'_, F>, + ) { + if items.len() <= state.group { + for item in items { + state.guard.run(|| (state.for_each)(item)); + } + } else { + let (left, right) = items.split_at_mut(items.len() / 2); + let mut left = state.for_each.derive(left); + let mut right = state.for_each.derive(right); + rayon_core::join(move || par_rec(*left, state), move || par_rec(*right, state)); + } + } + + let state = State { + for_each: FromDyn::from(for_each), + guard, + group: std::cmp::max(items.len() / 128, 1), + }; + par_rec(items, &state) +} + +pub fn par_for_each_in<I: DynSend, T: IntoIterator<Item = I>>( t: T, - for_each: impl Fn(I) + DynSync + DynSend, + for_each: impl Fn(&I) + DynSync + DynSend, ) { parallel_guard(|guard| { if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter().for_each(|i| { - guard.run(|| for_each(i)); - }); + let mut items: Vec<_> = t.into_iter().collect(); + par_slice(&mut items, guard, |i| for_each(&*i)) } else { t.into_iter().for_each(|i| { - guard.run(|| for_each(i)); + guard.run(|| for_each(&i)); }); } }); } -pub fn try_par_for_each_in< - T: IntoIterator + IntoParallelIterator<Item = <T as IntoIterator>::Item>, - E: Send, ->( +/// This runs `for_each` in parallel for each iterator item. If one or more of the +/// `for_each` calls returns `Err`, the function will also return `Err`. The error returned +/// will be non-deterministic, but this is expected to be used with `ErrorGuaranteed` which +/// are all equivalent. +pub fn try_par_for_each_in<T: IntoIterator, E: DynSend>( t: T, - for_each: impl Fn(<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend, -) -> Result<(), E> { + for_each: impl Fn(&<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend, +) -> Result<(), E> +where + <T as IntoIterator>::Item: DynSend, +{ parallel_guard(|guard| { if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter() - .filter_map(|i| guard.run(|| for_each(i))) - .reduce(|| Ok(()), Result::and) + let mut items: Vec<_> = t.into_iter().collect(); + + let error = Mutex::new(None); + + par_slice(&mut items, guard, |i| { + if let Err(err) = for_each(&*i) { + *error.lock() = Some(err); + } + }); + + if let Some(err) = error.into_inner() { Err(err) } else { Ok(()) } } else { - t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) + t.into_iter().filter_map(|i| guard.run(|| for_each(&i))).fold(Ok(()), Result::and) } }) } -pub fn par_map< - I, - T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>, - R: std::marker::Send, - C: FromIterator<R> + FromParallelIterator<R>, ->( +pub fn par_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterator<R>>( t: T, map: impl Fn(I) -> R + DynSync + DynSend, ) -> C { parallel_guard(|guard| { if mode::is_dyn_thread_safe() { let map = FromDyn::from(map); - t.into_par_iter().filter_map(|i| guard.run(|| map(i))).collect() + + let mut items: Vec<(Option<I>, Option<R>)> = + t.into_iter().map(|i| (Some(i), None)).collect(); + + par_slice(&mut items, guard, |i| { + i.1 = Some(map(i.0.take().unwrap())); + }); + + items.into_iter().filter_map(|i| i.1).collect() } else { t.into_iter().filter_map(|i| guard.run(|| map(i))).collect() } diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index baa66cd7c85..3d44fb1fd48 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -109,6 +109,16 @@ impl<T, I: Iterator<Item = T>> UnordItems<T, I> { pub fn collect<C: From<UnordItems<T, I>>>(self) -> C { self.into() } + + /// If the iterator has only one element, returns it, otherwise returns `None`. + #[track_caller] + pub fn get_only(mut self) -> Option<T> { + let item = self.0.next(); + if self.0.next().is_some() { + return None; + } + item + } } impl<T> UnordItems<T, std::iter::Empty<T>> { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 595ac1edd28..7d9560ab4c5 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -264,6 +264,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) hash_untracked_state: None, register_lints: None, override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: diagnostics_registry(), using_internal_features: &USING_INTERNAL_FEATURES, @@ -348,10 +349,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) // Make sure name resolution and macro expansion is run. let _ = tcx.resolver_for_lowering(); - if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { - dump_feature_usage_metrics(tcx, metrics_dir); - } - if callbacks.after_expansion(compiler, tcx) == Compilation::Stop { return early_exit(); } @@ -370,6 +367,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) tcx.ensure_ok().analysis(()); + if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { + dump_feature_usage_metrics(tcx, metrics_dir); + } + if callbacks.after_analysis(compiler, tcx) == Compilation::Stop { return early_exit(); } diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index e6ff949d3e9..9b8131a061e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An intrinsic was declared without being a function. Erroneous code example: -```compile_fail,E0622 +```no_run #![feature(intrinsics)] #![allow(internal_features)] diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index dfeef5a957d..2488d870899 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -397,7 +397,7 @@ E0618: 0618, E0619: 0619, E0620: 0620, E0621: 0621, -E0622: 0622, +E0622: 0622, // REMOVED: rustc-intrinsic ABI was removed E0623: 0623, E0624: 0624, E0625: 0625, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d14e476ba32..49f6d58172f 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1102,7 +1102,7 @@ pub trait ResolverExpand { /// HIR proc macros items back to their harness items. fn declare_proc_macro(&mut self, id: NodeId); - fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem); + fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem); /// Tools registered with `#![register_tool]` and used by tool attributes and lints. fn registered_tools(&self) -> &RegisteredTools; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index bca846d2ec4..1b539477d51 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1169,9 +1169,9 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); } - /// All of the names (items) declared by this node. + /// All of the identifiers (items) declared by this node. /// This is an approximation and should only be used for diagnostics. - fn declared_names(&self) -> Vec<Ident> { + fn declared_idents(&self) -> Vec<Ident> { vec![] } } @@ -1306,7 +1306,7 @@ impl InvocationCollectorNode for P<ast::Item> { res } - fn declared_names(&self) -> Vec<Ident> { + fn declared_idents(&self) -> Vec<Ident> { if let ItemKind::Use(ut) = &self.kind { fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) { match &ut.kind { @@ -2061,10 +2061,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } if let Some(meta_item) = meta_item { - for name in node.declared_names() { + for ident in node.declared_idents() { self.cx.resolver.append_stripped_cfg_item( self.cx.current_expansion.lint_node_id, - name, + ident, meta_item.clone(), ) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index dc00b52a593..9372ab532bf 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -267,11 +267,16 @@ impl DefKind { | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam - | DefKind::ExternCrate => DefPathData::TypeNs(Some(name.unwrap())), - - // An associated type names will be missing for an RPITIT. It will - // later be given a name with `synthetic` in it, if necessary. - DefKind::AssocTy => DefPathData::TypeNs(name), + | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()), + + // An associated type name will be missing for an RPITIT. + DefKind::AssocTy => { + if let Some(name) = name { + DefPathData::TypeNs(name) + } else { + DefPathData::AnonAssocTy + } + } // It's not exactly an anon const, but wrt DefPathData, there // is no difference. diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index c52954aa96f..34f3c169505 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -271,9 +271,8 @@ pub enum DefPathData { Use, /// A global asm item. GlobalAsm, - /// Something in the type namespace. Will be empty for RPITIT associated - /// types, which are given a synthetic name later, if necessary. - TypeNs(Option<Symbol>), + /// Something in the type namespace. + TypeNs(Symbol), /// Something in the value namespace. ValueNs(Symbol), /// Something in the macro namespace. @@ -291,6 +290,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// An anonymous associated type from an RPITIT. + AnonAssocTy, /// A synthetic body for a coroutine's by-move body. SyntheticCoroutineBody, } @@ -413,9 +414,7 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option<Symbol> { use self::DefPathData::*; match *self { - TypeNs(name) => name, - - ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), Impl | ForeignMod @@ -426,6 +425,7 @@ impl DefPathData { | Ctor | AnonConst | OpaqueTy + | AnonAssocTy | SyntheticCoroutineBody => None, } } @@ -433,14 +433,9 @@ impl DefPathData { pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { - TypeNs(name) => { - if let Some(name) = name { - DefPathDataName::Named(name) - } else { - DefPathDataName::Anon { namespace: sym::synthetic } - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { + DefPathDataName::Named(name) } - ValueNs(name) | MacroNs(name) | LifetimeNs(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, @@ -451,6 +446,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, + AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc }, SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c61477951c9..c9c4936c156 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3399,9 +3399,9 @@ pub struct BareFnTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - // `Option` because bare fn parameter names are optional. We also end up + // `Option` because bare fn parameter identifiers are optional. We also end up // with `None` in some error cases, e.g. invalid parameter patterns. - pub param_names: &'hir [Option<Ident>], + pub param_idents: &'hir [Option<Ident>], } #[derive(Debug, Clone, Copy, HashStable_Generic)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ea3f396761b..93d20dfa799 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -652,10 +652,10 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ident(foreign_item.ident)); match foreign_item.kind { - ForeignItemKind::Fn(ref sig, param_names, ref generics) => { + ForeignItemKind::Fn(ref sig, param_idents, ref generics) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_names.iter().copied() { + for ident in param_idents.iter().copied() { visit_opt!(visitor, visit_ident, ident); } } @@ -1169,9 +1169,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_nested_body, default); } - TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { + TraitItemKind::Fn(ref sig, TraitFn::Required(param_idents)) => { try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_names.iter().copied() { + for ident in param_idents.iter().copied() { visit_opt!(visitor, visit_ident, ident); } } diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 0837444ffdb..18c2bfdac8c 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -17,7 +17,7 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - create_session_globals_then(Edition::Edition2024, None, || { + create_session_globals_then(Edition::Edition2024, &[], None, || { let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], ""); let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], ""); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 2f7c3cb3c7d..92701e3328e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,5 +1,5 @@ -hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$qself}` - .label = ambiguous associated {$assoc_kind} `{$assoc_name}` +hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}` + .label = ambiguous associated {$assoc_kind} `{$assoc_ident}` hir_analysis_ambiguous_lifetime_bound = ambiguous lifetime bound, explicit lifetime bound required @@ -12,13 +12,13 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private .label = private {$kind} .defined_here_label = the {$kind} is defined here -hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$qself}` +hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_ident}` not found for `{$qself}` hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> [true] an *[false] a similarly named } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` -hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found +hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_ident}` not found hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind} hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg = consider fully qualifying{$identically_named -> diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bcfbd7b0e97..f50746dd18d 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -719,7 +719,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { def_id, tcx.def_ident_span(def_id).unwrap(), i.name, - ExternAbi::Rust, ) } } @@ -787,16 +786,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for item in items { let def_id = item.id.owner_id.def_id; - if tcx.has_attr(def_id, sym::rustc_intrinsic) { - intrinsic::check_intrinsic_type( - tcx, - item.id.owner_id.def_id, - item.span, - item.ident.name, - abi, - ); - } - let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.own_params.len() - own_counts.lifetimes != 0 { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 32a8f101849..29a9931696f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1046,11 +1046,11 @@ fn report_trait_method_mismatch<'tcx>( // argument pattern and type. let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); let span = tcx - .hir_body_param_names(body) + .hir_body_param_idents(body) .zip(sig.decl.inputs.iter()) - .map(|(param_name, ty)| { - if let Some(param_name) = param_name { - param_name.span.to(ty.span) + .map(|(param_ident, ty)| { + if let Some(param_ident) = param_ident { + param_ident.span.to(ty.span) } else { ty.span } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 0bf9e127989..ed8ca27d217 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,9 +1,8 @@ //! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. use rustc_abi::ExternAbi; -use rustc_errors::codes::*; -use rustc_errors::{DiagMessage, struct_span_code_err}; -use rustc_hir::{self as hir, Safety}; +use rustc_errors::DiagMessage; +use rustc_hir::{self as hir}; use rustc_middle::bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -26,17 +25,10 @@ fn equate_intrinsic_type<'tcx>( sig: ty::PolyFnSig<'tcx>, ) { let (generics, span) = match tcx.hir_node_by_def_id(def_id) { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) - | hir::Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(_, _, generics), - .. - }) => (tcx.generics_of(def_id), generics.span), - _ => { - struct_span_code_err!(tcx.dcx(), span, E0622, "intrinsic must be a function") - .with_span_label(span, "expected a function") - .emit(); - return; + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => { + (tcx.generics_of(def_id), generics.span) } + _ => tcx.dcx().span_bug(span, "intrinsic must be a function"), }; let own_counts = generics.own_counts(); @@ -70,13 +62,7 @@ fn equate_intrinsic_type<'tcx>( } /// Returns the unsafety of the given intrinsic. -pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { - let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { - tcx.fn_sig(intrinsic_id).skip_binder().safety() - } else { - // Old-style intrinsics are never safe - Safety::Unsafe - }; +fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { let is_in_list = match tcx.item_name(intrinsic_id.into()) { // When adding a new intrinsic to this list, // it's usually worth updating that intrinsic's documentation @@ -148,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - _ => hir::Safety::Unsafe, }; - if has_safe_attr != is_in_list { + if tcx.fn_sig(intrinsic_id).skip_binder().safety() != is_in_list { tcx.dcx().struct_span_err( tcx.def_span(intrinsic_id), DiagMessage::from(format!( @@ -163,12 +149,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, /// and in `library/core/src/intrinsics.rs`. -pub fn check_intrinsic_type( +pub(crate) fn check_intrinsic_type( tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Span, intrinsic_name: Symbol, - abi: ExternAbi, ) { let generics = tcx.generics_of(intrinsic_id); let param = |n| { @@ -674,8 +659,12 @@ pub fn check_intrinsic_type( sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), - sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), - sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), + sym::simd_insert | sym::simd_insert_dyn => { + (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)) + } + sym::simd_extract | sym::simd_extract_dyn => { + (2, 0, vec![param(0), tcx.types.u32], param(1)) + } sym::simd_cast | sym::simd_as | sym::simd_cast_ptr @@ -706,7 +695,7 @@ pub fn check_intrinsic_type( }; (n_tps, 0, n_cts, inputs, output, safety) }; - let sig = tcx.mk_fn_sig(inputs, output, false, safety, abi); + let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust); let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 69b921fccbf..deded6904d4 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -439,9 +439,9 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { &self, span: Span, def_id: LocalDefId, - assoc_name: Ident, + assoc_ident: Ident, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name)) + self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident)) } fn lower_assoc_shared( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index e90a1cc24c1..ce0f83d0ec2 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -584,12 +584,12 @@ pub(super) fn explicit_super_predicates_of<'tcx>( pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>( tcx: TyCtxt<'tcx>, - (trait_def_id, assoc_name): (DefId, Ident), + (trait_def_id, assoc_ident): (DefId, Ident), ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { implied_predicates_with_filter( tcx, trait_def_id, - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), ) } @@ -617,7 +617,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( filter: PredicateFilter, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let Some(trait_def_id) = trait_def_id.as_local() else { - // if `assoc_name` is None, then the query should've been redirected to an + // if `assoc_ident` is None, then the query should've been redirected to an // external provider assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_)); return tcx.explicit_super_predicates_of(trait_def_id); @@ -834,11 +834,11 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( #[instrument(level = "trace", skip(tcx))] pub(super) fn type_param_predicates<'tcx>( tcx: TyCtxt<'tcx>, - (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident), + (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident), ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { match tcx.opt_rpitit_info(item_def_id.to_def_id()) { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { - return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_name)); + return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident)); } Some(ty::ImplTraitInTraitData::Impl { .. }) => { unreachable!("should not be lowering bounds on RPITIT in impl") @@ -863,7 +863,7 @@ pub(super) fn type_param_predicates<'tcx>( let result = if let Some(parent) = parent { let icx = ItemCtxt::new(tcx, parent); - icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_name) + icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident) } else { ty::EarlyBinder::bind(&[] as &[_]) }; @@ -889,7 +889,7 @@ pub(super) fn type_param_predicates<'tcx>( let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics( hir_generics, def_id, - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), )); let bounds = @@ -908,7 +908,7 @@ pub(super) fn type_param_predicates<'tcx>( _ => unreachable!(), }; assert_only_contains_predicates_from( - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), bounds, self_ty, ); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 404753875ee..9bcda35ee87 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1874,13 +1874,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { fn supertrait_hrtb_vars( tcx: TyCtxt<'tcx>, def_id: DefId, - assoc_name: Ident, + assoc_ident: Ident, assoc_kind: ty::AssocKind, ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> { let trait_defines_associated_item_named = |trait_def_id: DefId| { - tcx.associated_items(trait_def_id).find_by_name_and_kind( + tcx.associated_items(trait_def_id).find_by_ident_and_kind( tcx, - assoc_name, + assoc_ident, assoc_kind, trait_def_id, ) @@ -1904,7 +1904,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let Some(assoc_item) = trait_defines_associated_item_named(def_id) { break Some((bound_vars.into_iter().collect(), assoc_item)); } - let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_name)); + let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_ident)); let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e6090a128b1..508970cf255 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -23,7 +23,7 @@ pub(crate) struct AmbiguousAssocItem<'a> { #[label] pub span: Span, pub assoc_kind: &'static str, - pub assoc_name: Ident, + pub assoc_ident: Ident, pub qself: &'a str, } @@ -75,7 +75,7 @@ pub(crate) struct AssocItemIsPrivate { pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, - pub assoc_name: Ident, + pub assoc_ident: Ident, pub assoc_kind: &'static str, pub qself: &'a str, #[subdiagnostic] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 55087d1f400..24d05b49861 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -363,10 +363,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { for hir_bound in hir_bounds { // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. - if let PredicateFilter::SelfTraitThatDefines(assoc_name) = predicate_filter { + if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter { if let Some(trait_ref) = hir_bound.trait_ref() && let Some(trait_did) = trait_ref.trait_def_id() - && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) + && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident) { // Okay } else { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index ecb453bced0..d1ee5a5494c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -49,13 +49,13 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(Err(index)) => { // fn(x: u32, u32, u32, u16, y: u16) -> u32, // ^^^^^^ - let span = if let Some(ident) = bare_fn_ty.param_names[index] { + let span = if let Some(ident) = bare_fn_ty.param_idents[index] { ident.span.to(bare_fn_ty.decl.inputs[index].span) } else { bare_fn_ty.decl.inputs[index].span } .to(bare_fn_ty.decl.inputs.last().unwrap().span); - let plural = bare_fn_ty.param_names.len() - index != 1; + let plural = bare_fn_ty.param_idents.len() - index != 1; dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } Err(layout_err) => { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 6e9c178d33a..5a0524d33fd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -117,7 +117,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates: impl Fn() -> I, qself: AssocItemQSelf, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> ErrorGuaranteed @@ -129,11 +129,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // First and foremost, provide a more user-friendly & “intuitive” error on kind mismatches. if let Some(assoc_item) = all_candidates().find_map(|r| { tcx.associated_items(r.def_id()) - .filter_by_name_unhygienic(assoc_name.name) - .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id())) }) { return self.complain_about_assoc_kind_mismatch( - assoc_item, assoc_kind, assoc_name, span, constraint, + assoc_item, + assoc_kind, + assoc_ident, + span, + constraint, ); } @@ -142,18 +146,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // valid span, so we point at the whole path segment instead. - let is_dummy = assoc_name.span == DUMMY_SP; + let is_dummy = assoc_ident.span == DUMMY_SP; let mut err = errors::AssocItemNotFound { - span: if is_dummy { span } else { assoc_name.span }, - assoc_name, + span: if is_dummy { span } else { assoc_ident.span }, + assoc_ident, assoc_kind: assoc_kind_str, qself: &qself_str, label: None, sugg: None, // Try to get the span of the identifier within the path's syntax context // (if that's different). - within_macro_span: assoc_name.span.within_macro(span, tcx.sess.source_map()), + within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()), }; if is_dummy { @@ -169,10 +173,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect(); if let Some(suggested_name) = - find_best_match_for_name(&all_candidate_names, assoc_name.name, None) + find_best_match_for_name(&all_candidate_names, assoc_ident.name, None) { err.sugg = Some(errors::AssocItemNotFoundSugg::Similar { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, suggested_name, }); @@ -201,7 +205,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect(); if let Some(suggested_name) = - find_best_match_for_name(&wider_candidate_names, assoc_name.name, None) + find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None) { if let [best_trait] = visible_traits .iter() @@ -215,11 +219,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { let trait_name = tcx.def_path_str(best_trait); err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, trait_name: &trait_name, suggested_name, - identically_named: suggested_name == assoc_name.name, + identically_named: suggested_name == assoc_ident.name, }); if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself // Not using `self.item_def_id()` here as that would yield the opaque type itself if we're @@ -246,7 +250,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // The type param already has a bound for `trait_name`, we just need to // change the associated item. err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, suggested_name, }); @@ -265,7 +269,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MaybeIncorrect }; - let identically_named = suggested_name == assoc_name.name; + let identically_named = suggested_name == assoc_ident.name; if let DefKind::TyAlias = tcx.def_kind(item_def_id) && !tcx.type_alias_is_lazy(item_def_id) @@ -273,7 +277,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath { lo: ty_param_span.shrink_to_lo(), mi: ty_param_span.shrink_to_hi(), - hi: (!identically_named).then_some(assoc_name.span), + hi: (!identically_named).then_some(assoc_ident.span), trait_ref, identically_named, suggested_name, @@ -294,7 +298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We suggested constraining a type parameter, but the associated item on it // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( - assoc_name.span, + assoc_ident.span, fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, suggested_name, Applicability::MaybeIncorrect, @@ -311,13 +315,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // suggest using it. if let [candidate_name] = all_candidate_names.as_slice() { err.sugg = Some(errors::AssocItemNotFoundSugg::Other { - span: assoc_name.span, + span: assoc_ident.span, qself: &qself_str, assoc_kind: assoc_kind_str, suggested_name: *candidate_name, }); } else { - err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_name.span }); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_ident.span }); } self.dcx().emit_err(err) @@ -805,7 +809,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return None; }; - let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( + let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind( tcx, ident, ty::AssocKind::Type, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index b4a71edc118..83aa0d95620 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -147,7 +147,7 @@ pub trait HirTyLowerer<'tcx> { &self, span: Span, def_id: LocalDefId, - assoc_name: Ident, + assoc_ident: Ident, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>; /// Lower an associated type/const (from a trait) to a projection. @@ -933,11 +933,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, trait_def_id: DefId, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, ) -> bool { self.tcx() .associated_items(trait_def_id) - .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id) + .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_kind, trait_def_id) .is_some() } @@ -964,7 +964,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Search for a trait bound on a type parameter whose trait defines the associated item - /// given by `assoc_name` and `kind`. + /// given by `assoc_ident` and `kind`. /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. @@ -976,13 +976,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty_param_def_id: LocalDefId, ty_param_span: Span, kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> { - debug!(?ty_param_def_id, ?assoc_name, ?span); + debug!(?ty_param_def_id, ?assoc_ident, ?span); let tcx = self.tcx(); - let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name); + let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_ident); debug!("predicates={:#?}", predicates); self.probe_single_bound_for_assoc_item( @@ -990,17 +990,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_refs = predicates .iter_identity_copied() .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))); - traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name) + traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident) }, AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span), kind, - assoc_name, + assoc_ident, span, None, ) } - /// Search for a single trait bound whose trait defines the associated item given by `assoc_name`. + /// Search for a single trait bound whose trait defines the associated item given by + /// `assoc_ident`. /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. @@ -1010,7 +1011,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates: impl Fn() -> I, qself: AssocItemQSelf, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> @@ -1020,7 +1021,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let mut matching_candidates = all_candidates().filter(|r| { - self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_name) + self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_ident) }); let Some(bound) = matching_candidates.next() else { @@ -1028,7 +1029,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates, qself, assoc_kind, - assoc_name, + assoc_ident, span, constraint, ); @@ -1044,7 +1045,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { span, assoc_kind: assoc_kind_str, - assoc_name, + assoc_ident, qself: &qself_str, }); // Provide a more specific error code index entry for equality bindings. @@ -1065,13 +1066,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_id = bound.def_id(); let bound_span = tcx .associated_items(bound_id) - .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) + .find_by_ident_and_kind(tcx, assoc_ident, assoc_kind, bound_id) .and_then(|item| tcx.hir_span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( bound_span, - format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), + format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),), ); if let Some(constraint) = constraint { match constraint.kind { @@ -1087,7 +1088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // FIXME(#97583): This isn't syntactically well-formed! where_bounds.push(format!( - " T: {trait}::{assoc_name} = {term}", + " T: {trait}::{assoc_ident} = {term}", trait = bound.print_only_trait_path(), )); } @@ -1096,7 +1097,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } else { err.span_suggestion_verbose( - span.with_hi(assoc_name.span.lo()), + span.with_hi(assoc_ident.span.lo()), "use fully-qualified syntax to disambiguate", format!("<{qself_str} as {}>::", bound.print_only_trait_path()), Applicability::MaybeIncorrect, @@ -1104,7 +1105,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } else { err.note(format!( - "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", + "associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`", bound.print_only_trait_path(), )); } @@ -2858,7 +2859,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty)); - let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( + let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind( tcx, *ident, ty::AssocKind::Fn, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 865209b6a96..e5ab317685f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -397,7 +397,7 @@ impl<'a> State<'a> { self.pclose(); } hir::TyKind::BareFn(f) => { - self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names); + self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_idents); } hir::TyKind::UnsafeBinder(unsafe_binder) => { self.print_unsafe_binder(unsafe_binder); @@ -473,14 +473,14 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_attrs_as_outer(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(sig, arg_names, generics) => { + hir::ForeignItemKind::Fn(sig, arg_idents, generics) => { self.head(""); self.print_fn( sig.decl, sig.header, Some(item.ident.name), generics, - arg_names, + arg_idents, None, ); self.end(); // end head-ibox @@ -899,10 +899,10 @@ impl<'a> State<'a> { ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, - arg_names: &[Option<Ident>], + arg_idents: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { - self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); + self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_idents, body_id); } fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -914,8 +914,8 @@ impl<'a> State<'a> { hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => { - self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { + self.print_method_sig(ti.ident, sig, ti.generics, arg_idents, None); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { @@ -2122,7 +2122,7 @@ impl<'a> State<'a> { header: hir::FnHeader, name: Option<Symbol>, generics: &hir::Generics<'_>, - arg_names: &[Option<Ident>], + arg_idents: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { self.print_fn_header_info(header); @@ -2134,16 +2134,16 @@ impl<'a> State<'a> { self.print_generic_params(generics.params); self.popen(); - // Make sure we aren't supplied *both* `arg_names` and `body_id`. - assert!(arg_names.is_empty() || body_id.is_none()); + // Make sure we aren't supplied *both* `arg_idents` and `body_id`. + assert!(arg_idents.is_empty() || body_id.is_none()); let mut i = 0; let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| { if i == 0 && decl.implicit_self.has_implicit_self() { s.print_implicit_self(&decl.implicit_self); } else { - if let Some(arg_name) = arg_names.get(i) { - if let Some(arg_name) = arg_name { - s.word(arg_name.to_string()); + if let Some(arg_ident) = arg_idents.get(i) { + if let Some(arg_ident) = arg_ident { + s.word(arg_ident.to_string()); s.word(":"); s.space(); } @@ -2452,7 +2452,7 @@ impl<'a> State<'a> { decl: &hir::FnDecl<'_>, name: Option<Symbol>, generic_params: &[hir::GenericParam<'_>], - arg_names: &[Option<Ident>], + arg_idents: &[Option<Ident>], ) { self.ibox(INDENT_UNIT); self.print_formal_generic_params(generic_params); @@ -2467,7 +2467,7 @@ impl<'a> State<'a> { }, name, generics, - arg_names, + arg_idents, None, ); self.end(); diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 872861d6289..9e1b70f5767 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -148,7 +148,7 @@ hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback af hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access .help = specify the type explicitly -hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> +hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> [true] {""} *[other] {" "}in the current scope } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index b73cd26927a..dfaa374592b 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -727,7 +727,7 @@ pub(crate) struct NoAssociatedItem { #[primary_span] pub span: Span, pub item_kind: &'static str, - pub item_name: Ident, + pub item_ident: Ident, pub ty_prefix: Cow<'static, str>, pub ty_str: String, pub trait_missing_method: bool, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3475d15e948..de2f039cb1c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2920,8 +2920,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // We failed to check the expression, report an error. - // Emits an error if we deref an infer variable, like calling `.field` on a base type of &_. - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + // Emits an error if we deref an infer variable, like calling `.field` on a base type + // of `&_`. We can also use this to suppress unnecessary "missing field" errors that + // will follow ambiguity errors. + let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + if let ty::Error(_) = final_ty.kind() { + return final_ty; + } if let Some((adjustments, did)) = private_candidate { // (#90483) apply adjustments to avoid ExprUseVisitor from diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f4bd7ec701f..81eb8510785 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1136,7 +1136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize && let Some(Some(arg)) = - self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit) + self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit) && arg.name != kw::SelfLower { format!("/* {} */", arg.name) @@ -2619,7 +2619,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_method: bool, ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)> { - let (sig, generics, body_id, param_names) = match self.tcx.hir_get_if_local(def_id)? { + let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? { hir::Node::TraitItem(&hir::TraitItem { generics, kind: hir::TraitItemKind::Fn(sig, trait_fn), @@ -2661,7 +2661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }); - match (body_id, param_names) { + match (body_id, params) { (Some(_), Some(_)) | (None, None) => unreachable!(), (Some(body), None) => { let params = self.tcx.hir_body(body).params; @@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); Some(( - fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(), + fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(), generics, )) } @@ -2709,14 +2709,14 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { #[derive(Clone, Copy)] enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), - Name(Option<Ident>), + Ident(Option<Ident>), } impl FnParam<'_> { fn span(&self) -> Span { match self { Self::Param(param) => param.span, - Self::Name(ident) => { + Self::Ident(ident) => { if let Some(ident) = ident { ident.span } else { @@ -2738,7 +2738,7 @@ impl FnParam<'_> { { Some(ident.name) } - FnParam::Name(ident) + FnParam::Ident(ident) if let Some(ident) = ident && ident.name != kw::Underscore => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 4008021c3a8..ddfd27ccf6b 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -534,12 +534,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok((def_kind, pick.item.def_id)) } - /// Finds item with name `item_name` defined in impl/trait `def_id` + /// Finds item with name `item_ident` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option<ty::AssocItem> { + fn associated_value(&self, def_id: DefId, item_ident: Ident) -> Option<ty::AssocItem> { self.tcx .associated_items(def_id) - .find_by_name_and_namespace(self.tcx, item_name, Namespace::ValueNS, def_id) + .find_by_ident_and_namespace(self.tcx, item_ident, Namespace::ValueNS, def_id) .copied() } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8be4d55542d..68f13d654d6 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -585,7 +585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, mut span: Span, rcvr_ty: Ty<'tcx>, - item_name: Ident, + item_ident: Ident, expr_id: hir::HirId, source: SelfSource<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, @@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if rcvr_ty.is_enum() { "variant or associated item" } else { - match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { + match (item_ident.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { (Some(name), false) if name.is_lowercase() => "function or associated item", (Some(_), false) => "associated item", (Some(_), true) | (None, false) => "variant or associated item", @@ -631,7 +631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty, source, span, - item_name, + item_ident, &short_ty_str, &mut ty_file, ) { @@ -643,13 +643,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, span, item_kind, - item_name, + item_ident, &short_ty_str, &mut ty_file, ) { return guar; } - span = item_name.span; + span = item_ident.span; // Don't show generic arguments when the method can't be found in any implementation (#81576). let mut ty_str_reported = ty_str.clone(); @@ -661,7 +661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx .inherent_impls(adt_def.did()) .into_iter() - .any(|def_id| self.associated_value(*def_id, item_name).is_some()) + .any(|def_id| self.associated_value(*def_id, item_ident).is_some()) } else { false } @@ -678,14 +678,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) - }) && item_name.name == sym::write_fmt; + }) && item_ident.name == sym::write_fmt; let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { let mut err = self.dcx().create_err(NoAssociatedItem { span, item_kind, - item_name, + item_ident, ty_prefix: if trait_missing_method { // FIXME(mu001999) E0599 maybe not suitable here because it is for types Cow::from("trait") @@ -699,7 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_method { self.suggest_use_shadowed_binding_with_method( source, - item_name, + item_ident, &ty_str_reported, &mut err, ); @@ -710,9 +710,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id) - && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind( + && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( self.tcx, - item_name, + item_ident, ty::AssocKind::Type, impl_def_id, ) @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let def_path = tcx.def_path_str(adt_def.did()); err.span_suggestion( - ty.span.to(item_name.span), + ty.span.to(item_ident.span), format!("to construct a value of type `{}`, use the explicit path", def_path), def_path, Applicability::MachineApplicable, @@ -750,7 +750,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.find_builder_fn(&mut err, rcvr_ty, expr_id); } - if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { + if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll { err.help(format!( "method `poll` found on `Pin<&mut {ty_str}>`, \ see documentation for `std::pin::Pin`" @@ -765,7 +765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { self.suggest_await_before_method( &mut err, - item_name, + item_ident, rcvr_ty, cal, span, @@ -787,7 +787,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(rcvr_expr) = source && let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind() && let Ok(pick) = self.lookup_probe_for_diagnostic( - item_name, + item_ident, Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl), self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)), ProbeScope::TraitsInScope, @@ -808,7 +808,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; err.span_note( tcx.def_span(pick.item.def_id), - format!("the method `{item_name}` exists on the type `{ty}`", ty = pick.self_ty), + format!("the method `{item_ident}` exists on the type `{ty}`", ty = pick.self_ty), ); let mut_str = ptr_mutbl.ptr_str(); err.note(format!( @@ -834,7 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)); let probe = self.lookup_probe_for_diagnostic( - item_name, + item_ident, output_ty, call_expr, ProbeScope::AllTraits, @@ -873,13 +873,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { static_candidates, rcvr_ty, source, - item_name, + item_ident, args, sugg_span, ); self.note_candidates_on_method_error( rcvr_ty, - item_name, + item_ident, source, args, span, @@ -890,7 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if static_candidates.len() > 1 { self.note_candidates_on_method_error( rcvr_ty, - item_name, + item_ident, source, args, span, @@ -904,7 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut restrict_type_params = false; let mut suggested_derive = false; let mut unsatisfied_bounds = false; - if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { + if item_ident.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; if let SelfSource::MethodCall(_expr) = source { err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable); @@ -1349,7 +1349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let primary_message = primary_message.unwrap_or_else(|| { format!( - "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \ + "the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \ but its trait bounds were not satisfied" ) }); @@ -1379,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `Pin<&Self>`. if targs.len() == 1 { let mut item_segment = hir::PathSegment::invalid(); - item_segment.ident = item_name; + item_segment.ident = item_ident; for t in [Ty::new_mut_ref, Ty::new_imm_ref, |_, _, t| t] { let new_args = tcx.mk_args_from_iter(targs.iter().map(|arg| match arg.as_type() { @@ -1423,9 +1423,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String), _ => false, }; - if is_string_or_ref_str && item_name.name == sym::iter { + if is_string_or_ref_str && item_ident.name == sym::iter { err.span_suggestion_verbose( - item_name.span, + item_ident.span, "because of the in-memory representation of `&str`, to obtain \ an `Iterator` over each of its codepoint use method `chars`", "chars", @@ -1439,7 +1439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .copied() .filter(|def_id| { - if let Some(assoc) = self.associated_value(*def_id, item_name) { + if let Some(assoc) = self.associated_value(*def_id, item_ident) { // Check for both mode is the same so we avoid suggesting // incorrect associated item. match (mode, assoc.fn_has_self_parameter, source) { @@ -1500,7 +1500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. if let SelfSource::MethodCall(expr) = source { - if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err) + if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_ident, &mut err) && similar_candidate.is_none() && !custom_span_label { @@ -1513,7 +1513,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let confusable_suggested = self.confusable_method_name( &mut err, rcvr_ty, - item_name, + item_ident, args.map(|args| { args.iter() .map(|expr| { @@ -1531,12 +1531,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, span, rcvr_ty, - item_name, + item_ident, expected.only_has_type(self), ); } - self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name); + self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_ident); for (span, mut bounds) in bound_spans { if !tcx.sess.source_map().is_span_accessible(span) { @@ -1547,7 +1547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let pre = if Some(span) == ty_span { ty_span.take(); format!( - "{item_kind} `{item_name}` not found for this {} because it ", + "{item_kind} `{item_ident}` not found for this {} because it ", rcvr_ty.prefix_string(self.tcx) ) } else { @@ -1567,7 +1567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( span, format!( - "{item_kind} `{item_name}` not found for this {}", + "{item_kind} `{item_ident}` not found for this {}", rcvr_ty.prefix_string(self.tcx) ), ); @@ -1579,7 +1579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, span, rcvr_ty, - item_name, + item_ident, args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), @@ -1596,7 +1596,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(var_name) = edit_distance::find_best_match_for_name( &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(), - item_name.name, + item_ident.name, None, ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == var_name) { @@ -1737,14 +1737,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !find_candidate_for_method { self.lookup_segments_chain_for_no_match_method( &mut err, - item_name, + item_ident, item_kind, source, no_match_data, ); } - self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); + self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected); err.emit() } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8641348bffb..fbc783c0509 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { enum AdjustMode { /// Peel off all immediate reference types. Peel, - /// Reset binding mode to the initial mode. - /// Used for destructuring assignment, where we don't want any match ergonomics. - Reset, /// Pass on the input binding mode and expected type. Pass, } @@ -321,77 +318,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Conversely, inside this module, `check_pat_top` should never be used. #[instrument(level = "debug", skip(self, pat_info))] fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) { - let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; - - let path_res = match pat.kind { + let opt_path_res = match pat.kind { PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span)) } _ => None, }; - let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); - let (expected, binding_mode, max_ref_mutbl) = - self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl); - let pat_info = PatInfo { - binding_mode, - max_ref_mutbl, - top_info: ti, - decl_origin: pat_info.decl_origin, - current_depth: current_depth + 1, - }; - - let ty = match pat.kind { - PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, - // We allow any type here; we ensure that the type is uninhabited during match checking. - PatKind::Never => expected, - PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - let ty = self.check_pat_path( - *hir_id, - pat.hir_id, - *span, - qpath, - path_res.unwrap(), - expected, - &pat_info.top_info, - ); - self.write_ty(*hir_id, ty); - ty - } - PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info), - PatKind::Range(lhs, rhs, _) => { - self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info) - } - PatKind::Binding(ba, var_id, ident, sub) => { - self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) - } - PatKind::TupleStruct(ref qpath, subpats, ddpos) => { - self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) - } - PatKind::Struct(ref qpath, fields, has_rest_pat) => { - self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) - } - PatKind::Guard(pat, cond) => { - self.check_pat(pat, expected, pat_info); - self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {}); - expected - } - PatKind::Or(pats) => { - for pat in pats { - self.check_pat(pat, expected, pat_info); - } - expected - } - PatKind::Tuple(elements, ddpos) => { - self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info) - } - PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info), - PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info), - PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info), - PatKind::Slice(before, slice, after) => { - self.check_pat_slice(pat.span, before, slice, after, expected, pat_info) - } - }; - + let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res)); + let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); self.write_ty(pat.hir_id, ty); // (note_1): In most of the cases where (note_1) is referenced @@ -437,27 +371,126 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, } - /// Compute the new expected type and default binding mode from the old ones - /// as well as the pattern form we are currently checking. - fn calc_default_binding_mode( + // Helper to avoid resolving the same path pattern several times. + fn check_pat_inner( &self, pat: &'tcx Pat<'tcx>, - expected: Ty<'tcx>, - def_br: ByRef, + opt_path_res: Option<(Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>])>, adjust_mode: AdjustMode, - max_ref_mutbl: MutblCap, - ) -> (Ty<'tcx>, ByRef, MutblCap) { + expected: Ty<'tcx>, + pat_info: PatInfo<'tcx>, + ) -> Ty<'tcx> { #[cfg(debug_assertions)] - if def_br == ByRef::Yes(Mutability::Mut) - && max_ref_mutbl != MutblCap::Mut + if pat_info.binding_mode == ByRef::Yes(Mutability::Mut) + && pat_info.max_ref_mutbl != MutblCap::Mut && self.downgrade_mut_inside_shared() { span_bug!(pat.span, "Pattern mutability cap violated!"); } - match adjust_mode { - AdjustMode::Pass => (expected, def_br, max_ref_mutbl), - AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut), - AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl), + + // Resolve type if needed. + let expected = if let AdjustMode::Peel = adjust_mode + && pat.default_binding_modes + { + self.try_structurally_resolve_type(pat.span, expected) + } else { + expected + }; + let old_pat_info = pat_info; + let pat_info = PatInfo { current_depth: old_pat_info.current_depth + 1, ..old_pat_info }; + + match pat.kind { + // Peel off a `&` or `&mut` from the scrutinee type. See the examples in + // `tests/ui/rfcs/rfc-2005-default-binding-mode`. + _ if let AdjustMode::Peel = adjust_mode + && pat.default_binding_modes + && let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() => + { + debug!("inspecting {:?}", expected); + + debug!("current discriminant is Ref, inserting implicit deref"); + // Preserve the reference type. We'll need it later during THIR lowering. + self.typeck_results + .borrow_mut() + .pat_adjustments_mut() + .entry(pat.hir_id) + .or_default() + .push(expected); + + let mut binding_mode = ByRef::Yes(match pat_info.binding_mode { + // If default binding mode is by value, make it `ref` or `ref mut` + // (depending on whether we observe `&` or `&mut`). + ByRef::No | + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). + ByRef::Yes(Mutability::Mut) => inner_mutability, + // Once a `ref`, always a `ref`. + // This is because a `& &mut` cannot mutate the underlying value. + ByRef::Yes(Mutability::Not) => Mutability::Not, + }); + + let mut max_ref_mutbl = pat_info.max_ref_mutbl; + if self.downgrade_mut_inside_shared() { + binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); + } + if binding_mode == ByRef::Yes(Mutability::Not) { + max_ref_mutbl = MutblCap::Not; + } + debug!("default binding mode is now {:?}", binding_mode); + + // Use the old pat info to keep `current_depth` to its old value. + let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info }; + // Recurse with the new expected type. + self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info) + } + PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, + // We allow any type here; we ensure that the type is uninhabited during match checking. + PatKind::Never => expected, + PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { + let ty = self.check_pat_path( + *hir_id, + pat.hir_id, + *span, + qpath, + opt_path_res.unwrap(), + expected, + &pat_info.top_info, + ); + self.write_ty(*hir_id, ty); + ty + } + PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info), + PatKind::Range(lhs, rhs, _) => { + self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info) + } + PatKind::Binding(ba, var_id, ident, sub) => { + self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) + } + PatKind::TupleStruct(ref qpath, subpats, ddpos) => { + self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) + } + PatKind::Struct(ref qpath, fields, has_rest_pat) => { + self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) + } + PatKind::Guard(pat, cond) => { + self.check_pat(pat, expected, pat_info); + self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {}); + expected + } + PatKind::Or(pats) => { + for pat in pats { + self.check_pat(pat, expected, pat_info); + } + expected + } + PatKind::Tuple(elements, ddpos) => { + self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info) + } + PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info), + PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info), + PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info), + PatKind::Slice(before, slice, after) => { + self.check_pat_slice(pat.span, before, slice, after, expected, pat_info) + } } } @@ -465,11 +498,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode { - // When we perform destructuring assignment, we disable default match bindings, which are - // unintuitive in this context. - if !pat.default_binding_modes { - return AdjustMode::Reset; - } match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. @@ -526,64 +554,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Peel off as many immediately nested `& mut?` from the expected type as possible - /// and return the new expected type and binding default binding mode. - /// The adjustments vector, if non-empty is stored in a table. - fn peel_off_references( - &self, - pat: &'tcx Pat<'tcx>, - expected: Ty<'tcx>, - mut def_br: ByRef, - mut max_ref_mutbl: MutblCap, - ) -> (Ty<'tcx>, ByRef, MutblCap) { - let mut expected = self.try_structurally_resolve_type(pat.span, expected); - // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, - // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type Ref. - // - // For each ampersand peeled off, update the binding mode and push the original - // type into the adjustments vector. - // - // See the examples in `ui/match-defbm*.rs`. - let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { - debug!("inspecting {:?}", expected); - - debug!("current discriminant is Ref, inserting implicit deref"); - // Preserve the reference type. We'll need it later during THIR lowering. - pat_adjustments.push(expected); - - expected = self.try_structurally_resolve_type(pat.span, inner_ty); - def_br = ByRef::Yes(match def_br { - // If default binding mode is by value, make it `ref` or `ref mut` - // (depending on whether we observe `&` or `&mut`). - ByRef::No | - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). - ByRef::Yes(Mutability::Mut) => inner_mutability, - // Once a `ref`, always a `ref`. - // This is because a `& &mut` cannot mutate the underlying value. - ByRef::Yes(Mutability::Not) => Mutability::Not, - }); - } - - if self.downgrade_mut_inside_shared() { - def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl()); - } - if def_br == ByRef::Yes(Mutability::Not) { - max_ref_mutbl = MutblCap::Not; - } - - if !pat_adjustments.is_empty() { - debug!("default binding mode is now {:?}", def_br); - self.typeck_results - .borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } - - (expected, def_br, max_ref_mutbl) - } - fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { let ty = match <.kind { rustc_hir::PatExprKind::Lit { lit, negated } => { diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e3673935664..ff28dbeaee6 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-rayon = { version = "0.5.0" } rustc-rayon-core = { version = "0.5.0" } rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 33b4a48b28d..708fe23b791 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -348,6 +348,10 @@ pub struct Config { /// the list of queries. pub override_queries: Option<fn(&Session, &mut Providers)>, + /// An extra set of symbols to add to the symbol interner, the symbol indices + /// will start at [`PREDEFINED_SYMBOLS_COUNT`](rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT) + pub extra_symbols: Vec<&'static str>, + /// This is a callback from the driver that is called to create a codegen backend. /// /// Has no uses within this repository, but is used by bjorn3 for "the @@ -409,6 +413,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se &early_dcx, config.opts.edition, config.opts.unstable_opts.threads, + &config.extra_symbols, SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind }, |current_gcx| { // The previous `early_dcx` can't be reused here because it doesn't diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7dfad165836..fde1872fb39 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -800,6 +800,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>( sess.opts.cg.metadata.clone(), sess.cfg_version, ); + let outputs = util::build_output_filenames(&pre_configured_attrs, sess); let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() }; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a8e55663257..75a1b61b416 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -53,7 +53,7 @@ where checksum_hash_kind, }); - rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || { + rustc_span::create_session_globals_then(DEFAULT_EDITION, &[], sm_inputs, || { let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 83d80938b4e..c3a939f1ab0 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -117,6 +117,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( thread_stack_size: usize, edition: Edition, sm_inputs: SourceMapInputs, + extra_symbols: &[&'static str], f: F, ) -> R { // The "thread pool" is a single spawned thread in the non-parallel @@ -134,9 +135,12 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>( // name contains null bytes. let r = builder .spawn_scoped(s, move || { - rustc_span::create_session_globals_then(edition, Some(sm_inputs), || { - f(CurrentGcx::new()) - }) + rustc_span::create_session_globals_then( + edition, + extra_symbols, + Some(sm_inputs), + || f(CurrentGcx::new()), + ) }) .unwrap() .join(); @@ -152,6 +156,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, thread_builder_diag: &EarlyDiagCtxt, edition: Edition, threads: usize, + extra_symbols: &[&'static str], sm_inputs: SourceMapInputs, f: F, ) -> R { @@ -168,18 +173,24 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap()); if !sync::is_dyn_thread_safe() { - return run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, |current_gcx| { - // Register the thread for use with the `WorkerLocal` type. - registry.register(); - - f(current_gcx) - }); + return run_in_thread_with_globals( + thread_stack_size, + edition, + sm_inputs, + extra_symbols, + |current_gcx| { + // Register the thread for use with the `WorkerLocal` type. + registry.register(); + + f(current_gcx) + }, + ); } let current_gcx = FromDyn::from(CurrentGcx::new()); let current_gcx2 = current_gcx.clone(); - let builder = rayon::ThreadPoolBuilder::new() + let builder = rayon_core::ThreadPoolBuilder::new() .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) .release_thread_handler(jobserver::release_thread) @@ -230,13 +241,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, // pool. Upon creation, each worker thread created gets a copy of the // session globals in TLS. This is possible because `SessionGlobals` impls // `Send` in the parallel compiler. - rustc_span::create_session_globals_then(edition, Some(sm_inputs), || { + rustc_span::create_session_globals_then(edition, extra_symbols, Some(sm_inputs), || { rustc_span::with_session_globals(|session_globals| { let session_globals = FromDyn::from(session_globals); builder .build_scoped( // Initialize each new worker thread when created. - move |thread: rayon::ThreadBuilder| { + move |thread: rayon_core::ThreadBuilder| { // Register the thread for use with the `WorkerLocal` type. registry.register(); @@ -245,7 +256,9 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, }) }, // Run `f` on the first thread in the thread pool. - move |pool: &rayon::ThreadPool| pool.install(|| f(current_gcx.into_inner())), + move |pool: &rayon_core::ThreadPool| { + pool.install(|| f(current_gcx.into_inner())) + }, ) .unwrap() }) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 885a7308bdc..16c9e08c78d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -859,7 +859,7 @@ impl<'tcx> LateContext<'tcx> { ) -> Option<Ty<'tcx>> { let tcx = self.tcx; tcx.associated_items(trait_id) - .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) + .find_by_ident_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index df567e80e55..a3e7c84584d 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -423,11 +423,11 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(param_idents)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); - for param_name in pnames { - if let Some(param_name) = param_name { - self.check_snake_case(cx, "variable", param_name); + for param_ident in param_idents { + if let Some(param_ident) = param_ident { + self.check_snake_case(cx, "variable", param_ident); } } } diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 37200f62eb5..0400de62274 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -142,13 +142,13 @@ pub(super) fn symbols(input: TokenStream) -> TokenStream { output } -struct Preinterned { +struct Predefined { idx: u32, span_of_name: Span, } struct Entries { - map: HashMap<String, Preinterned>, + map: HashMap<String, Predefined>, } impl Entries { @@ -163,7 +163,7 @@ impl Entries { prev.idx } else { let idx = self.len(); - self.map.insert(s.to_string(), Preinterned { idx, span_of_name: span }); + self.map.insert(s.to_string(), Predefined { idx, span_of_name: span }); idx } } @@ -295,10 +295,14 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) { } let symbol_digits_base = entries.map["0"].idx; - let preinterned_symbols_count = entries.len(); + let predefined_symbols_count = entries.len(); let output = quote! { const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base; - const PREINTERNED_SYMBOLS_COUNT: u32 = #preinterned_symbols_count; + + /// The number of predefined symbols; this is the the first index for + /// extra pre-interned symbols in an Interner created via + /// [`Interner::with_extra_symbols`]. + pub const PREDEFINED_SYMBOLS_COUNT: u32 = #predefined_symbols_count; #[doc(hidden)] #[allow(non_upper_case_globals)] @@ -315,10 +319,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) { } impl Interner { - pub(crate) fn fresh() -> Self { - Interner::prefill(&[ - #prefill_stream - ]) + /// Creates an `Interner` with the predefined symbols from the `symbols!` macro and + /// any extra symbols provided by external drivers such as Clippy + pub(crate) fn with_extra_symbols(extra_symbols: &[&'static str]) -> Self { + Interner::prefill( + &[#prefill_stream], + extra_symbols, + ) } } }; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4610a571da0..4cc12ca2e0b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -562,9 +562,9 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> { Symbol::intern(s) }) } - SYMBOL_PREINTERNED => { + SYMBOL_PREDEFINED => { let symbol_index = self.read_u32(); - Symbol::new_from_decoded(symbol_index) + Symbol::new(symbol_index) } _ => unreachable!(), } @@ -1313,7 +1313,7 @@ impl<'a> CrateMetadataRef<'a> { fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { self.root .tables - .fn_arg_names + .fn_arg_idents .get(self, id) .expect("argument names not encoded for a function") .decode((self, sess)) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 3dc82ce9d18..ecc2dcc5318 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -286,7 +286,7 @@ provide! { tcx, def_id, other, cdata, rendered_const => { table } rendered_precise_capturing_args => { table } asyncness => { table_direct } - fn_arg_names => { table } + fn_arg_idents => { table } coroutine_kind => { table_direct } coroutine_for_closure => { table } coroutine_by_move_body_def_id => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 55bb984c5b6..5c8e2888ec9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -201,9 +201,9 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } fn encode_symbol(&mut self, symbol: Symbol) { - // if symbol preinterned, emit tag and symbol index - if symbol.is_preinterned() { - self.opaque.emit_u8(SYMBOL_PREINTERNED); + // if symbol predefined, emit tag and symbol index + if symbol.is_predefined() { + self.opaque.emit_u8(SYMBOL_PREDEFINED); self.opaque.emit_u32(symbol.as_u32()); } else { // otherwise write it as string or as offset to it @@ -1469,7 +1469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Fn | DefKind::AssocFn = def_kind { self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id)); - record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id)); + record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); } if let Some(name) = tcx.intrinsic(def_id) { record!(self.tables.intrinsic[def_id] <- name); @@ -2199,7 +2199,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { } let reachable_set = tcx.reachable_set(()); - par_for_each_in(tcx.mir_keys(()), |&def_id| { + par_for_each_in(tcx.mir_keys(()), |&&def_id| { let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id); if encode_const { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 96a1f65eeb0..2f27e5f6c5d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -451,7 +451,7 @@ define_tables! { rendered_const: Table<DefIndex, LazyValue<String>>, rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>, asyncness: Table<DefIndex, ty::Asyncness>, - fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>, + fn_arg_idents: Table<DefIndex, LazyArray<Option<Ident>>>, coroutine_kind: Table<DefIndex, hir::CoroutineKind>, coroutine_for_closure: Table<DefIndex, RawDefId>, adt_destructor: Table<DefIndex, LazyValue<ty::Destructor>>, @@ -586,7 +586,7 @@ impl SpanTag { // Tags for encoding Symbol's const SYMBOL_STR: u8 = 0; const SYMBOL_OFFSET: u8 = 1; -const SYMBOL_PREINTERNED: u8 = 2; +const SYMBOL_PREDEFINED: u8 = 2; pub fn provide(providers: &mut Providers) { encoder::provide(providers); diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 21ab06c98a7..daf95420c43 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -281,7 +281,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> { + pub fn hir_body_param_idents(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> { self.hir_body(id).params.iter().map(|param| match param.pat.kind { PatKind::Binding(_, _, ident, _) => Some(ident), PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)), @@ -343,7 +343,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) { - par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); + par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&&def_id| f(def_id)); } pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId { diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 74369b6636c..640ac70d3a7 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -83,35 +83,35 @@ impl ModuleItems { &self, f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.free_items[..], |&id| f(id)) + try_par_for_each_in(&self.free_items[..], |&&id| f(id)) } pub fn par_trait_items( &self, f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.trait_items[..], |&id| f(id)) + try_par_for_each_in(&self.trait_items[..], |&&id| f(id)) } pub fn par_impl_items( &self, f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.impl_items[..], |&id| f(id)) + try_par_for_each_in(&self.impl_items[..], |&&id| f(id)) } pub fn par_foreign_items( &self, f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.foreign_items[..], |&id| f(id)) + try_par_for_each_in(&self.foreign_items[..], |&&id| f(id)) } pub fn par_opaques( &self, f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.opaques[..], |&id| f(id)) + try_par_for_each_in(&self.opaques[..], |&&id| f(id)) } } @@ -215,9 +215,9 @@ pub fn provide(providers: &mut Providers) { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir_opt_ident_span(hir_id) }; - providers.fn_arg_names = |tcx, def_id| { + providers.fn_arg_idents = |tcx, def_id| { if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() { - tcx.arena.alloc_from_iter(tcx.hir_body_param_names(body_id)) + tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. @@ -231,7 +231,7 @@ pub fn provide(providers: &mut Providers) { } else { span_bug!( tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)), - "fn_arg_names: unexpected item {:?}", + "fn_arg_idents: unexpected item {:?}", def_id ); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 40d0028db86..28a59d3e73e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1442,8 +1442,8 @@ rustc_queries! { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } - query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] { - desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } + query fn_arg_idents(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] { + desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } @@ -1900,6 +1900,11 @@ rustc_queries! { // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. + // + // The hash should not be calculated before the `analysis` pass is complete, specifically + // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental + // compilation is enabled calculating this hash can freeze this structure too early in + // compilation and cause subsequent crashes when attempting to write to `definitions` query crate_hash(_: CrateNum) -> Svh { eval_always desc { "looking up the hash a crate" } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index c6ecc679b7b..f78398c7c37 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -46,7 +46,7 @@ const TAG_EXPN_DATA: u8 = 1; // Tags for encoding Symbol's const SYMBOL_STR: u8 = 0; const SYMBOL_OFFSET: u8 = 1; -const SYMBOL_PREINTERNED: u8 = 2; +const SYMBOL_PREDEFINED: u8 = 2; /// Provides an interface to incremental compilation data cached from the /// previous compilation session. This data will eventually include the results @@ -674,9 +674,9 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { Symbol::intern(s) }) } - SYMBOL_PREINTERNED => { + SYMBOL_PREDEFINED => { let symbol_index = self.read_u32(); - Symbol::new_from_decoded(symbol_index) + Symbol::new(symbol_index) } _ => unreachable!(), } @@ -892,9 +892,9 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { // copy&paste impl from rustc_metadata fn encode_symbol(&mut self, symbol: Symbol) { - // if symbol preinterned, emit tag and symbol index - if symbol.is_preinterned() { - self.encoder.emit_u8(SYMBOL_PREINTERNED); + // if symbol predefined, emit tag and symbol index + if symbol.is_predefined() { + self.encoder.emit_u8(SYMBOL_PREDEFINED); self.encoder.emit_u32(symbol.as_u32()); } else { // otherwise write it as string or as offset to it diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index ce4c08aa485..bbaf735fbdb 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -98,10 +98,10 @@ impl AssocItem { pub fn descr(&self) -> &'static str { match self.kind { - ty::AssocKind::Const => "const", + ty::AssocKind::Const => "associated const", ty::AssocKind::Fn if self.fn_has_self_parameter => "method", ty::AssocKind::Fn => "associated function", - ty::AssocKind::Type => "type", + ty::AssocKind::Type => "associated type", } } @@ -155,6 +155,8 @@ impl AssocKind { impl std::fmt::Display for AssocKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + // FIXME: fails to distinguish between "associated function" and + // "method" because `has_self` isn't known here. AssocKind::Fn => write!(f, "method"), AssocKind::Const => write!(f, "associated const"), AssocKind::Type => write!(f, "associated type"), @@ -199,8 +201,9 @@ impl AssocItems { self.items.get_by_key(name) } - /// Returns the associated item with the given name and `AssocKind`, if one exists. - pub fn find_by_name_and_kind( + /// Returns the associated item with the given identifier and `AssocKind`, if one exists. + /// The identifier is matched hygienically. + pub fn find_by_ident_and_kind( &self, tcx: TyCtxt<'_>, ident: Ident, @@ -212,8 +215,9 @@ impl AssocItems { .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } - /// Returns the associated item with the given name and any of `AssocKind`, if one exists. - pub fn find_by_name_and_kinds( + /// Returns the associated item with the given identifier and any of `AssocKind`, if one + /// exists. The identifier is matched hygienically. + pub fn find_by_ident_and_kinds( &self, tcx: TyCtxt<'_>, ident: Ident, @@ -221,11 +225,12 @@ impl AssocItems { kinds: &[AssocKind], parent_def_id: DefId, ) -> Option<&ty::AssocItem> { - kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id)) + kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id)) } - /// Returns the associated item with the given name in the given `Namespace`, if one exists. - pub fn find_by_name_and_namespace( + /// Returns the associated item with the given identifier in the given `Namespace`, if one + /// exists. The identifier is matched hygienically. + pub fn find_by_ident_and_namespace( &self, tcx: TyCtxt<'_>, ident: Ident, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index a0e67929c52..5ecf1174def 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -279,7 +279,7 @@ impl<'tcx> TyCtxt<'tcx> { p.hash(&mut s); let hash = s.finish(); *path = Some(path.take().unwrap_or_else(|| { - self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None) + self.output_filenames(()).temp_path_for_diagnostic(&format!("long-type-{hash}.txt")) })); let Ok(mut file) = File::options().create(true).read(true).append(true).open(&path.as_ref().unwrap()) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 80f1bd7c6f4..a2b3acac3f2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1939,15 +1939,15 @@ impl<'tcx> TyCtxt<'tcx> { /// Hygienically compares a use-site name (`use_name`) for a field or an associated item with /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed /// definition's parent/scope to perform comparison. - pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { - // We could use `Ident::eq` here, but we deliberately don't. The name + pub fn hygienic_eq(self, use_ident: Ident, def_ident: Ident, def_parent_def_id: DefId) -> bool { + // We could use `Ident::eq` here, but we deliberately don't. The identifier // comparison fails frequently, and we want to avoid the expensive // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. - use_name.name == def_name.name - && use_name + use_ident.name == def_ident.name + && use_ident .span .ctxt() - .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id)) + .hygienic_eq(def_ident.span.ctxt(), self.expn_that_defined(def_parent_def_id)) } pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 5904deaaaad..9172c5d3ab7 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -382,7 +382,7 @@ pub fn shrunk_instance_name<'tcx>( return (s, None); } - let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None); + let path = tcx.output_filenames(()).temp_path_for_diagnostic("long-type.txt"); let written_to_path = std::fs::write(&path, s).ok().map(|_| path); (shrunk, written_to_path) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 667cc5c3f0e..2f93197bcef 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -620,7 +620,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // the children of the visible parent (as was done when computing // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. - DefPathData::TypeNs(Some(ref mut name)) if Some(visible_parent) != actual_parent => { + DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { // Item might be re-exported several times, but filter for the one // that's public and whose identifier isn't `_`. let reexport = self @@ -641,7 +641,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { - data = DefPathData::TypeNs(Some(self.tcx().crate_name(def_id.krate))); + data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate)); } _ => {} } diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index ce4208f2c44..561f84192b4 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -26,7 +26,7 @@ fn true_significant_drop_ty<'tcx>( name_rev.push(tcx.crate_name(did.krate)); } rustc_hir::definitions::DefPathData::TypeNs(symbol) => { - name_rev.push(symbol.unwrap()); + name_rev.push(symbol); } _ => return None, } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 2eff6b31372..a8d6aaa50a2 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -39,26 +39,26 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { - match statement.kind { - StatementKind::Assign(box (_place, ref mut rvalue)) => { - if !preserve_ub_checks { - ctx.simplify_ub_check(rvalue); - } - ctx.simplify_bool_cmp(rvalue); - ctx.simplify_ref_deref(rvalue); - ctx.simplify_ptr_aggregate(rvalue); - ctx.simplify_cast(rvalue); - ctx.simplify_repeated_aggregate(rvalue); - ctx.simplify_repeat_once(rvalue); - } - _ => {} + let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else { + continue; + }; + + if !preserve_ub_checks { + ctx.simplify_ub_check(rvalue); } + ctx.simplify_bool_cmp(rvalue); + ctx.simplify_ref_deref(rvalue); + ctx.simplify_ptr_aggregate(rvalue); + ctx.simplify_cast(rvalue); + ctx.simplify_repeated_aggregate(rvalue); + ctx.simplify_repeat_once(rvalue); } - ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements); - ctx.simplify_intrinsic_assert(block.terminator.as_mut().unwrap()); - ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); - simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); + let terminator = block.terminator.as_mut().unwrap(); + ctx.simplify_primitive_clone(terminator, &mut block.statements); + ctx.simplify_intrinsic_assert(terminator); + ctx.simplify_nounwind_call(terminator); + simplify_duplicate_switch_targets(terminator); } } @@ -105,43 +105,34 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { /// Transform boolean comparisons into logical operations. fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) { - match rvalue { - Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => { - let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { - // Transform "Eq(a, true)" ==> "a" - (BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())), + let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return }; + *rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { + // Transform "Eq(a, true)" ==> "a" + (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()), - // Transform "Ne(a, false)" ==> "a" - (BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())), + // Transform "Ne(a, false)" ==> "a" + (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()), - // Transform "Eq(true, b)" ==> "b" - (BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())), + // Transform "Eq(true, b)" ==> "b" + (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()), - // Transform "Ne(false, b)" ==> "b" - (BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())), + // Transform "Ne(false, b)" ==> "b" + (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()), - // Transform "Eq(false, b)" ==> "Not(b)" - (BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())), + // Transform "Eq(false, b)" ==> "Not(b)" + (BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()), - // Transform "Ne(true, b)" ==> "Not(b)" - (BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())), + // Transform "Ne(true, b)" ==> "Not(b)" + (BinOp::Ne, Some(true), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()), - // Transform "Eq(a, false)" ==> "Not(a)" - (BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())), + // Transform "Eq(a, false)" ==> "Not(a)" + (BinOp::Eq, _, Some(false)) => Rvalue::UnaryOp(UnOp::Not, a.clone()), - // Transform "Ne(a, true)" ==> "Not(a)" - (BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())), - - _ => None, - }; - - if let Some(new) = new { - *rvalue = new; - } - } + // Transform "Ne(a, true)" ==> "Not(a)" + (BinOp::Ne, _, Some(true)) => Rvalue::UnaryOp(UnOp::Not, a.clone()), - _ => {} - } + _ => return, + }; } fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> { @@ -151,64 +142,58 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { /// Transform `&(*a)` ==> `a`. fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue { - if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { - if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { - return; - } - - *rvalue = Rvalue::Use(Operand::Copy(Place { - local: base.local, - projection: self.tcx.mk_place_elems(base.projection), - })); - } + if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue + && let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() + && rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty + { + *rvalue = Rvalue::Use(Operand::Copy(Place { + local: base.local, + projection: self.tcx.mk_place_elems(base.projection), + })); } } /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`. fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue + && let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx) + && meta_ty.is_unit() { - let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx); - if meta_ty.is_unit() { - // The mutable borrows we're holding prevent printing `rvalue` here - let mut fields = std::mem::take(fields); - let _meta = fields.pop().unwrap(); - let data = fields.pop().unwrap(); - let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability); - *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty); - } + // The mutable borrows we're holding prevent printing `rvalue` here + let mut fields = std::mem::take(fields); + let _meta = fields.pop().unwrap(); + let data = fields.pop().unwrap(); + let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability); + *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty); } } fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue { - let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); - let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; - *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); - } + let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return }; + + let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); + let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; + *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Cast(kind, operand, cast_ty) = rvalue { - let operand_ty = operand.ty(self.local_decls, self.tcx); - if operand_ty == *cast_ty { - *rvalue = Rvalue::Use(operand.clone()); - } else if *kind == CastKind::Transmute { - // Transmuting an integer to another integer is just a signedness cast - if let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) = - (operand_ty.kind(), cast_ty.kind()) - && int.bit_width() == uint.bit_width() - { - // The width check isn't strictly necessary, as different widths - // are UB and thus we'd be allowed to turn it into a cast anyway. - // But let's keep the UB around for codegen to exploit later. - // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes, - // then the width check is necessary for big-endian correctness.) - *kind = CastKind::IntToInt; - return; - } - } + let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return }; + + let operand_ty = operand.ty(self.local_decls, self.tcx); + if operand_ty == *cast_ty { + *rvalue = Rvalue::Use(operand.clone()); + } else if *kind == CastKind::Transmute + // Transmuting an integer to another integer is just a signedness cast + && let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) = + (operand_ty.kind(), cast_ty.kind()) + && int.bit_width() == uint.bit_width() + { + // The width check isn't strictly necessary, as different widths + // are UB and thus we'd be allowed to turn it into a cast anyway. + // But let's keep the UB around for codegen to exploit later. + // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes, + // then the width check is necessary for big-endian correctness.) + *kind = CastKind::IntToInt; } } @@ -277,7 +262,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { - let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else { return; }; @@ -290,7 +275,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), ty::Closure(..) => ExternAbi::RustCall, ty::Coroutine(..) => ExternAbi::Rust, - _ => bug!("unexpected body ty: {:?}", body_ty), + _ => bug!("unexpected body ty: {body_ty:?}"), }; if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { @@ -299,10 +284,9 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) { - let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else { - return; - }; - let Some(target_block) = target else { + let TerminatorKind::Call { ref func, target: ref mut target @ Some(target_block), .. } = + terminator.kind + else { return; }; let func_ty = func.ty(self.local_decls, self.tcx); @@ -310,12 +294,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { return; }; // The intrinsics we are interested in have one generic parameter - if args.is_empty() { - return; - } + let [arg, ..] = args[..] else { return }; let known_is_valid = - intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env, arg, intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} @@ -325,7 +307,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } Some(false) => { // If we know the assert does not panic, turn the call into a Goto - terminator.kind = TerminatorKind::Goto { target: *target_block }; + terminator.kind = TerminatorKind::Goto { target: target_block }; } } } @@ -346,9 +328,7 @@ fn resolve_rust_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>, ) -> Option<(Symbol, GenericArgsRef<'tcx>)> { - if let ty::FnDef(def_id, args) = *func_ty.kind() { - let intrinsic = tcx.intrinsic(def_id)?; - return Some((intrinsic.name, args)); - } - None + let ty::FnDef(def_id, args) = *func_ty.kind() else { return None }; + let intrinsic = tcx.intrinsic(def_id)?; + Some((intrinsic.name, args)) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 6e676ac6b8d..1dbb35f92c2 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1689,7 +1689,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>( let mut recursion_depths = DefIdMap::default(); collect_items_rec( tcx, - dummy_spanned(root), + dummy_spanned(*root), &state, &mut recursion_depths, recursion_limit, diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index a484573f0d8..55d52d5075d 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -191,7 +191,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> { for impl_def_id in tcx.inherent_impls(def_id) { - if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind( + if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( tcx, fn_ident, AssocKind::Fn, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9c457f150a3..d52e36fcfac 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2166,10 +2166,15 @@ impl<'a> Parser<'a> { let expr = self .eat_metavar_seq(mv_kind, |this| this.parse_expr()) .expect("metavar seq expr"); - let ast::ExprKind::Lit(token_lit) = expr.kind else { - panic!("didn't reparse an expr"); - }; - Some(token_lit) + if let ast::ExprKind::Lit(token_lit) = expr.kind { + Some(token_lit) + } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind + && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner + { + None + } else { + panic!("unexpected reparsed expr: {:?}", expr.kind); + } } _ => None, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3647bf2c378..06501816340 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -602,21 +602,13 @@ impl<'a> Parser<'a> { let polarity = self.parse_polarity(); // Parse both types and traits as a type, then reinterpret if necessary. - let err_path = |span| ast::Path::from_ident(Ident::new(kw::Empty, span)); let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt) { let span = self.prev_token.span.between(self.token.span); - self.dcx().emit_err(errors::MissingTraitInTraitImpl { + return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl { span, for_span: span.to(self.token.span), - }); - - P(Ty { - kind: TyKind::Path(None, err_path(span)), - span, - id: DUMMY_NODE_ID, - tokens: None, - }) + })); } else { self.parse_ty_with_generics_recovery(&generics)? }; @@ -657,6 +649,7 @@ impl<'a> Parser<'a> { other => { if let TyKind::ImplTrait(_, bounds) = other && let [bound] = bounds.as_slice() + && let GenericBound::Trait(poly_trait_ref) = bound { // Suggest removing extra `impl` keyword: // `impl<T: Default> impl Default for Wrapper<T>` @@ -666,12 +659,12 @@ impl<'a> Parser<'a> { extra_impl_kw, impl_trait_span: ty_first.span, }); + poly_trait_ref.trait_ref.path.clone() } else { - self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType { - span: ty_first.span, - }); + return Err(self.dcx().create_err( + errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span }, + )); } - err_path(ty_first.span) } }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 9f34417973e..56fd3a660d0 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -141,7 +141,7 @@ impl<D: Deps> DepGraph<D> { let colors = DepNodeColorMap::new(prev_graph_node_count); // Instantiate a node with zero dependencies only once for anonymous queries. - let _green_node_index = current.alloc_node( + let _green_node_index = current.alloc_new_node( DepNode { kind: D::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, @@ -149,7 +149,7 @@ impl<D: Deps> DepGraph<D> { assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE); // Instantiate a dependy-less red node only once for anonymous queries. - let red_node_index = current.alloc_node( + let red_node_index = current.alloc_new_node( DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), Fingerprint::ZERO, @@ -438,7 +438,7 @@ impl<D: Deps> DepGraphData<D> { // memory impact of this `anon_node_to_index` map remains tolerable, and helps // us avoid useless growth of the graph with almost-equivalent nodes. self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || { - self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO) + self.current.alloc_new_node(target_dep_node, task_deps, Fingerprint::ZERO) }) } }; @@ -680,8 +680,8 @@ impl<D: Deps> DepGraphData<D> { qcx: Qcx, diagnostic: &DiagInner, ) -> DepNodeIndex { - // Use `send` so we get an unique index, even though the dep node is not. - let dep_node_index = self.current.encoder.send( + // Use `send_new` so we get an unique index, even though the dep node is not. + let dep_node_index = self.current.encoder.send_new( DepNode { kind: D::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), @@ -713,20 +713,22 @@ impl<D: Deps> DepGraphData<D> { } } - // Manually recreate the node as `promote_node_and_deps_to_current` expects all - // green dependencies. - let dep_node_index = self.current.encoder.send( + // Use `send_and_color` as `promote_node_and_deps_to_current` expects all + // green dependencies. `send_and_color` will also prevent multiple nodes + // being encoded for concurrent calls. + let dep_node_index = self.current.encoder.send_and_color( + prev_index, + &self.colors, DepNode { kind: D::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + true, ); + // This will just overwrite the same value for concurrent calls. qcx.store_side_effect(dep_node_index, side_effect); - - // Mark the node as green. - self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); }) } @@ -736,38 +738,43 @@ impl<D: Deps> DepGraphData<D> { edges: EdgesVec, fingerprint: Option<Fingerprint>, ) -> DepNodeIndex { - let dep_node_index = - self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO)); - if let Some(prev_index) = self.previous.node_to_index_opt(&key) { // Determine the color and index of the new `DepNode`. - let color = if let Some(fingerprint) = fingerprint { + let is_green = if let Some(fingerprint) = fingerprint { if fingerprint == self.previous.fingerprint_by_index(prev_index) { // This is a green node: it existed in the previous compilation, // its query was re-executed, and it has the same result as before. - DepNodeColor::Green(dep_node_index) + true } else { // This is a red node: it existed in the previous compilation, its query // was re-executed, but it has a different result from before. - DepNodeColor::Red + false } } else { // This is a red node, effectively: it existed in the previous compilation // session, its query was re-executed, but it doesn't compute a result hash // (i.e. it represents a `no_hash` query), so we have no way of determining // whether or not the result was the same as before. - DepNodeColor::Red + false }; - debug_assert!( - self.colors.get(prev_index).is_none(), - "DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}", + let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); + + let dep_node_index = self.current.encoder.send_and_color( + prev_index, + &self.colors, + key, + fingerprint, + edges, + is_green, ); - self.colors.insert(prev_index, color); - } + self.current.record_node(dep_node_index, key, fingerprint); - dep_node_index + dep_node_index + } else { + self.current.alloc_new_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO)) + } } fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex { @@ -1246,19 +1253,15 @@ impl<D: Deps> CurrentDepGraph<D> { assert_eq!(previous, fingerprint, "Unstable fingerprints for {:?}", key); } - /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. - /// Assumes that this is a node that has no equivalent in the previous dep-graph. #[inline(always)] - fn alloc_node( + fn record_node( &self, + dep_node_index: DepNodeIndex, key: DepNode, - edges: EdgesVec, - current_fingerprint: Fingerprint, - ) -> DepNodeIndex { - let dep_node_index = self.encoder.send(key, current_fingerprint, edges); - + _current_fingerprint: Fingerprint, + ) { #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, current_fingerprint); + self.record_edge(dep_node_index, key, _current_fingerprint); if let Some(ref nodes_in_current_session) = self.nodes_in_current_session { outline(|| { @@ -1267,6 +1270,20 @@ impl<D: Deps> CurrentDepGraph<D> { } }); } + } + + /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. + /// Assumes that this is a node that has no equivalent in the previous dep-graph. + #[inline(always)] + fn alloc_new_node( + &self, + key: DepNode, + edges: EdgesVec, + current_fingerprint: Fingerprint, + ) -> DepNodeIndex { + let dep_node_index = self.encoder.send_new(key, current_fingerprint, edges); + + self.record_node(dep_node_index, key, current_fingerprint); dep_node_index } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 7750d6d1fef..7556a2456aa 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -707,7 +707,8 @@ impl<D: Deps> GraphEncoder<D> { } } - pub(crate) fn send( + /// Encodes a node that does not exists in the previous graph. + pub(crate) fn send_new( &self, node: DepNode, fingerprint: Fingerprint, @@ -718,6 +719,40 @@ impl<D: Deps> GraphEncoder<D> { self.status.lock().as_mut().unwrap().encode_node(&node, &self.record_graph) } + /// Encodes a node that exists in the previous graph, but was re-executed. + /// + /// This will also ensure the dep node is colored either red or green. + pub(crate) fn send_and_color( + &self, + prev_index: SerializedDepNodeIndex, + colors: &DepNodeColorMap, + node: DepNode, + fingerprint: Fingerprint, + edges: EdgesVec, + is_green: bool, + ) -> DepNodeIndex { + let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); + let node = NodeInfo { node, fingerprint, edges }; + + let mut status = self.status.lock(); + let status = status.as_mut().unwrap(); + + // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.get(prev_index) { + None => { + let dep_node_index = status.encode_node(&node, &self.record_graph); + colors.insert( + prev_index, + if is_green { DepNodeColor::Green(dep_node_index) } else { DepNodeColor::Red }, + ); + dep_node_index + } + Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, + Some(DepNodeColor::Red) => panic!(), + } + } + /// Encodes a node that was promoted from the previous graph. It reads the information directly from /// the previous dep graph and expects all edges to already have a new dep node index assigned. /// @@ -733,8 +768,8 @@ impl<D: Deps> GraphEncoder<D> { let mut status = self.status.lock(); let status = status.as_mut().unwrap(); - // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently - // on the same index. + // Check colors inside the lock to avoid racing when `send_promoted` or `send_and_color` + // is called concurrently on the same index. match colors.get(prev_index) { None => { let dep_node_index = diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 9ea9c58cfd1..0fcc3d8f6b3 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -18,7 +18,6 @@ rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4368f7882ff..cb328022c76 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1207,7 +1207,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { for (rule_i, rule_span) in &self.r.macro_map[&def_id.to_def_id()].rule_spans { self.r .unused_macro_rules - .entry(def_id) + .entry(node_id) .or_default() .insert(*rule_i, (ident, *rule_span)); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6dc854758da..363a75911ad 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -170,10 +170,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn report_with_use_injections(&mut self, krate: &Crate) { for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in - self.use_injections.drain(..) + std::mem::take(&mut self.use_injections) { let (span, found_use) = if let Some(def_id) = def_id.as_local() { - UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]) + UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)) } else { (None, FoundUse::No) }; @@ -1435,7 +1435,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() { - Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]), + Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)), None => (None, FoundUse::No), }; show_candidates( @@ -2550,7 +2550,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .iter() .filter_map(|item| { let parent_module = self.opt_local_def_id(item.parent_module)?.to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg.clone() }) + Some(StrippedCfgItem { + parent_module, + ident: item.ident, + cfg: item.cfg.clone(), + }) }) .collect::<Vec<_>>(); local_items.as_slice() @@ -2558,12 +2562,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.tcx.stripped_cfg_items(module.krate) }; - for &StrippedCfgItem { parent_module, name, ref cfg } in symbols { - if parent_module != module || name.name != *segment { + for &StrippedCfgItem { parent_module, ident, ref cfg } in symbols { + if parent_module != module || ident.name != *segment { continue; } - let note = errors::FoundItemConfigureOut { span: name.span }; + let note = errors::FoundItemConfigureOut { span: ident.span }; err.subdiagnostic(note); if let MetaItemKind::List(nested) = &cfg.kind diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5f0a2a597e9..180d6af219d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Option<LexicalScopeBinding<'ra>> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; - if ident.name == kw::Empty { - return Some(LexicalScopeBinding::Res(Res::Err)); - } let (general_span, normalized_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene let empty_span = ident.span.with_ctxt(SyntaxContext::root()); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0b3633a452c..3f3b455f4db 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -639,38 +639,38 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if let Some(glob_binding) = resolution.shadowed_glob { - let binding_id = match binding.kind { - NameBindingKind::Res(res) => { - Some(self.def_id_to_node_id[res.def_id().expect_local()]) - } - NameBindingKind::Module(module) => { - Some(self.def_id_to_node_id[module.def_id().expect_local()]) - } - NameBindingKind::Import { import, .. } => import.id(), - }; - if binding.res() != Res::Err && glob_binding.res() != Res::Err && let NameBindingKind::Import { import: glob_import, .. } = glob_binding.kind - && let Some(binding_id) = binding_id && let Some(glob_import_id) = glob_import.id() && let glob_import_def_id = self.local_def_id(glob_import_id) && self.effective_visibilities.is_exported(glob_import_def_id) && glob_binding.vis.is_public() && !binding.vis.is_public() { - self.lint_buffer.buffer_lint( - HIDDEN_GLOB_REEXPORTS, - binding_id, - binding.span, - BuiltinLintDiag::HiddenGlobReexports { - name: key.ident.name.to_string(), - namespace: key.ns.descr().to_owned(), - glob_reexport_span: glob_binding.span, - private_item_span: binding.span, - }, - ); + let binding_id = match binding.kind { + NameBindingKind::Res(res) => { + Some(self.def_id_to_node_id(res.def_id().expect_local())) + } + NameBindingKind::Module(module) => { + Some(self.def_id_to_node_id(module.def_id().expect_local())) + } + NameBindingKind::Import { import, .. } => import.id(), + }; + if let Some(binding_id) = binding_id { + self.lint_buffer.buffer_lint( + HIDDEN_GLOB_REEXPORTS, + binding_id, + binding.span, + BuiltinLintDiag::HiddenGlobReexports { + name: key.ident.name.to_string(), + namespace: key.ns.descr().to_owned(), + glob_reexport_span: glob_binding.span, + private_item_span: binding.span, + }, + ); + } } } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1389e8c811e..a7170edb986 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5007,8 +5007,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return false; } let Some(local_did) = did.as_local() else { return true }; - let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true }; - !self.r.proc_macros.contains(node_id) + !self.r.proc_macros.contains(&local_did) } fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b62bc6c45e0..c2761bd2717 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2238,7 +2238,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .get(&def_id) .is_some_and(|sig| sig.has_self), None => { - self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| { + self.r.tcx.fn_arg_idents(def_id).first().is_some_and(|&ident| { matches!(ident, Some(Ident { name: kw::SelfLower, .. })) }) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3ac66840d87..a92912c9639 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -56,7 +56,6 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::{PrimTy, TraitCandidate}; -use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; @@ -1141,7 +1140,7 @@ pub struct Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>, unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>, /// A map from the macro to all its potentially unused arms. - unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>, + unused_macro_rules: FxIndexMap<NodeId, UnordMap<usize, (Ident, Span)>>, proc_macro_stubs: FxHashSet<LocalDefId>, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: @@ -1184,7 +1183,6 @@ pub struct Resolver<'ra, 'tcx> { next_node_id: NodeId, node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>, - def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>, /// Indices of unnamed struct or variant fields with unresolved attributes. placeholder_field_indices: FxHashMap<NodeId, usize>, @@ -1202,7 +1200,7 @@ pub struct Resolver<'ra, 'tcx> { trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. - proc_macros: Vec<NodeId>, + proc_macros: Vec<LocalDefId>, confused_type_with_std_module: FxIndexMap<Span, Span>, /// Whether lifetime elision was successful. lifetime_elision_allowed: FxHashSet<NodeId>, @@ -1339,12 +1337,12 @@ impl<'tcx> Resolver<'_, 'tcx> { expn_id: ExpnId, span: Span, ) -> TyCtxtFeed<'tcx, LocalDefId> { - let data = def_kind.def_path_data(name); assert!( !self.node_id_to_def_id.contains_key(&node_id), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + "adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}", node_id, - data, + name, + def_kind, self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()), ); @@ -1369,7 +1367,6 @@ impl<'tcx> Resolver<'_, 'tcx> { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.node_id_to_def_id.insert(node_id, feed.downgrade()); } - assert_eq!(self.def_id_to_node_id.push(node_id), def_id); feed } @@ -1385,6 +1382,19 @@ impl<'tcx> Resolver<'_, 'tcx> { pub fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } + + /// This function is very slow, as it iterates over the entire + /// [Resolver::node_id_to_def_id] map just to find the [NodeId] + /// that corresponds to the given [LocalDefId]. Only use this in + /// diagnostics code paths. + fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId { + self.node_id_to_def_id + .items() + .filter(|(_, v)| v.key() == def_id) + .map(|(k, _)| *k) + .get_only() + .unwrap() + } } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { @@ -1417,8 +1427,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut Default::default(), ); - let mut def_id_to_node_id = IndexVec::default(); - assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); let crate_feed = tcx.create_local_crate_def_id(crate_span); @@ -1553,7 +1561,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lint_buffer: LintBuffer::default(), next_node_id: CRATE_NODE_ID, node_id_to_def_id, - def_id_to_node_id, placeholder_field_indices: Default::default(), invocation_parents, legacy_const_generic_args: Default::default(), @@ -1633,7 +1640,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub fn into_outputs(self) -> ResolverOutputs { - let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); + let proc_macros = self.proc_macros; let expn_that_defined = self.expn_that_defined; let extern_crate_map = self.extern_crate_map; let maybe_unused_trait_imports = self.maybe_unused_trait_imports; @@ -1648,7 +1655,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .filter_map(|item| { let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) + Some(StrippedCfgItem { parent_module, ident: item.ident, cfg: item.cfg }) }) .collect(), ); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 9d6ae0aa9d1..749b7f24c50 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -323,8 +323,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) { - let did = self.local_def_id(id); - if let Some(rules) = self.unused_macro_rules.get_mut(&did) { + if let Some(rules) = self.unused_macro_rules.get_mut(&id) { rules.remove(&rule_i); } } @@ -337,15 +336,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ident.span, BuiltinLintDiag::UnusedMacroDefinition(ident.name), ); + // Do not report unused individual rules if the entire macro is unused + self.unused_macro_rules.swap_remove(&node_id); } - for (&def_id, unused_arms) in self.unused_macro_rules.iter() { + for (&node_id, unused_arms) in self.unused_macro_rules.iter() { for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() { - if self.unused_macros.contains_key(&def_id) { - // We already lint the entire macro as unused - continue; - } - let node_id = self.def_id_to_node_id[def_id]; self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, node_id, @@ -466,11 +462,11 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn declare_proc_macro(&mut self, id: NodeId) { - self.proc_macros.push(id) + self.proc_macros.push(self.local_def_id(id)) } - fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem) { - self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, name, cfg }); + fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) { + self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, ident, cfg }); } fn registered_tools(&self) -> &RegisteredTools { @@ -932,7 +928,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .invocation_parents .get(&parent_scope.expansion) .map_or(ast::CRATE_NODE_ID, |parent| { - self.def_id_to_node_id[parent.parent_def] + self.def_id_to_node_id(parent.parent_def) }); self.lint_buffer.buffer_lint( LEGACY_DERIVE_HELPERS, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index d56ca9c2453..4b1b3903e40 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -721,7 +721,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) - | hir::definitions::DefPathData::LifetimeNs(..) => { + | hir::definitions::DefPathData::LifetimeNs(..) + | hir::definitions::DefPathData::AnonAssocTy => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); } }); diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index a087725d34d..63772a32222 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" getopts = "0.2" +rand = "0.9.0" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 56b3fe2ab4c..bdd54a15147 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1015,11 +1015,14 @@ impl OutFileName { &self, outputs: &OutputFilenames, flavor: OutputType, - codegen_unit_name: Option<&str>, + codegen_unit_name: &str, + invocation_temp: Option<&str>, ) -> PathBuf { match *self { OutFileName::Real(ref path) => path.clone(), - OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), + OutFileName::Stdout => { + outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp) + } } } @@ -1094,40 +1097,59 @@ impl OutputFilenames { /// Gets the path where a compilation artifact of the given type for the /// given codegen unit should be placed on disk. If codegen_unit_name is /// None, a path distinct from those of any codegen unit will be generated. - pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { + pub fn temp_path_for_cgu( + &self, + flavor: OutputType, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { let extension = flavor.extension(); - self.temp_path_ext(extension, codegen_unit_name) + self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but specifically for dwarf objects. - pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { - self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) + pub fn temp_path_dwo_for_cgu( + &self, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but also supports things where there is no corresponding /// OutputType, like noopt-bitcode or lto-bitcode. - pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { - let mut extension = String::new(); + pub fn temp_path_ext_for_cgu( + &self, + ext: &str, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + let mut extension = codegen_unit_name.to_string(); - if let Some(codegen_unit_name) = codegen_unit_name { - extension.push_str(codegen_unit_name); + // Append `.{invocation_temp}` to ensure temporary files are unique. + if let Some(rng) = invocation_temp { + extension.push('.'); + extension.push_str(rng); } + // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty. + // Append `.rcgu.{ext}`. if !ext.is_empty() { - if !extension.is_empty() { - extension.push('.'); - extension.push_str(RUST_CGU_EXT); - extension.push('.'); - } - + extension.push('.'); + extension.push_str(RUST_CGU_EXT); + extension.push('.'); extension.push_str(ext); } let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(temps_directory, &extension) } + pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf { + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + self.with_directory_and_extension(temps_directory, &ext) + } + pub fn with_extension(&self, extension: &str) -> PathBuf { self.with_directory_and_extension(&self.out_directory, extension) } @@ -1144,10 +1166,11 @@ impl OutputFilenames { &self, split_debuginfo_kind: SplitDebuginfo, split_dwarf_kind: SplitDwarfKind, - cgu_name: Option<&str>, + cgu_name: &str, + invocation_temp: Option<&str>, ) -> Option<PathBuf> { - let obj_out = self.temp_path(OutputType::Object, cgu_name); - let dwo_out = self.temp_path_dwo(cgu_name); + let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp); + let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp); match (split_debuginfo_kind, split_dwarf_kind) { (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fb4a437a487..1359f7eb7bb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -6,6 +6,8 @@ use std::sync::Arc; use std::sync::atomic::AtomicBool; use std::{env, fmt, io}; +use rand::{RngCore, rng}; +use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; @@ -203,6 +205,14 @@ pub struct Session { target_filesearch: FileSearch, host_filesearch: FileSearch, + + /// A random string generated per invocation of rustc. + /// + /// This is prepended to all temporary files so that they do not collide + /// during concurrent invocations of rustc, or past invocations that were + /// preserved with a flag like `-C save-temps`, since these files may be + /// hard linked. + pub invocation_temp: Option<String>, } #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -1117,6 +1127,12 @@ pub fn build_session( let target_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target); let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host); + + let invocation_temp = sopts + .incremental + .as_ref() + .map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string()); + let sess = Session { target, host, @@ -1140,6 +1156,7 @@ pub fn build_session( expanded_args, target_filesearch, host_filesearch, + invocation_temp, }; validate_commandline_args_with_session_available(&sess); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9e6ba2e1b9c..c95c03b4e4f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -116,9 +116,13 @@ pub struct SessionGlobals { } impl SessionGlobals { - pub fn new(edition: Edition, sm_inputs: Option<SourceMapInputs>) -> SessionGlobals { + pub fn new( + edition: Edition, + extra_symbols: &[&'static str], + sm_inputs: Option<SourceMapInputs>, + ) -> SessionGlobals { SessionGlobals { - symbol_interner: symbol::Interner::fresh(), + symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols), span_interner: Lock::new(span_encoding::SpanInterner::default()), metavar_spans: Default::default(), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), @@ -129,6 +133,7 @@ impl SessionGlobals { pub fn create_session_globals_then<R>( edition: Edition, + extra_symbols: &[&'static str], sm_inputs: Option<SourceMapInputs>, f: impl FnOnce() -> R, ) -> R { @@ -137,7 +142,7 @@ pub fn create_session_globals_then<R>( "SESSION_GLOBALS should never be overwritten! \ Use another thread if you need another SessionGlobals" ); - let session_globals = SessionGlobals::new(edition, sm_inputs); + let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs); SESSION_GLOBALS.set(&session_globals, f) } @@ -156,7 +161,7 @@ where F: FnOnce(&SessionGlobals) -> R, { if !SESSION_GLOBALS.is_set() { - let session_globals = SessionGlobals::new(edition, None); + let session_globals = SessionGlobals::new(edition, &[], None); SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f)) } else { SESSION_GLOBALS.with(f) @@ -172,7 +177,7 @@ where /// Default edition, no source map. pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R { - create_session_globals_then(edition::DEFAULT_EDITION, None, f) + create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f) } // If this ever becomes non thread-local, `decode_syntax_context` diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 31847ae3b46..986370f5019 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -454,6 +454,7 @@ symbols! { and_then, anon, anon_adt, + anon_assoc, anonymous_lifetime_in_impl_trait, any, append_const_msg, @@ -1913,6 +1914,7 @@ symbols! { simd_eq, simd_expose_provenance, simd_extract, + simd_extract_dyn, simd_fabs, simd_fcos, simd_fexp, @@ -1931,6 +1933,7 @@ symbols! { simd_ge, simd_gt, simd_insert, + simd_insert_dyn, simd_le, simd_lt, simd_masked_load, @@ -2538,15 +2541,10 @@ rustc_index::newtype_index! { } impl Symbol { - const fn new(n: u32) -> Self { + pub const fn new(n: u32) -> Self { Symbol(SymbolIndex::from_u32(n)) } - /// for use in Decoder only - pub fn new_from_decoded(n: u32) -> Self { - Self::new(n) - } - /// Maps a string to its interned representation. #[rustc_diagnostic_item = "SymbolIntern"] pub fn intern(string: &str) -> Self { @@ -2632,11 +2630,14 @@ struct InternerInner { } impl Interner { - fn prefill(init: &[&'static str]) -> Self { - Interner(Lock::new(InternerInner { - arena: Default::default(), - strings: init.iter().copied().collect(), - })) + fn prefill(init: &[&'static str], extra: &[&'static str]) -> Self { + let strings = FxIndexSet::from_iter(init.iter().copied().chain(extra.iter().copied())); + assert_eq!( + strings.len(), + init.len() + extra.len(), + "`init` or `extra` contain duplicate symbols", + ); + Interner(Lock::new(InternerInner { arena: Default::default(), strings })) } #[inline] @@ -2760,9 +2761,9 @@ impl Symbol { self != kw::Empty && self != kw::Underscore && !self.is_path_segment_keyword() } - /// Is this symbol was interned in compiler's `symbols!` macro - pub fn is_preinterned(self) -> bool { - self.as_u32() < PREINTERNED_SYMBOLS_COUNT + /// Was this symbol predefined in the compiler's `symbols!` macro + pub fn is_predefined(self) -> bool { + self.as_u32() < PREDEFINED_SYMBOLS_COUNT } } diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index c6aa7627b2b..660d0d7179a 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -3,7 +3,7 @@ use crate::create_default_session_globals_then; #[test] fn interner_tests() { - let i = Interner::prefill(&[]); + let i = Interner::prefill(&[], &[]); // first one is zero: assert_eq!(i.intern("dog"), Symbol::new(0)); // re-use gets the same entry: diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 8edfd16016c..d28f10ba9e3 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -858,7 +858,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::GlobalAsm | DefPathData::Impl | DefPathData::MacroNs(_) - | DefPathData::LifetimeNs(_) => { + | DefPathData::LifetimeNs(_) + | DefPathData::AnonAssocTy => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 38fcba4ea62..b963e4a2c7c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1988,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let closure: Vec<_> = self .tcx - .fn_arg_names(fn_def_id) + .fn_arg_idents(fn_def_id) .iter() .enumerate() .map(|(i, ident)| { @@ -3018,12 +3018,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"), }; let needs_parens = traits.len() != 1; - err.span_suggestion_verbose( - span, - "you can use `impl Trait` as the argument type", - "impl ", - Applicability::MaybeIncorrect, - ); + // Don't recommend impl Trait as a closure argument + if let Some(hir_id) = hir_id + && matches!( + self.tcx.parent_hir_node(hir_id), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { .. }, + .. + }) + ) + { + err.span_suggestion_verbose( + span, + "you can use `impl Trait` as the argument type", + "impl ", + Applicability::MaybeIncorrect, + ); + } let sugg = if !needs_parens { vec![(span.shrink_to_lo(), format!("&{kw}"))] } else { @@ -5397,7 +5408,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>( ); } if let Some(new) = - tcx.associated_items(data.impl_or_alias_def_id).find_by_name_and_kind( + tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(name), ty::AssocKind::Type, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 9cbe4147fb4..d8dcd12aecb 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as use rustc_type_ir::solve::NoSolution; use tracing::{instrument, trace}; -use crate::solve::Certainty; use crate::solve::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use crate::solve::{Certainty, deeply_normalize_for_diagnostics}; use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; pub(super) fn fulfillment_error_for_no_solution<'tcx>( @@ -151,7 +151,7 @@ fn find_best_leaf_obligation<'tcx>( // // We should probably fix the visitor to not do so instead, as this also // means the leaf obligation may be incorrect. - infcx + let obligation = infcx .fudge_inference_if_ok(|| { infcx .visit_proof_tree( @@ -161,7 +161,8 @@ fn find_best_leaf_obligation<'tcx>( .break_value() .ok_or(()) }) - .unwrap_or(obligation) + .unwrap_or(obligation); + deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation) } struct BestObligation<'tcx> { @@ -298,7 +299,7 @@ impl<'tcx> BestObligation<'tcx> { /// `NormalizesTo` goal, so we don't fall back to the rigid projection check /// that should catch when a projection goal fails due to an unsatisfied trait /// goal. - fn detect_error_in_higher_ranked_projection( + fn detect_trait_error_in_higher_ranked_projection( &mut self, goal: &inspect::InspectGoal<'_, 'tcx>, ) -> ControlFlow<PredicateObligation<'tcx>> { @@ -307,7 +308,13 @@ impl<'tcx> BestObligation<'tcx> { && !projection_clause.bound_vars().is_empty() { let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx)); - self.with_derived_obligation(self.obligation.with(tcx, pred), |this| { + let obligation = Obligation::new( + tcx, + self.obligation.cause.clone(), + goal.goal().param_env, + deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred), + ); + self.with_derived_obligation(obligation, |this| { goal.infcx().visit_proof_tree_at_depth( goal.goal().with(tcx, pred), goal.depth() + 1, @@ -388,7 +395,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} _ => return ControlFlow::Continue(()), } - let pred_kind = goal.goal().predicate.kind(); + + let pred = goal.goal().predicate; let candidates = self.non_trivial_candidates(goal); let candidate = match candidates.as_slice() { @@ -410,12 +418,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { // FIXME: Also, what about considering >1 layer up the stack? May be necessary // for normalizes-to. - let child_mode = match pred_kind.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - ChildMode::Trait(pred_kind.rebind(pred)) + let child_mode = match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { + ChildMode::Trait(pred.kind().rebind(trait_pred)) } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { - ChildMode::Host(pred_kind.rebind(pred)) + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => { + ChildMode::Host(pred.kind().rebind(host_pred)) } ty::PredicateKind::NormalizesTo(normalizes_to) if matches!( @@ -423,7 +431,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst ) => { - ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { + ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate { trait_ref: normalizes_to.alias.trait_ref(tcx), polarity: ty::PredicatePolarity::Positive, })) @@ -457,10 +465,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { for nested_goal in nested_goals { trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); + let nested_pred = nested_goal.goal().predicate; + let make_obligation = |cause| Obligation { cause, param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, + predicate: nested_pred, recursion_depth: self.obligation.recursion_depth + 1, }; @@ -510,31 +520,20 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { // alias-relate may fail because the lhs or rhs can't be normalized, // and therefore is treated as rigid. - if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { - if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } else if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } + if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() { + goal.infcx().visit_proof_tree_at_depth( + goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())), + goal.depth() + 1, + self, + )?; + goal.infcx().visit_proof_tree_at_depth( + goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())), + goal.depth() + 1, + self, + )?; } - self.detect_error_in_higher_ranked_projection(goal)?; + self.detect_trait_error_in_higher_ranked_projection(goal)?; ControlFlow::Break(self.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 232357dc71a..79fb044a67f 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -253,20 +253,28 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_, } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - deeply_normalize_with_skipped_universes( - self.at, - ty, - vec![None; ty.outer_exclusive_binder().as_usize()], - ) - .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self)) + let infcx = self.at.infcx; + infcx + .commit_if_ok(|_| { + deeply_normalize_with_skipped_universes( + self.at, + ty, + vec![None; ty.outer_exclusive_binder().as_usize()], + ) + }) + .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self)) } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - deeply_normalize_with_skipped_universes( - self.at, - ct, - vec![None; ct.outer_exclusive_binder().as_usize()], - ) - .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self)) + let infcx = self.at.infcx; + infcx + .commit_if_ok(|_| { + deeply_normalize_with_skipped_universes( + self.at, + ct, + vec![None; ct.outer_exclusive_binder().as_usize()], + ) + }) + .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self)) } } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index b7684e85d41..9520d948f51 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -252,7 +252,7 @@ fn associated_type_for_impl_trait_in_trait( assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); let span = tcx.def_span(opaque_ty_def_id); - // No name because this is a synthetic associated type. + // No name because this is an anonymous associated type. let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy); let local_def_id = trait_assoc_ty.def_id(); @@ -305,7 +305,7 @@ fn associated_type_for_impl_trait_in_impl( hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), hir::FnRetTy::Return(ty) => ty.span, }; - // No name because this is a synthetic associated type. + // No name because this is an anonymous associated type. let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy); let local_def_id = impl_assoc_ty.def_id(); diff --git a/library/Cargo.lock b/library/Cargo.lock index ad634e9f794..d035ca6c91f 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.152" +version = "0.1.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58" +checksum = "926ef6a360c15a911023352fd6969c51605d70495406f735beb1ca0257448e59" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 1d2dd1e6081..ee8cb9d25a3 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.153", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 1edade41597..90f76d6d4c7 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -1,38 +1,35 @@ //! Defines the `IntoIter` owned iterator for arrays. use crate::intrinsics::transmute_unchecked; -use crate::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; use crate::mem::MaybeUninit; use crate::num::NonZero; -use crate::ops::{IndexRange, Range}; +use crate::ops::{IndexRange, Range, Try}; use crate::{fmt, ptr}; +mod iter_inner; + +type InnerSized<T, const N: usize> = iter_inner::PolymorphicIter<[MaybeUninit<T>; N]>; +type InnerUnsized<T> = iter_inner::PolymorphicIter<[MaybeUninit<T>]>; + /// A by-value [array] iterator. #[stable(feature = "array_value_iter", since = "1.51.0")] #[rustc_insignificant_dtor] #[rustc_diagnostic_item = "ArrayIntoIter"] +#[derive(Clone)] pub struct IntoIter<T, const N: usize> { - /// This is the array we are iterating over. - /// - /// Elements with index `i` where `alive.start <= i < alive.end` have not - /// been yielded yet and are valid array entries. Elements with indices `i - /// < alive.start` or `i >= alive.end` have been yielded already and must - /// not be accessed anymore! Those dead elements might even be in a - /// completely uninitialized state! - /// - /// So the invariants are: - /// - `data[alive]` is alive (i.e. contains valid elements) - /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the - /// elements were already read and must not be touched anymore!) - data: [MaybeUninit<T>; N], + inner: InnerSized<T, N>, +} - /// The elements in `data` that have not been yielded yet. - /// - /// Invariants: - /// - `alive.end <= N` - /// - /// (And the `IndexRange` type requires `alive.start <= alive.end`.) - alive: IndexRange, +impl<T, const N: usize> IntoIter<T, N> { + #[inline] + fn unsize(&self) -> &InnerUnsized<T> { + &self.inner + } + #[inline] + fn unsize_mut(&mut self) -> &mut InnerUnsized<T> { + &mut self.inner + } } // Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator` @@ -53,6 +50,7 @@ impl<T, const N: usize> IntoIterator for [T; N] { /// 2021 edition -- see the [array] Editions section for more information. /// /// [array]: prim@array + #[inline] fn into_iter(self) -> Self::IntoIter { // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` // promise: @@ -68,7 +66,10 @@ impl<T, const N: usize> IntoIterator for [T; N] { // FIXME: If normal `transmute` ever gets smart enough to allow this // directly, use it instead of `transmute_unchecked`. let data: [MaybeUninit<T>; N] = unsafe { transmute_unchecked(self) }; - IntoIter { data, alive: IndexRange::zero_to(N) } + // SAFETY: The original array was entirely initialized and the the alive + // range we're passing here represents that fact. + let inner = unsafe { InnerSized::new_unchecked(IndexRange::zero_to(N), data) }; + IntoIter { inner } } } @@ -136,13 +137,16 @@ impl<T, const N: usize> IntoIter<T, N> { /// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]); /// ``` #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[inline] pub const unsafe fn new_unchecked( buffer: [MaybeUninit<T>; N], initialized: Range<usize>, ) -> Self { // SAFETY: one of our safety conditions is that the range is canonical. let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) }; - Self { data: buffer, alive } + // SAFETY: one of our safety condition is that these items are initialized. + let inner = unsafe { InnerSized::new_unchecked(alive, buffer) }; + IntoIter { inner } } /// Creates an iterator over `T` which returns no elements. @@ -198,172 +202,134 @@ impl<T, const N: usize> IntoIter<T, N> { /// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]); /// ``` #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[inline] pub const fn empty() -> Self { - let buffer = [const { MaybeUninit::uninit() }; N]; - let initialized = 0..0; - - // SAFETY: We're telling it that none of the elements are initialized, - // which is trivially true. And ∀N: usize, 0 <= N. - unsafe { Self::new_unchecked(buffer, initialized) } + let inner = InnerSized::empty(); + IntoIter { inner } } /// Returns an immutable slice of all elements that have not been yielded /// yet. #[stable(feature = "array_value_iter", since = "1.51.0")] + #[inline] pub fn as_slice(&self) -> &[T] { - // SAFETY: We know that all elements within `alive` are properly initialized. - unsafe { - let slice = self.data.get_unchecked(self.alive.clone()); - slice.assume_init_ref() - } + self.unsize().as_slice() } /// Returns a mutable slice of all elements that have not been yielded yet. #[stable(feature = "array_value_iter", since = "1.51.0")] + #[inline] pub fn as_mut_slice(&mut self) -> &mut [T] { - // SAFETY: We know that all elements within `alive` are properly initialized. - unsafe { - let slice = self.data.get_unchecked_mut(self.alive.clone()); - slice.assume_init_mut() - } + self.unsize_mut().as_mut_slice() } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T, const N: usize> Iterator for IntoIter<T, N> { type Item = T; + + #[inline] fn next(&mut self) -> Option<Self::Item> { - // Get the next index from the front. - // - // Increasing `alive.start` by 1 maintains the invariant regarding - // `alive`. However, due to this change, for a short time, the alive - // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. - self.alive.next().map(|idx| { - // Read the element from the array. - // SAFETY: `idx` is an index into the former "alive" region of the - // array. Reading this element means that `data[idx]` is regarded as - // dead now (i.e. do not touch). As `idx` was the start of the - // alive-zone, the alive zone is now `data[alive]` again, restoring - // all invariants. - unsafe { self.data.get_unchecked(idx).assume_init_read() } - }) + self.unsize_mut().next() } + #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let len = self.len(); - (len, Some(len)) + self.unsize().size_hint() } #[inline] - fn fold<Acc, Fold>(mut self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let data = &mut self.data; - iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) - }) + self.unsize_mut().fold(init, fold) } + #[inline] + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + self.unsize_mut().try_fold(init, f) + } + + #[inline] fn count(self) -> usize { self.len() } + #[inline] fn last(mut self) -> Option<Self::Item> { self.next_back() } + #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { - // This also moves the start, which marks them as conceptually "dropped", - // so if anything goes bad then our drop impl won't double-free them. - let range_to_drop = self.alive.take_prefix(n); - let remaining = n - range_to_drop.len(); - - // SAFETY: These elements are currently initialized, so it's fine to drop them. - unsafe { - let slice = self.data.get_unchecked_mut(range_to_drop); - slice.assume_init_drop(); - } - - NonZero::new(remaining).map_or(Ok(()), Err) + self.unsize_mut().advance_by(n) } #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { // SAFETY: The caller must provide an idx that is in bound of the remainder. - unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::<T>().read() } + let elem_ref = unsafe { self.as_mut_slice().get_unchecked_mut(idx) }; + // SAFETY: We only implement `TrustedRandomAccessNoCoerce` for types + // which are actually `Copy`, so cannot have multiple-drop issues. + unsafe { ptr::read(elem_ref) } } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> { + #[inline] fn next_back(&mut self) -> Option<Self::Item> { - // Get the next index from the back. - // - // Decreasing `alive.end` by 1 maintains the invariant regarding - // `alive`. However, due to this change, for a short time, the alive - // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. - self.alive.next_back().map(|idx| { - // Read the element from the array. - // SAFETY: `idx` is an index into the former "alive" region of the - // array. Reading this element means that `data[idx]` is regarded as - // dead now (i.e. do not touch). As `idx` was the end of the - // alive-zone, the alive zone is now `data[alive]` again, restoring - // all invariants. - unsafe { self.data.get_unchecked(idx).assume_init_read() } - }) + self.unsize_mut().next_back() } #[inline] - fn rfold<Acc, Fold>(mut self, init: Acc, mut rfold: Fold) -> Acc + fn rfold<Acc, Fold>(mut self, init: Acc, rfold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let data = &mut self.data; - iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) - }) + self.unsize_mut().rfold(init, rfold) + } + + #[inline] + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + self.unsize_mut().try_rfold(init, f) } + #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { - // This also moves the end, which marks them as conceptually "dropped", - // so if anything goes bad then our drop impl won't double-free them. - let range_to_drop = self.alive.take_suffix(n); - let remaining = n - range_to_drop.len(); - - // SAFETY: These elements are currently initialized, so it's fine to drop them. - unsafe { - let slice = self.data.get_unchecked_mut(range_to_drop); - slice.assume_init_drop(); - } - - NonZero::new(remaining).map_or(Ok(()), Err) + self.unsize_mut().advance_back_by(n) } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T, const N: usize> Drop for IntoIter<T, N> { + #[inline] fn drop(&mut self) { - // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice - // of elements that have not been moved out yet and that remain - // to be dropped. - unsafe { ptr::drop_in_place(self.as_mut_slice()) } + // `inner` now handles this, but it'd technically be a breaking change + // to remove this `impl`, even though it's useless. } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> { + #[inline] fn len(&self) -> usize { - self.alive.len() + self.inner.len() } + #[inline] fn is_empty(&self) -> bool { - self.alive.is_empty() + self.inner.len() == 0 } } @@ -397,31 +363,8 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl<T: Clone, const N: usize> Clone for IntoIter<T, N> { - fn clone(&self) -> Self { - // Note, we don't really need to match the exact same alive range, so - // we can just clone into offset 0 regardless of where `self` is. - let mut new = - Self { data: [const { MaybeUninit::uninit() }; N], alive: IndexRange::zero_to(0) }; - - // Clone all alive elements. - for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { - // Write a clone into the new array, then update its alive range. - // If cloning panics, we'll correctly drop the previous items. - dst.write(src.clone()); - // This addition cannot overflow as we're iterating a slice - new.alive = IndexRange::zero_to(new.alive.end() + 1); - } - - new - } -} - -#[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Only print the elements that were not yielded yet: we cannot - // access the yielded elements anymore. - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + self.unsize().fmt(f) } } diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs new file mode 100644 index 00000000000..3c2343591f8 --- /dev/null +++ b/library/core/src/array/iter/iter_inner.rs @@ -0,0 +1,281 @@ +//! Defines the `IntoIter` owned iterator for arrays. + +use crate::mem::MaybeUninit; +use crate::num::NonZero; +use crate::ops::{IndexRange, NeverShortCircuit, Try}; +use crate::{fmt, iter}; + +#[allow(private_bounds)] +trait PartialDrop { + /// # Safety + /// `self[alive]` are all initialized before the call, + /// then are never used (without reinitializing them) after it. + unsafe fn partial_drop(&mut self, alive: IndexRange); +} +impl<T> PartialDrop for [MaybeUninit<T>] { + unsafe fn partial_drop(&mut self, alive: IndexRange) { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { self.get_unchecked_mut(alive).assume_init_drop() } + } +} +impl<T, const N: usize> PartialDrop for [MaybeUninit<T>; N] { + unsafe fn partial_drop(&mut self, alive: IndexRange) { + let slice: &mut [MaybeUninit<T>] = self; + // SAFETY: Initialized elements in the array are also initialized in the slice. + unsafe { slice.partial_drop(alive) } + } +} + +/// The internals of a by-value array iterator. +/// +/// The real `array::IntoIter<T, N>` stores a `PolymorphicIter<[MaybeUninit<T>, N]>` +/// which it unsizes to `PolymorphicIter<[MaybeUninit<T>]>` to iterate. +#[allow(private_bounds)] +pub(super) struct PolymorphicIter<DATA: ?Sized> +where + DATA: PartialDrop, +{ + /// The elements in `data` that have not been yielded yet. + /// + /// Invariants: + /// - `alive.end <= N` + /// + /// (And the `IndexRange` type requires `alive.start <= alive.end`.) + alive: IndexRange, + + /// This is the array we are iterating over. + /// + /// Elements with index `i` where `alive.start <= i < alive.end` have not + /// been yielded yet and are valid array entries. Elements with indices `i + /// < alive.start` or `i >= alive.end` have been yielded already and must + /// not be accessed anymore! Those dead elements might even be in a + /// completely uninitialized state! + /// + /// So the invariants are: + /// - `data[alive]` is alive (i.e. contains valid elements) + /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the + /// elements were already read and must not be touched anymore!) + data: DATA, +} + +#[allow(private_bounds)] +impl<DATA: ?Sized> PolymorphicIter<DATA> +where + DATA: PartialDrop, +{ + #[inline] + pub(super) const fn len(&self) -> usize { + self.alive.len() + } +} + +#[allow(private_bounds)] +impl<DATA: ?Sized> Drop for PolymorphicIter<DATA> +where + DATA: PartialDrop, +{ + #[inline] + fn drop(&mut self) { + // SAFETY: by our type invariant `self.alive` is exactly the initialized + // items, and this is drop so nothing can use the items afterwards. + unsafe { self.data.partial_drop(self.alive.clone()) } + } +} + +impl<T, const N: usize> PolymorphicIter<[MaybeUninit<T>; N]> { + #[inline] + pub(super) const fn empty() -> Self { + Self { alive: IndexRange::zero_to(0), data: [const { MaybeUninit::uninit() }; N] } + } + + /// # Safety + /// `data[alive]` are all initialized. + #[inline] + pub(super) const unsafe fn new_unchecked(alive: IndexRange, data: [MaybeUninit<T>; N]) -> Self { + Self { alive, data } + } +} + +impl<T: Clone, const N: usize> Clone for PolymorphicIter<[MaybeUninit<T>; N]> { + #[inline] + fn clone(&self) -> Self { + // Note, we don't really need to match the exact same alive range, so + // we can just clone into offset 0 regardless of where `self` is. + let mut new = Self::empty(); + + fn clone_into_new<U: Clone>( + source: &PolymorphicIter<[MaybeUninit<U>]>, + target: &mut PolymorphicIter<[MaybeUninit<U>]>, + ) { + // Clone all alive elements. + for (src, dst) in iter::zip(source.as_slice(), &mut target.data) { + // Write a clone into the new array, then update its alive range. + // If cloning panics, we'll correctly drop the previous items. + dst.write(src.clone()); + // This addition cannot overflow as we're iterating a slice, + // the length of which always fits in usize. + target.alive = IndexRange::zero_to(target.alive.end() + 1); + } + } + + clone_into_new(self, &mut new); + new + } +} + +impl<T> PolymorphicIter<[MaybeUninit<T>]> { + #[inline] + pub(super) fn as_slice(&self) -> &[T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked(self.alive.clone()); + slice.assume_init_ref() + } + } + + #[inline] + pub(super) fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked_mut(self.alive.clone()); + slice.assume_init_mut() + } + } +} + +impl<T: fmt::Debug> fmt::Debug for PolymorphicIter<[MaybeUninit<T>]> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Only print the elements that were not yielded yet: we cannot + // access the yielded elements anymore. + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +/// Iterator-equivalent methods. +/// +/// We don't implement the actual iterator traits because we want to implement +/// things like `try_fold` that require `Self: Sized` (which we're not). +impl<T> PolymorphicIter<[MaybeUninit<T>]> { + #[inline] + pub(super) fn next(&mut self) -> Option<T> { + // Get the next index from the front. + // + // Increasing `alive.start` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. + self.alive.next().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the start of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + pub(super) fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + pub(super) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + // This also moves the start, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_prefix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + slice.assume_init_drop(); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + pub(super) fn fold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + pub(super) fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, T) -> R, + R: Try<Output = B>, + { + // `alive` is an `IndexRange`, not an arbitrary iterator, so we can + // trust that its `try_fold` isn't going to do something weird like + // call the fold-er multiple times for the same index. + let data = &mut self.data; + self.alive.try_fold(init, move |accum, idx| { + // SAFETY: `idx` has been removed from the alive range, so we're not + // going to drop it (even if `f` panics) and thus its ok to give + // out ownership of that item to `f` to handle. + let elem = unsafe { data.get_unchecked(idx).assume_init_read() }; + f(accum, elem) + }) + } + + #[inline] + pub(super) fn next_back(&mut self) -> Option<T> { + // Get the next index from the back. + // + // Decreasing `alive.end` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. + self.alive.next_back().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the end of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + pub(super) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + // This also moves the end, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_suffix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + slice.assume_init_drop(); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + pub(super) fn rfold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + pub(super) fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, T) -> R, + R: Try<Output = B>, + { + // `alive` is an `IndexRange`, not an arbitrary iterator, so we can + // trust that its `try_rfold` isn't going to do something weird like + // call the fold-er multiple times for the same index. + let data = &mut self.data; + self.alive.try_rfold(init, move |accum, idx| { + // SAFETY: `idx` has been removed from the alive range, so we're not + // going to drop it (even if `f` panics) and thus its ok to give + // out ownership of that item to `f` to handle. + let elem = unsafe { data.get_unchecked(idx).assume_init_read() }; + f(accum, elem) + }) + } +} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ad33e2e5fe9..e99776a71c1 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2628,13 +2628,15 @@ pub const fn bswap<T: Copy>(x: T) -> T; #[rustc_intrinsic] pub const fn bitreverse<T: Copy>(x: T) -> T; -/// Does a three-way comparison between the two integer arguments. +/// Does a three-way comparison between the two arguments, +/// which must be of character or integer (signed or unsigned) type. /// -/// This is included as an intrinsic as it's useful to let it be one thing -/// in MIR, rather than the multiple checks and switches that make its IR -/// large and difficult to optimize. +/// This was originally added because it greatly simplified the MIR in `cmp` +/// implementations, and then LLVM 20 added a backend intrinsic for it too. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] #[rustc_intrinsic] pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering; diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index ae6e1a779ed..9ac6ee85535 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -4,7 +4,7 @@ /// Inserts an element into a vector, returning the updated vector. /// -/// `T` must be a vector with element type `U`. +/// `T` must be a vector with element type `U`, and `idx` must be `const`. /// /// # Safety /// @@ -15,15 +15,48 @@ pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T; /// Extracts an element from a vector. /// -/// `T` must be a vector with element type `U`. +/// `T` must be a vector with element type `U`, and `idx` must be `const`. /// /// # Safety /// -/// `idx` must be in-bounds of the vector. +/// `idx` must be const and in-bounds of the vector. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U; +/// Inserts an element into a vector, returning the updated vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// If the index is `const`, [`simd_insert`] may emit better assembly. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_insert_dyn<T, U>(mut x: T, idx: u32, val: U) -> T { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw mut x).cast::<U>().add(idx as usize).write(val) } + x +} + +/// Extracts an element from a vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// If the index is `const`, [`simd_extract`] may emit better assembly. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw const x).cast::<U>().add(idx as usize).read() } +} + /// Adds two simd vectors elementwise. /// /// `T` must be a vector of integers or floats. diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index f9c388e8564..bd093e279c3 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -36,7 +36,7 @@ where /// /// The method does no guarding against overflows, so enumerating more than /// `usize::MAX` elements either produces the wrong result or panics. If - /// debug assertions are enabled, a panic is guaranteed. + /// overflow checks are enabled, a panic is guaranteed. /// /// # Panics /// diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 3bbb52fdbcb..d9534a44598 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -199,7 +199,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so counting elements of /// an iterator with more than [`usize::MAX`] elements either produces the - /// wrong result or panics. If debug assertions are enabled, a panic is + /// wrong result or panics. If overflow checks are enabled, a panic is /// guaranteed. /// /// # Panics @@ -931,7 +931,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so enumerating more than /// [`usize::MAX`] elements either produces the wrong result or panics. If - /// debug assertions are enabled, a panic is guaranteed. + /// overflow checks are enabled, a panic is guaranteed. /// /// # Panics /// @@ -2964,7 +2964,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so if there are more /// than [`usize::MAX`] non-matching elements, it either produces the wrong - /// result or panics. If debug assertions are enabled, a panic is + /// result or panics. If overflow checks are enabled, a panic is /// guaranteed. /// /// # Panics @@ -3516,7 +3516,7 @@ pub trait Iterator { /// # Panics /// /// When calling `sum()` and a primitive integer type is being returned, this - /// method will panic if the computation overflows and debug assertions are + /// method will panic if the computation overflows and overflow checks are /// enabled. /// /// # Examples @@ -3550,7 +3550,7 @@ pub trait Iterator { /// # Panics /// /// When calling `product()` and a primitive integer type is being returned, - /// method will panic if the computation overflows and debug assertions are + /// method will panic if the computation overflows and overflow checks are /// enabled. /// /// # Examples diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index de0d55e2185..05d8216ac27 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3571,10 +3571,7 @@ macro_rules! int_impl { // so delegate it to `Ord` which is already producing -1/0/+1 // exactly like we need and can be the place to deal with the complexity. - // FIXME(const-hack): replace with cmp - if self < 0 { -1 } - else if self == 0 { 0 } - else { 1 } + crate::intrinsics::three_way_compare(self, 0) as Self } /// Returns `true` if `self` is positive and `false` if the number is zero or diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index b82184b15b2..c645c996eb7 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,5 +1,6 @@ use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZero; +use crate::ops::{NeverShortCircuit, Try}; use crate::ub_checks; /// Like a `Range<usize>`, but with a safety invariant that `start <= end`. @@ -112,6 +113,12 @@ impl IndexRange { self.end = mid; suffix } + + #[inline] + fn assume_range(&self) { + // SAFETY: This is the type invariant + unsafe { crate::hint::assert_unchecked(self.start <= self.end) } + } } impl Iterator for IndexRange { @@ -138,6 +145,30 @@ impl Iterator for IndexRange { let taken = self.take_prefix(n); NonZero::new(n - taken.len()).map_or(Ok(()), Err) } + + #[inline] + fn fold<B, F: FnMut(B, usize) -> B>(mut self, init: B, f: F) -> B { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_fold<B, F, R>(&mut self, mut accum: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + // `Range` needs to check `start < end`, but thanks to our type invariant + // we can loop on the stricter `start != end`. + + self.assume_range(); + while self.start != self.end { + // SAFETY: We just checked that the range is non-empty + let i = unsafe { self.next_unchecked() }; + accum = f(accum, i)?; + } + try { accum } + } } impl DoubleEndedIterator for IndexRange { @@ -156,6 +187,30 @@ impl DoubleEndedIterator for IndexRange { let taken = self.take_suffix(n); NonZero::new(n - taken.len()).map_or(Ok(()), Err) } + + #[inline] + fn rfold<B, F: FnMut(B, usize) -> B>(mut self, init: B, f: F) -> B { + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_rfold<B, F, R>(&mut self, mut accum: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + // `Range` needs to check `start < end`, but thanks to our type invariant + // we can loop on the stricter `start != end`. + + self.assume_range(); + while self.start != self.end { + // SAFETY: We just checked that the range is non-empty + let i = unsafe { self.next_back_unchecked() }; + accum = f(accum, i)?; + } + try { accum } + } } impl ExactSizeIterator for IndexRange { diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ea53da78d3b..2357ba23aa0 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -398,6 +398,7 @@ use crate::cmp::Ordering; use crate::intrinsics::const_eval_select; use crate::marker::FnPtr; use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +use crate::num::NonZero; use crate::{fmt, hash, intrinsics, ub_checks}; mod alignment; @@ -1094,51 +1095,25 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { // are pointers inside `T` we will copy them in one go rather than trying to copy a part // of a pointer (which would not work). // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } + unsafe { swap_nonoverlapping_const(x, y, count) } } else { - macro_rules! attempt_swap_as_chunks { - ($ChunkTy:ty) => { - if align_of::<T>() >= align_of::<$ChunkTy>() - && size_of::<T>() % size_of::<$ChunkTy>() == 0 - { - let x: *mut $ChunkTy = x.cast(); - let y: *mut $ChunkTy = y.cast(); - let count = count * (size_of::<T>() / size_of::<$ChunkTy>()); - // SAFETY: these are the same bytes that the caller promised were - // ok, just typed as `MaybeUninit<ChunkTy>`s instead of as `T`s. - // The `if` condition above ensures that we're not violating - // alignment requirements, and that the division is exact so - // that we don't lose any bytes off the end. - return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }; - } - }; + // Going though a slice here helps codegen know the size fits in `isize` + let slice = slice_from_raw_parts_mut(x, count); + // SAFETY: This is all readable from the pointer, meaning it's one + // allocated object, and thus cannot be more than isize::MAX bytes. + let bytes = unsafe { mem::size_of_val_raw::<[T]>(slice) }; + if let Some(bytes) = NonZero::new(bytes) { + // SAFETY: These are the same ranges, just expressed in a different + // type, so they're still non-overlapping. + unsafe { swap_nonoverlapping_bytes(x.cast(), y.cast(), bytes) }; } - - // Split up the slice into small power-of-two-sized chunks that LLVM is able - // to vectorize (unless it's a special type with more-than-pointer alignment, - // because we don't want to pessimize things like slices of SIMD vectors.) - if align_of::<T>() <= size_of::<usize>() - && (!size_of::<T>().is_power_of_two() - || size_of::<T>() > size_of::<usize>() * 2) - { - attempt_swap_as_chunks!(usize); - attempt_swap_as_chunks!(u8); - } - - // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } } ) } /// Same behavior and safety conditions as [`swap_nonoverlapping`] -/// -/// LLVM can vectorize this (at least it can for the power-of-two-sized types -/// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] -const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) { - let x = x.cast::<MaybeUninit<T>>(); - let y = y.cast::<MaybeUninit<T>>(); +const unsafe fn swap_nonoverlapping_const<T>(x: *mut T, y: *mut T, count: usize) { let mut i = 0; while i < count { // SAFETY: By precondition, `i` is in-bounds because it's below `n` @@ -1147,26 +1122,91 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun // and it's distinct from `x` since the ranges are non-overlapping let y = unsafe { y.add(i) }; - // If we end up here, it's because we're using a simple type -- like - // a small power-of-two-sized thing -- or a special type with particularly - // large alignment, particularly SIMD types. - // Thus, we're fine just reading-and-writing it, as either it's small - // and that works well anyway or it's special and the type's author - // presumably wanted things to be done in the larger chunk. - // SAFETY: we're only ever given pointers that are valid to read/write, // including being aligned, and nothing here panics so it's drop-safe. unsafe { - let a: MaybeUninit<T> = read(x); - let b: MaybeUninit<T> = read(y); - write(x, b); - write(y, a); + // Note that it's critical that these use `copy_nonoverlapping`, + // rather than `read`/`write`, to avoid #134713 if T has padding. + let mut temp = MaybeUninit::<T>::uninit(); + copy_nonoverlapping(x, temp.as_mut_ptr(), 1); + copy_nonoverlapping(y, x, 1); + copy_nonoverlapping(temp.as_ptr(), y, 1); } i += 1; } } +// Don't let MIR inline this, because we really want it to keep its noalias metadata +#[rustc_no_mir_inline] +#[inline] +fn swap_chunk<const N: usize>(x: &mut MaybeUninit<[u8; N]>, y: &mut MaybeUninit<[u8; N]>) { + let a = *x; + let b = *y; + *x = b; + *y = a; +} + +#[inline] +unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, bytes: NonZero<usize>) { + // Same as `swap_nonoverlapping::<[u8; N]>`. + unsafe fn swap_nonoverlapping_chunks<const N: usize>( + x: *mut MaybeUninit<[u8; N]>, + y: *mut MaybeUninit<[u8; N]>, + chunks: NonZero<usize>, + ) { + let chunks = chunks.get(); + for i in 0..chunks { + // SAFETY: i is in [0, chunks) so the adds and dereferences are in-bounds. + unsafe { swap_chunk(&mut *x.add(i), &mut *y.add(i)) }; + } + } + + // Same as `swap_nonoverlapping_bytes`, but accepts at most 1+2+4=7 bytes + #[inline] + unsafe fn swap_nonoverlapping_short(x: *mut u8, y: *mut u8, bytes: NonZero<usize>) { + // Tail handling for auto-vectorized code sometimes has element-at-a-time behaviour, + // see <https://github.com/rust-lang/rust/issues/134946>. + // By swapping as different sizes, rather than as a loop over bytes, + // we make sure not to end up with, say, seven byte-at-a-time copies. + + let bytes = bytes.get(); + let mut i = 0; + macro_rules! swap_prefix { + ($($n:literal)+) => {$( + if (bytes & $n) != 0 { + // SAFETY: `i` can only have the same bits set as those in bytes, + // so these `add`s are in-bounds of `bytes`. But the bit for + // `$n` hasn't been set yet, so the `$n` bytes that `swap_chunk` + // will read and write are within the usable range. + unsafe { swap_chunk::<$n>(&mut*x.add(i).cast(), &mut*y.add(i).cast()) }; + i |= $n; + } + )+}; + } + swap_prefix!(4 2 1); + debug_assert_eq!(i, bytes); + } + + const CHUNK_SIZE: usize = size_of::<*const ()>(); + let bytes = bytes.get(); + + let chunks = bytes / CHUNK_SIZE; + let tail = bytes % CHUNK_SIZE; + if let Some(chunks) = NonZero::new(chunks) { + // SAFETY: this is bytes/CHUNK_SIZE*CHUNK_SIZE bytes, which is <= bytes, + // so it's within the range of our non-overlapping bytes. + unsafe { swap_nonoverlapping_chunks::<CHUNK_SIZE>(x.cast(), y.cast(), chunks) }; + } + if let Some(tail) = NonZero::new(tail) { + const { assert!(CHUNK_SIZE <= 8) }; + let delta = chunks * CHUNK_SIZE; + // SAFETY: the tail length is below CHUNK SIZE because of the remainder, + // and CHUNK_SIZE is at most 8 by the const assert, so tail <= 7 + unsafe { swap_nonoverlapping_short(x.add(delta), y.add(delta), tail) }; + } +} + /// Moves `src` into the pointed `dst`, returning the previous `dst` value. /// /// Neither value is dropped. diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 6091926084a..cc5f7946863 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -984,3 +984,39 @@ fn test_ptr_metadata_in_const() { assert_eq!(SLICE_META, 3); assert_eq!(DYN_META.size_of(), 42); } + +// See <https://github.com/rust-lang/rust/issues/134713> +const fn ptr_swap_nonoverlapping_is_untyped_inner() { + #[repr(C)] + struct HasPadding(usize, u8); + + let buf1: [usize; 2] = [1000, 2000]; + let buf2: [usize; 2] = [3000, 4000]; + + // HasPadding and [usize; 2] have the same size and alignment, + // so swap_nonoverlapping should treat them the same + assert!(size_of::<HasPadding>() == size_of::<[usize; 2]>()); + assert!(align_of::<HasPadding>() == align_of::<[usize; 2]>()); + + let mut b1 = buf1; + let mut b2 = buf2; + // Safety: b1 and b2 are distinct local variables, + // with the same size and alignment as HasPadding. + unsafe { + std::ptr::swap_nonoverlapping( + b1.as_mut_ptr().cast::<HasPadding>(), + b2.as_mut_ptr().cast::<HasPadding>(), + 1, + ); + } + assert!(b1[0] == buf2[0]); + assert!(b1[1] == buf2[1]); + assert!(b2[0] == buf1[0]); + assert!(b2[1] == buf1[1]); +} + +#[test] +fn test_ptr_swap_nonoverlapping_is_untyped() { + ptr_swap_nonoverlapping_is_untyped_inner(); + const { ptr_swap_nonoverlapping_is_untyped_inner() }; +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 176da603d58..6b70ff764d7 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.152" } +compiler_builtins = { version = "=0.1.153" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml index f2cbe512b5e..f0cb34eb458 100644 --- a/src/bootstrap/defaults/bootstrap.dist.toml +++ b/src/bootstrap/defaults/bootstrap.dist.toml @@ -17,7 +17,7 @@ download-ci-llvm = false [rust] # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`). # Make sure they don't get set when installing from source. -channel = "nightly" +channel = "auto-detect" # Never download a rustc, distributions must build a fresh compiler. download-rustc = false lld = true diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 7cc7093e23b..1c61f0a56d7 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -148,7 +148,9 @@ impl Step for ToolBuild { &self.extra_features, ); - if path.ends_with("/rustdoc") && + // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer) + // could use the additional optimizations. + if self.mode == Mode::ToolRustc && // rustdoc is performance sensitive, so apply LTO to it. is_lto_stage(&self.compiler) { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e270c92fcab..25ec64f90b5 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1544,9 +1544,6 @@ impl Config { } } - let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); - let ci_channel = file_content.trim_end(); - // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `bootstrap.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { @@ -1852,17 +1849,21 @@ impl Config { let mut lld_enabled = None; let mut std_features = None; - let is_user_configured_rust_channel = - if let Some(channel) = toml.rust.as_ref().and_then(|r| r.channel.clone()) { - if channel == "auto-detect" { - config.channel = ci_channel.into(); - } else { - config.channel = channel; - } + let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); + let ci_channel = file_content.trim_end(); + + let toml_channel = toml.rust.as_ref().and_then(|r| r.channel.clone()); + let is_user_configured_rust_channel = match toml_channel { + Some(channel) if channel == "auto-detect" => { + config.channel = ci_channel.into(); true - } else { - false - }; + } + Some(channel) => { + config.channel = channel; + true + } + None => false, + }; let default = config.channel == "dev"; config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default); @@ -1887,6 +1888,10 @@ impl Config { && config.src.join(".cargo/config.toml").exists(), ); + if !is_user_configured_rust_channel && config.rust_info.is_from_tarball() { + config.channel = ci_channel.into(); + } + if let Some(rust) = toml.rust { let Rust { optimize: optimize_toml, @@ -2090,8 +2095,6 @@ impl Config { config.channel = channel; } - } else if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { - ci_channel.clone_into(&mut config.channel); } if let Some(llvm) = toml.llvm { diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 8e4a710178e..4ec2909b8fa 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -191,8 +191,13 @@ settings: specified atomic widths, e.g. the test with `//@ needs-target-has-atomic: 8, 16, ptr` will only run if it supports the comma-separated list of atomic widths. -- `needs-dynamic-linking` - ignores if target does not support dynamic linking +- `needs-dynamic-linking` — ignores if target does not support dynamic linking (which is orthogonal to it being unable to create `dylib` and `cdylib` crate types) +- `needs-crate-type` — ignores if target platform does not support one or more + of the comma-delimited list of specified crate types. For example, + `//@ needs-crate-type: cdylib, proc-macro` will cause the test to be ignored + on `wasm32-unknown-unknown` target because the target does not support the + `proc-macro` crate type. The following directives will check LLVM support: @@ -229,14 +234,14 @@ ignoring debuggers. ### Affecting how tests are built -| Directive | Explanation | Supported test suites | Possible values | -|---------------------|----------------------------------------------------------------------------------------------|---------------------------|------------------------------------------------------------------------------| -| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental`. | -| `edition` | Alias for `compile-flags: --edition=xxx` | All except for `run-make` | Any valid `--edition` value | -| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `<KEY>=<VALUE>` | -| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name | -| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A | -| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A | +| Directive | Explanation | Supported test suites | Possible values | +|---------------------|----------------------------------------------------------------------------------------------|---------------------------|--------------------------------------------------------------------------------------------| +| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` | +| `edition` | The edition used to build the test | All except for `run-make` | Any valid `--edition` value | +| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `<KEY>=<VALUE>` | +| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name | +| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A | +| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A | <div class="warning"> Tests (outside of `run-make`) that want to use incremental tests not in the diff --git a/src/doc/unstable-book/src/language-features/offset-of-enum.md b/src/doc/unstable-book/src/language-features/offset-of-enum.md index 1960d6299eb..78c0d87f639 100644 --- a/src/doc/unstable-book/src/language-features/offset-of-enum.md +++ b/src/doc/unstable-book/src/language-features/offset-of-enum.md @@ -1,4 +1,4 @@ -# `offset_of_slice` +# `offset_of_enum` The tracking issue for this feature is: [#120141] diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e0e09b53fc2..3a2b6974681 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -497,7 +497,7 @@ pub(crate) fn build_impl( }; let trait_item = tcx .associated_items(associated_trait.def_id) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, item.ident, assoc_kind, @@ -524,7 +524,7 @@ pub(crate) fn build_impl( if let Some(associated_trait) = associated_trait { let trait_item = tcx .associated_items(associated_trait.def_id) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, item.ident(tcx), item.kind, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ee6008b7851..45a915719e9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1088,7 +1088,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib enum FunctionArgs<'tcx> { Body(hir::BodyId), - Names(&'tcx [Option<Ident>]), + Idents(&'tcx [Option<Ident>]), } fn clean_function<'tcx>( @@ -1104,8 +1104,8 @@ fn clean_function<'tcx>( FunctionArgs::Body(body_id) => { clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id) } - FunctionArgs::Names(names) => { - clean_args_from_types_and_names(cx, sig.decl.inputs, names) + FunctionArgs::Idents(idents) => { + clean_args_from_types_and_names(cx, sig.decl.inputs, idents) } }; let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args); @@ -1117,7 +1117,7 @@ fn clean_function<'tcx>( fn clean_args_from_types_and_names<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], - names: &[Option<Ident>], + idents: &[Option<Ident>], ) -> Arguments { fn nonempty_name(ident: &Option<Ident>) -> Option<Symbol> { if let Some(ident) = ident @@ -1131,7 +1131,7 @@ fn clean_args_from_types_and_names<'tcx>( // If at least one argument has a name, use `_` as the name of unnamed // arguments. Otherwise omit argument names. - let default_name = if names.iter().any(|ident| nonempty_name(ident).is_some()) { + let default_name = if idents.iter().any(|ident| nonempty_name(ident).is_some()) { kw::Underscore } else { kw::Empty @@ -1143,7 +1143,7 @@ fn clean_args_from_types_and_names<'tcx>( .enumerate() .map(|(i, ty)| Argument { type_: clean_ty(ty, cx), - name: names.get(i).and_then(nonempty_name).unwrap_or(default_name), + name: idents.get(i).and_then(nonempty_name).unwrap_or(default_name), is_const: false, }) .collect(), @@ -1193,7 +1193,7 @@ fn clean_poly_fn_sig<'tcx>( did: Option<DefId>, sig: ty::PolyFnSig<'tcx>, ) -> FnDecl { - let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_names(did)).iter(); + let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_idents(did)).iter(); // We assume all empty tuples are default return type. This theoretically can discard `-> ()`, // but shouldn't change any code meaning. @@ -1270,8 +1270,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); MethodItem(m, None) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { - let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names)); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { + let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Idents(idents)); RequiredMethodItem(m) } hir::TraitItemKind::Type(bounds, Some(default)) => { @@ -2612,7 +2612,7 @@ fn clean_bare_fn_ty<'tcx>( .filter(|p| !is_elided_lifetime(p)) .map(|x| clean_generic_param(cx, None, x)) .collect(); - let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names); + let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_idents); let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args); (generic_params, decl) }); @@ -3148,8 +3148,8 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(sig, names, generics) => ForeignFunctionItem( - clean_function(cx, &sig, generics, FunctionArgs::Names(names)), + hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem( + clean_function(cx, &sig, generics, FunctionArgs::Idents(idents)), sig.header.safety(), ), hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c47e42670c9..c4dea79370d 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -321,6 +321,7 @@ pub(crate) fn create_config( (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a2808bddb3a..88eaa52c6de 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -191,6 +191,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions hash_untracked_state: None, register_lints: Some(Box::new(crate::lint::register_lints)), override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 334a7a86989..44134bda5ea 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -721,7 +721,7 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>( extra_info: Option<&ExtraInfo<'_>>, include_non_rust: bool, ) { - let mut parser = Parser::new(doc).into_offset_iter(); + let mut parser = Parser::new_ext(doc, main_body_opts()).into_offset_iter(); let mut prev_offset = 0; let mut nb_lines = 0; let mut register_header = None; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3512dff0865..21c823f49d1 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -13,6 +13,9 @@ //! is cloned per-thread and contains information about what is currently being //! rendered. //! +//! The main entry point to the rendering system is the implementation of +//! `FormatRenderer` on `Context`. +//! //! In order to speed up rendering (mostly because of markdown rendering), the //! rendering process has been parallelized. This parallelization is only //! exposed through the `crate` method on the context, and then also from the @@ -90,7 +93,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display { /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. #[derive(Copy, Clone, Debug)] -pub(crate) enum AssocItemRender<'a> { +enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } @@ -98,7 +101,7 @@ pub(crate) enum AssocItemRender<'a> { /// For different handling of associated items from the Deref target of a type rather than the type /// itself. #[derive(Copy, Clone, PartialEq)] -pub(crate) enum RenderMode { +enum RenderMode { Normal, ForDeref { mut_: bool }, } @@ -126,7 +129,7 @@ pub(crate) struct IndexItem { /// A type used for the search index. #[derive(Debug, Eq, PartialEq)] -pub(crate) struct RenderType { +struct RenderType { id: Option<RenderTypeId>, generics: Option<Vec<RenderType>>, bindings: Option<Vec<(RenderTypeId, Vec<RenderType>)>>, @@ -137,7 +140,7 @@ impl RenderType { // The contents of the lists are always integers in self-terminating hex // form, handled by `RenderTypeId::write_to_string`, so no commas are // needed to separate the items. - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { fn write_optional_id(id: Option<RenderTypeId>, string: &mut String) { // 0 is a sentinel, everything else is one-indexed match id { @@ -177,7 +180,7 @@ impl RenderType { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum RenderTypeId { +enum RenderTypeId { DefId(DefId), Primitive(clean::PrimitiveType), AssociatedType(Symbol), @@ -186,7 +189,7 @@ pub(crate) enum RenderTypeId { } impl RenderTypeId { - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { let id: i32 = match &self { // 0 is a sentinel, everything else is one-indexed // concrete type @@ -209,7 +212,7 @@ pub(crate) struct IndexItemFunctionType { } impl IndexItemFunctionType { - pub fn write_to_string<'a>( + fn write_to_string<'a>( &'a self, string: &mut String, backref_queue: &mut VecDeque<&'a IndexItemFunctionType>, @@ -309,7 +312,7 @@ impl ItemEntry { } impl ItemEntry { - pub(crate) fn print(&self) -> impl fmt::Display { + fn print(&self) -> impl fmt::Display { fmt::from_fn(move |f| write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name))) } } @@ -760,7 +763,7 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -pub(crate) fn render_impls( +fn render_impls( cx: &Context<'_>, mut w: impl Write, impls: &[&Impl], @@ -1201,7 +1204,7 @@ impl<'a> AssocItemLink<'a> { } } -pub fn write_section_heading( +fn write_section_heading( title: &str, id: &str, extra_class: Option<&str>, @@ -1226,7 +1229,7 @@ fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display { write_section_heading(title, id, None, "") } -pub(crate) fn render_all_impls( +fn render_all_impls( mut w: impl Write, cx: &Context<'_>, containing_item: &clean::Item, @@ -1473,10 +1476,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -pub(crate) fn notable_traits_button( - ty: &clean::Type, - cx: &Context<'_>, -) -> Option<impl fmt::Display> { +fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt::Display> { if ty.is_unit() { // Very common fast path. return None; @@ -1588,10 +1588,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { (format!("{:#}", ty.print(cx)), out) } -pub(crate) fn notable_traits_json<'a>( - tys: impl Iterator<Item = &'a clean::Type>, - cx: &Context<'_>, -) -> String { +fn notable_traits_json<'a>(tys: impl Iterator<Item = &'a clean::Type>, cx: &Context<'_>) -> String { let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect(); mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2)); struct NotableTraitsMap(Vec<(String, String)>); @@ -2171,7 +2168,7 @@ fn render_rightside( }) } -pub(crate) fn render_impl_summary( +fn render_impl_summary( cx: &Context<'_>, i: &Impl, parent: &clean::Item, diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index bcdca862862..692ce21d6cf 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -91,19 +91,21 @@ impl DocFolder for Stripper<'_, '_> { if let clean::ImportItem(clean::Import { source, .. }) = &i.kind && let Some(source_did) = source.did - && let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { - let reexports = reexport_chain(self.tcx, import_def_id, source_did); + if self.tcx.is_doc_hidden(source_did) { + return None; + } else if let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { + let reexports = reexport_chain(self.tcx, import_def_id, source_did); - // Check if any reexport in the chain has a hidden source - let has_hidden_source = reexports - .iter() - .filter_map(|reexport| reexport.id()) - .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)) - || self.tcx.is_doc_hidden(source_did); + // Check if any reexport in the chain has a hidden source + let has_hidden_source = reexports + .iter() + .filter_map(|reexport| reexport.id()) + .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)); - if has_hidden_source { - return None; + if has_hidden_source { + return None; + } } } diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 94c170d73af..f5a8e3dc387 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -25,6 +25,7 @@ path = "src/driver.rs" [dependencies] clippy_config = { path = "clippy_config" } clippy_lints = { path = "clippy_lints" } +clippy_utils = { path = "clippy_utils" } rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } tempfile = { version = "3.3", optional = true } termize = "0.1" diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs index cd38aed26a3..7fab97d3ea1 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -1,10 +1,10 @@ use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, MsrvStack}; +use clippy_utils::sym; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::EarlyContext; -use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { // check cfg_attr @@ -18,7 +18,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { && msrv.meets(msrvs::TOOL_ATTRIBUTES) // check for `rustfmt_skip` and `rustfmt::skip` && let Some(skip_item) = &items[1].meta_item() - && (skip_item.has_name(sym!(rustfmt_skip)) + && (skip_item.has_name(sym::rustfmt_skip) || skip_item .path .segments diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index e3e081ce08e..1cb43ab02a3 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -2,10 +2,10 @@ use super::USELESS_ATTRIBUTE; use super::utils::{is_lint_level, is_word, namespace_and_lint}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, first_line_of_span}; +use clippy_utils::sym; use rustc_ast::{Attribute, Item, ItemKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; -use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); @@ -61,7 +61,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { if is_word(lint, sym::unused_imports) && skip_unused_imports { return; } - if is_word(lint, sym!(unused_extern_crates)) { + if is_word(lint, sym::unused_extern_crates) { return; } }, diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index adac2f27ea8..ad18c7039ee 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -53,7 +53,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - .not_trait() .filter(|trait_id| implements_trait(cx, ty, *trait_id, &[])) .and_then(|trait_id| { - cx.tcx.associated_items(trait_id).find_by_name_and_kind( + cx.tcx.associated_items(trait_id).find_by_ident_and_kind( cx.tcx, Ident::from_str("Output"), ty::AssocKind::Type, diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index f6c10da1596..bf549dcdb50 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -38,7 +38,7 @@ pub fn check( // of all `#[test]` attributes in not ignored code examples fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) { rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, None, || { + rustc_span::create_session_globals_then(edition, &[], None, || { let mut test_attr_spans = vec![]; let filename = FileName::anon_source_code(&code); diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index 041f6228fba..4495aeb5953 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -22,8 +22,8 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored && let Some(did) = trait_item_def_id_of_impl(items, item.owner_id) && !is_from_ignored_trait(trait_ref, ignored_traits) { - let mut param_idents_iter = cx.tcx.hir_body_param_names(body_id); - let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied(); + let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id); + let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied(); let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter); if !renames.0.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 56ff7e2c61b..239ee6c729f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -238,7 +238,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - .instantiate_bound_regions_with_erased(sig.rebind(search_ty)) .kind() && let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) - && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_name_and_kind( + && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_ident_and_kind( cx.tcx, Ident::with_dummy_span(sym::Item), AssocKind::Type, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index bcb0f8349e2..9f450d654d5 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3,6 +3,7 @@ #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] +#![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![feature(let_chains)] #![feature(never_type)] @@ -74,6 +75,7 @@ pub mod qualify_min_const_fn; pub mod source; pub mod str_utils; pub mod sugg; +pub mod sym; pub mod ty; pub mod usage; pub mod visitors; @@ -126,7 +128,7 @@ use rustc_middle::ty::{ use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; -use rustc_span::{InnerSpan, Span, sym}; +use rustc_span::{InnerSpan, Span}; use visitors::{Visitable, for_each_unconsumed_temporary}; use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; @@ -3502,7 +3504,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::c ::d::sym refers to // e::f::sym:: :: // result should be super::super::super::super::e::f - if let DefPathData::TypeNs(Some(s)) = l { + if let DefPathData::TypeNs(s) = l { path.push(s.to_string()); } if let DefPathData::TypeNs(_) = r { @@ -3513,7 +3515,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::sym:: :: refers to // c::d::e ::f::sym // when looking at `f` - Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()), + Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()), // consider: // a::b::c ::d::sym refers to // e::f::sym:: :: @@ -3527,7 +3529,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // `super` chain would be too long, just use the absolute path instead once(String::from("crate")) .chain(to.data.iter().filter_map(|el| { - if let DefPathData::TypeNs(Some(sym)) = el.data { + if let DefPathData::TypeNs(sym) = el.data { Some(sym.to_string()) } else { None diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs new file mode 100644 index 00000000000..9cc72a5b3aa --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -0,0 +1,23 @@ +#![allow(non_upper_case_globals)] + +use rustc_span::symbol::{Symbol, PREDEFINED_SYMBOLS_COUNT}; + +pub use rustc_span::sym::*; + +macro_rules! generate { + ($($sym:ident,)*) => { + /// To be supplied to `rustc_interface::Config` + pub const EXTRA_SYMBOLS: &[&str] = &[ + $(stringify!($sym),)* + ]; + + $( + pub const $sym: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()}); + )* + }; +} + +generate! { + rustfmt_skip, + unused_extern_crates, +} diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 6fdf4c244f8..29cbf62c3d4 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -1109,7 +1109,7 @@ pub fn make_projection<'tcx>( assoc_ty: Symbol, args: GenericArgsRef<'tcx>, ) -> Option<AliasTy<'tcx>> { - let Some(assoc_item) = tcx.associated_items(container_id).find_by_name_and_kind( + let Some(assoc_item) = tcx.associated_items(container_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index e4092bcd105..df9c4e8e6ae 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -160,6 +160,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { clippy_lints::register_lints(lint_store, conf); clippy_lints::register_pre_expansion_lints(lint_store, conf); })); + config.extra_symbols = clippy_utils::sym::EXTRA_SYMBOLS.into(); // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be // run on the unoptimized MIR. On the other hand this results in some false negatives. If diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 06e618c2d25..3db34ed24cc 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "compiletest" version = "0.0.0" -edition = "2021" +edition = "2024" [lib] doctest = false diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 36218b2f904..6750b5288f4 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -395,6 +395,7 @@ pub struct Config { pub target_cfgs: OnceLock<TargetCfgs>, pub builtin_cfg_names: OnceLock<HashSet<String>>, + pub supported_crate_types: OnceLock<HashSet<String>>, pub nocapture: bool, @@ -472,6 +473,11 @@ impl Config { self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self)) } + /// Get the list of crate types that the target platform supports. + pub fn supported_crate_types(&self) -> &HashSet<String> { + self.supported_crate_types.get_or_init(|| supported_crate_types(self)) + } + pub fn has_threads(&self) -> bool { // Wasm targets don't have threads unless `-threads` is in the target // name, such as `wasm32-wasip1-threads`. @@ -745,6 +751,31 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> { .collect() } +pub const KNOWN_CRATE_TYPES: &[&str] = + &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]; + +fn supported_crate_types(config: &Config) -> HashSet<String> { + let crate_types: HashSet<_> = rustc_output( + config, + &["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"], + Default::default(), + ) + .lines() + .map(|l| l.to_string()) + .collect(); + + for crate_type in crate_types.iter() { + assert!( + KNOWN_CRATE_TYPES.contains(&crate_type.as_str()), + "unexpected crate type `{}`: known crate types are {:?}", + crate_type, + KNOWN_CRATE_TYPES + ); + } + + crate_types +} + fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String { let mut command = Command::new(&config.rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs index 20e3c8dfb9e..5126e55aea1 100644 --- a/src/tools/compiletest/src/debuggers.rs +++ b/src/tools/compiletest/src/debuggers.rs @@ -40,7 +40,9 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> { // // we should figure out how to lift this restriction! (run them all // on different ports allocated dynamically). - env::set_var("RUST_TEST_THREADS", "1"); + // + // SAFETY: at this point we are still single-threaded. + unsafe { env::set_var("RUST_TEST_THREADS", "1") }; } Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 44d9c0330f7..086a8a67456 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -133,6 +133,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "needs-asm-support", + "needs-crate-type", "needs-deterministic-layouts", "needs-dlltool", "needs-dynamic-linking", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 36a9e5df583..3406e8749a1 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -389,14 +389,22 @@ impl TestProps { } if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { - self.compile_flags.extend(split_flags(&flags)); + let flags = split_flags(&flags); + for flag in &flags { + if flag == "--edition" || flag.starts_with("--edition=") { + panic!("you must use `//@ edition` to configure the edition"); + } + } + self.compile_flags.extend(flags); } if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); } if let Some(edition) = config.parse_edition(ln) { - self.compile_flags.push(format!("--edition={}", edition.trim())); + // The edition is added at the start, since flags from //@compile-flags must + // be passed to rustc last. + self.compile_flags.insert(0, format!("--edition={}", edition.trim())); has_edition = true; } @@ -452,7 +460,7 @@ impl TestProps { ln, UNSET_EXEC_ENV, &mut self.unset_exec_env, - |r| r, + |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, @@ -464,7 +472,7 @@ impl TestProps { ln, UNSET_RUSTC_ENV, &mut self.unset_rustc_env, - |r| r, + |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, @@ -624,7 +632,9 @@ impl TestProps { } if let (Some(edition), false) = (&config.edition, has_edition) { - self.compile_flags.push(format!("--edition={}", edition)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={}", edition)); } } @@ -997,16 +1007,13 @@ impl Config { fn parse_env(nv: String) -> (String, String) { // nv is either FOO or FOO=BAR - let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect(); - - match strs.len() { - 1 => (strs.pop().unwrap(), String::new()), - 2 => { - let end = strs.pop().unwrap(); - (strs.pop().unwrap(), end) - } - n => panic!("Expected 1 or 2 strings, not {}", n), - } + // FIXME(Zalathar): The form without `=` seems to be unused; should + // we drop support for it? + let (name, value) = nv.split_once('=').unwrap_or((&nv, "")); + // Trim whitespace from the name, so that `//@ exec-env: FOO=BAR` + // sees the name as `FOO` and not ` FOO`. + let name = name.trim(); + (name.to_owned(), value.to_owned()) } fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 12f0790fb10..2ace40c490b 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; +use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; use crate::header::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( @@ -6,7 +6,7 @@ pub(super) fn handle_needs( config: &Config, ln: &str, ) -> IgnoreDecision { - // Note thet we intentionally still put the needs- prefix here to make the file show up when + // Note that we intentionally still put the needs- prefix here to make the file show up when // grepping for a directive name, even though we could technically strip that. let needs = &[ Need { @@ -224,6 +224,50 @@ pub(super) fn handle_needs( } } + // FIXME(jieyouxu): share multi-value directive logic with `needs-target-has-atomic` above. + if name == "needs-crate-type" { + let Some(rest) = rest else { + return IgnoreDecision::Error { + message: + "expected `needs-crate-type` to have a comma-separated list of crate types" + .to_string(), + }; + }; + + // Expect directive value to be a list of comma-separated crate-types. + let specified_crate_types = rest + .split(',') + .map(|crate_type| crate_type.trim()) + .map(ToString::to_string) + .collect::<Vec<String>>(); + + for crate_type in &specified_crate_types { + if !KNOWN_CRATE_TYPES.contains(&crate_type.as_str()) { + return IgnoreDecision::Error { + message: format!( + "unknown crate type specified in `needs-crate-type`: `{crate_type}` is not \ + a known crate type, known values are `{:?}`", + KNOWN_CRATE_TYPES + ), + }; + } + } + + let satisfies_all_crate_types = specified_crate_types + .iter() + .all(|specified| config.supported_crate_types().contains(specified)); + if satisfies_all_crate_types { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!( + "skipping test as target does not support all of the crate types `{:?}`", + specified_crate_types + ), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 1a796cdd7cd..f3461f3c244 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -902,3 +902,41 @@ fn test_rustc_abi() { assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2")); assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2")); } + +#[test] +fn test_supported_crate_types() { + // Basic assumptions check on under-test compiler's `--print=supported-crate-types` output based + // on knowledge about the cherry-picked `x86_64-unknown-linux-gnu` and `wasm32-unknown-unknown` + // targets. Also smoke tests the `needs-crate-type` directive itself. + + use std::collections::HashSet; + + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + assert_eq!( + config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(), + HashSet::from(["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]), + ); + assert!(!check_ignore(&config, "//@ needs-crate-type: rlib")); + assert!(!check_ignore(&config, "//@ needs-crate-type: dylib")); + assert!(!check_ignore( + &config, + "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib" + )); + + let config = cfg().target("wasm32-unknown-unknown").build(); + assert_eq!( + config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(), + HashSet::from(["bin", "cdylib", "lib", "rlib", "staticlib"]), + ); + + // rlib is supported + assert!(!check_ignore(&config, "//@ needs-crate-type: rlib")); + // dylib is not + assert!(check_ignore(&config, "//@ needs-crate-type: dylib")); + // If multiple crate types are specified, then all specified crate types need to be supported. + assert!(check_ignore(&config, "//@ needs-crate-type: cdylib, dylib")); + assert!(check_ignore( + &config, + "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib" + )); +} diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 782f6e0f2d8..720663b30ef 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -431,6 +431,7 @@ pub fn parse_config(args: Vec<String>) -> Config { target_cfgs: OnceLock::new(), builtin_cfg_names: OnceLock::new(), + supported_crate_types: OnceLock::new(), nocapture: matches.opt_present("no-capture"), @@ -529,10 +530,14 @@ pub fn run_tests(config: Arc<Config>) { } // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary - env::set_var("__COMPAT_LAYER", "RunAsInvoker"); - - // Let tests know which target they're running as - env::set_var("TARGET", &config.target); + // + // SAFETY: at this point we're still single-threaded. + unsafe { env::set_var("__COMPAT_LAYER", "RunAsInvoker") }; + + // Let tests know which target they're running as. + // + // SAFETY: at this point we're still single-threaded. + unsafe { env::set_var("TARGET", &config.target) }; let mut configs = Vec::new(); if let Mode::DebugInfo = config.mode { diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs index 7b12ba946b9..653b125a6b4 100644 --- a/src/tools/compiletest/src/raise_fd_limit.rs +++ b/src/tools/compiletest/src/raise_fd_limit.rs @@ -6,6 +6,7 @@ /// This fixes issue #7772. #[cfg(target_vendor = "apple")] #[allow(non_camel_case_types)] +// FIXME(#139616): document caller contract. pub unsafe fn raise_fd_limit() { use std::ptr::null_mut; use std::{cmp, io}; @@ -21,8 +22,10 @@ pub unsafe fn raise_fd_limit() { let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; let mut maxfiles: libc::c_int = 0; let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; - if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0) - != 0 + // FIXME(#139616): justify why this is sound. + if unsafe { + libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0) + } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); @@ -30,7 +33,8 @@ pub unsafe fn raise_fd_limit() { // Fetch the current resource limits let mut rlim = libc::rlimit { rlim_cur: 0, rlim_max: 0 }; - if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 { + // FIXME(#139616): justify why this is sound. + if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } @@ -41,7 +45,8 @@ pub unsafe fn raise_fd_limit() { rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max); // Set our newly-increased resource limit. - if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 { + // FIXME(#139616): justify why this is sound. + if unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 28ca5589992..2213dd07160 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -165,6 +165,7 @@ mod imp { mut err_pipe: ChildStderr, data: &mut dyn FnMut(bool, &mut Vec<u8>, bool), ) -> io::Result<()> { + // FIXME(#139616): justify why this is sound. unsafe { libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); @@ -175,6 +176,7 @@ mod imp { let mut out = Vec::new(); let mut err = Vec::new(); + // FIXME(#139616): justify why this is sound. let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; fds[0].fd = out_pipe.as_raw_fd(); fds[0].events = libc::POLLIN; @@ -185,6 +187,7 @@ mod imp { while nfds > 0 { // wait for either pipe to become readable using `select` + // FIXME(#139616): justify why this is sound. let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) }; if r == -1 { let err = io::Error::last_os_error(); @@ -256,6 +259,7 @@ mod imp { port.add_handle(0, &out_pipe)?; port.add_handle(1, &err_pipe)?; + // FIXME(#139616): justify why this is sound. unsafe { let mut out_pipe = Pipe::new(out_pipe, &mut out); let mut err_pipe = Pipe::new(err_pipe, &mut err); @@ -284,18 +288,23 @@ mod imp { } impl<'a> Pipe<'a> { + // FIXME(#139616): document caller contract. unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> { Pipe { dst, - pipe: NamedPipe::from_raw_handle(p.into_raw_handle()), + // FIXME(#139616): justify why this is sound. + pipe: unsafe { NamedPipe::from_raw_handle(p.into_raw_handle()) }, overlapped: Overlapped::zero(), done: false, } } + // FIXME(#139616): document caller contract. unsafe fn read(&mut self) -> io::Result<()> { - let dst = slice_to_end(self.dst); - match self.pipe.read_overlapped(dst, self.overlapped.raw()) { + // FIXME(#139616): justify why this is sound. + let dst = unsafe { slice_to_end(self.dst) }; + // FIXME(#139616): justify why this is sound. + match unsafe { self.pipe.read_overlapped(dst, self.overlapped.raw()) } { Ok(_) => Ok(()), Err(e) => { if e.raw_os_error() == Some(ERROR_BROKEN_PIPE.0 as i32) { @@ -308,15 +317,18 @@ mod imp { } } + // FIXME(#139616): document caller contract. unsafe fn complete(&mut self, status: &CompletionStatus) { let prev = self.dst.len(); - self.dst.set_len(prev + status.bytes_transferred() as usize); + // FIXME(#139616): justify why this is sound. + unsafe { self.dst.set_len(prev + status.bytes_transferred() as usize) }; if status.bytes_transferred() == 0 { self.done = true; } } } + // FIXME(#139616): document caller contract. unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] { if v.capacity() == 0 { v.reserve(16); @@ -324,6 +336,12 @@ mod imp { if v.capacity() == v.len() { v.reserve(1); } - slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize), v.capacity() - v.len()) + // FIXME(#139616): justify why this is sound. + unsafe { + slice::from_raw_parts_mut( + v.as_mut_ptr().offset(v.len() as isize), + v.capacity() - v.len(), + ) + } } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2805e6b3d62..208d32833c9 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -177,6 +177,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); config.run.hash(&mut hash); + config.edition.hash(&mut hash); match config.debugger { Some(Debugger::Cdb) => { @@ -445,8 +446,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), src, ) } @@ -968,16 +969,16 @@ impl<'test> TestCx<'test> { delete_after_success: bool, ) -> ProcRes { let prepare_env = |cmd: &mut Command| { - for key in &self.props.unset_exec_env { - cmd.env_remove(key); - } - for (key, val) in &self.props.exec_env { cmd.env(key, val); } for (key, val) in env_extra { cmd.env(key, val); } + + for key in &self.props.unset_exec_env { + cmd.env_remove(key); + } }; let proc_res = match &*self.config.target { @@ -1020,8 +1021,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( test_client, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1035,8 +1036,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( wr_run, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1050,8 +1051,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( program, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1197,8 +1198,8 @@ impl<'test> TestCx<'test> { self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove); self.compose_and_run( rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), input, ) } @@ -1219,8 +1220,7 @@ impl<'test> TestCx<'test> { rustc.args(&["--crate-type", "rlib"]); rustc.arg("-Cpanic=abort"); - let res = - self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), None, None); + let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None); if !res.status.success() { self.fatal_proc_rec( &format!( @@ -1332,8 +1332,8 @@ impl<'test> TestCx<'test> { let auxres = aux_cx.compose_and_run( aux_rustc, - aux_cx.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + aux_cx.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), None, ); if !auxres.status.success() { @@ -1373,8 +1373,8 @@ impl<'test> TestCx<'test> { fn compose_and_run( &self, mut command: Command, - lib_path: &str, - aux_path: Option<&str>, + lib_path: &Path, + aux_path: Option<&Path>, input: Option<String>, ) -> ProcRes { let cmdline = { @@ -1806,7 +1806,7 @@ impl<'test> TestCx<'test> { } } - fn make_cmdline(&self, command: &Command, libpath: &str) -> String { + fn make_cmdline(&self, command: &Command, libpath: &Path) -> String { use crate::util; // Linux and mac don't require adjusting the library search path @@ -1819,7 +1819,7 @@ impl<'test> TestCx<'test> { format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) } - format!("{} {:?}", lib_path_cmd_prefix(libpath), command) + format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command) } } @@ -1980,7 +1980,8 @@ impl<'test> TestCx<'test> { // Add custom flags supplied by the `filecheck-flags:` test header. filecheck.args(&self.props.filecheck_flags); - self.compose_and_run(filecheck, "", None, None) + // FIXME(jieyouxu): don't pass an empty Path + self.compose_and_run(filecheck, Path::new(""), None, None) } fn charset() -> &'static str { diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 170b8a80996..50e733cd31b 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -104,7 +104,7 @@ impl TestCx<'_> { let debugger_run_result = self.compose_and_run( cdb, - self.config.run_lib_path.to_str().unwrap(), + self.config.run_lib_path.as_path(), None, // aux_path None, // input ); @@ -241,7 +241,8 @@ impl TestCx<'_> { let cmdline = { let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); gdb.args(debugger_opts); - let cmdline = self.make_cmdline(&gdb, ""); + // FIXME(jieyouxu): don't pass an empty Path + let cmdline = self.make_cmdline(&gdb, Path::new("")); logv(self.config, format!("executing {}", cmdline)); cmdline }; @@ -340,7 +341,7 @@ impl TestCx<'_> { gdb.args(debugger_opts).env("PYTHONPATH", pythonpath); debugger_run_result = - self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, None); + self.compose_and_run(gdb, self.config.run_lib_path.as_path(), None, None); } if !debugger_run_result.status.success() { diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d2b8b514730..d1107e51509 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -7d7de5bf3c3cbf9c2c5bbc5cbfb9197a8a427d35 +1bc56185ee257ed829a0aea7abdc3b03c5fed887 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 56ee96502b3..4e8fe0ca8ad 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -185,7 +185,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0)); sync::par_for_each_in(many_seeds.seeds.clone(), |seed| { let mut config = config.clone(); - config.seed = Some(seed.into()); + config.seed = Some((*seed).into()); eprintln!("Trying seed: {seed}"); let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, config) .unwrap_or(rustc_driver::EXIT_FAILURE); diff --git a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs new file mode 100644 index 00000000000..27ea12398d8 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs @@ -0,0 +1,30 @@ +use std::mem::{align_of, size_of}; + +// See <https://github.com/rust-lang/rust/issues/134713> + +#[repr(C)] +struct Foo(usize, u8); + +fn main() { + let buf1: [usize; 2] = [1000, 2000]; + let buf2: [usize; 2] = [3000, 4000]; + + // Foo and [usize; 2] have the same size and alignment, + // so swap_nonoverlapping should treat them the same + assert_eq!(size_of::<Foo>(), size_of::<[usize; 2]>()); + assert_eq!(align_of::<Foo>(), align_of::<[usize; 2]>()); + + let mut b1 = buf1; + let mut b2 = buf2; + // Safety: b1 and b2 are distinct local variables, + // with the same size and alignment as Foo. + unsafe { + std::ptr::swap_nonoverlapping( + b1.as_mut_ptr().cast::<Foo>(), + b2.as_mut_ptr().cast::<Foo>(), + 1, + ); + } + assert_eq!(b1, buf2); + assert_eq!(b2, buf1); +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1a57d2b182a..bf3b4112324 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -361,7 +361,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "rustc-demangle", "rustc-hash", "rustc-literal-escaper", - "rustc-rayon", "rustc-rayon-core", "rustc-stable-hash", "rustc_apfloat", diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs index 7436e241823..07f25d1e1a4 100644 --- a/tests/assembly/cstring-merging.rs +++ b/tests/assembly/cstring-merging.rs @@ -1,6 +1,7 @@ //@ only-linux //@ assembly-output: emit-asm -//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024 +//@ compile-flags: --crate-type=lib -Copt-level=3 +//@ edition: 2024 use std::ffi::CStr; diff --git a/tests/assembly/x86_64-typed-swap.rs b/tests/assembly/x86_64-typed-swap.rs index dfd6ee565bc..a6753011d36 100644 --- a/tests/assembly/x86_64-typed-swap.rs +++ b/tests/assembly/x86_64-typed-swap.rs @@ -51,3 +51,31 @@ pub fn swap_simd(x: &mut __m128, y: &mut __m128) { // CHECK-NEXT: retq swap(x, y) } + +// CHECK-LABEL: swap_string: +#[no_mangle] +pub fn swap_string(x: &mut String, y: &mut String) { + // CHECK-NOT: mov + // CHECK-COUNT-4: movups + // CHECK-NOT: mov + // CHECK-COUNT-4: movq + // CHECK-NOT: mov + swap(x, y) +} + +// CHECK-LABEL: swap_44_bytes: +#[no_mangle] +pub fn swap_44_bytes(x: &mut [u8; 44], y: &mut [u8; 44]) { + // Ensure we do better than a long run of byte copies, + // see <https://github.com/rust-lang/rust/issues/134946> + + // CHECK-NOT: movb + // CHECK-COUNT-8: movups{{.+}}xmm + // CHECK-NOT: movb + // CHECK-COUNT-4: movq + // CHECK-NOT: movb + // CHECK-COUNT-4: movl + // CHECK-NOT: movb + // CHECK: retq + swap(x, y) +} diff --git a/tests/assembly/x86_64-windows-float-abi.rs b/tests/assembly/x86_64-windows-float-abi.rs index e8900be1aae..cbc80910851 100644 --- a/tests/assembly/x86_64-windows-float-abi.rs +++ b/tests/assembly/x86_64-windows-float-abi.rs @@ -37,7 +37,8 @@ pub extern "C" fn second_f64(_: f64, x: f64) -> f64 { } // CHECK-LABEL: second_f128 -// CHECK: movaps %xmm1, %xmm0 +// FIXME(llvm21): this can be just %rdx instead of the regex once we don't test on LLVM 20 +// CHECK: movaps {{(%xmm1|\(%rdx\))}}, %xmm0 // CHECK-NEXT: retq #[no_mangle] pub extern "C" fn second_f128(_: f128, x: f128) -> f128 { diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs index 2d67e02eb9c..b5b369e6e54 100644 --- a/tests/codegen/async-closure-debug.rs +++ b/tests/codegen/async-closure-debug.rs @@ -1,6 +1,7 @@ // Just make sure that async closures don't ICE. // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "async_closure_test" diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs index ab13d4509e2..50860c90662 100644 --- a/tests/codegen/async-fn-debug-awaitee-field.rs +++ b/tests/codegen/async-fn-debug-awaitee-field.rs @@ -7,7 +7,8 @@ //@[MSVC] only-msvc //@[NONMSVC] ignore-msvc -//@ compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0 +//@ compile-flags: -C debuginfo=2 -Copt-level=0 +//@ edition: 2018 #![crate_type = "lib"] diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs index 7c695042b42..e0c601146f8 100644 --- a/tests/codegen/async-fn-debug-msvc.rs +++ b/tests/codegen/async-fn-debug-msvc.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ only-msvc async fn foo() {} @@ -19,23 +20,23 @@ async fn async_fn_test() { // CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_msvc::async_fn_test::async_fn_env$0>", // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: file: [[FILE]], line: 13, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE]], line: 15, // CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) diff --git a/tests/codegen/async-fn-debug.rs b/tests/codegen/async-fn-debug.rs index 7be4ad45665..ed704c7cc8b 100644 --- a/tests/codegen/async-fn-debug.rs +++ b/tests/codegen/async-fn-debug.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc async fn foo() {} @@ -22,26 +23,26 @@ async fn async_fn_test() { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: file: [[FILE]], line: 13, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs index d00667a37d5..ff62e9709b4 100644 --- a/tests/codegen/coroutine-debug.rs +++ b/tests/codegen/coroutine-debug.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc #![feature(coroutines, coroutine_trait)] @@ -27,26 +28,26 @@ fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 15, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 19, +// CHECK-SAME: file: [[FILE]], line: 20, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 19, +// CHECK-SAME: file: [[FILE]], line: 20, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 16, +// CHECK-SAME: file: [[FILE]], line: 17, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], diff --git a/tests/codegen/debuginfo-generic-closure-env-names.rs b/tests/codegen/debuginfo-generic-closure-env-names.rs index 6b314c9abae..64bc58e1df7 100644 --- a/tests/codegen/debuginfo-generic-closure-env-names.rs +++ b/tests/codegen/debuginfo-generic-closure-env-names.rs @@ -18,7 +18,8 @@ // legacy mangling scheme rustc version and generic parameters are both hashed into a single part // of the name, thus randomizing item order with respect to rustc version. -//@ compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0 +//@ edition: 2021 // non_generic_closure() // NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs index 3756fafe384..c2297c58e77 100644 --- a/tests/codegen/infallible-unwrap-in-opt-z.rs +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -C opt-level=z --edition=2021 +//@ compile-flags: -C opt-level=z +//@ edition: 2021 #![crate_type = "lib"] diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs index 53a179160dc..c31419cb914 100644 --- a/tests/codegen/inline-function-args-debug-info.rs +++ b/tests/codegen/inline-function-args-debug-info.rs @@ -2,7 +2,8 @@ // gets inlined by MIR inlining. Without function argument indexes, `info args` in gdb won't show // arguments and their values for the current function. -//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2 --edition=2021 +//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2 +//@ edition: 2021 #![crate_type = "lib"] @@ -14,9 +15,9 @@ pub fn outer_function(x: usize, y: usize) -> usize { #[inline] fn inner_function(aaaa: usize, bbbb: usize) -> usize { // CHECK: !DILocalVariable(name: "aaaa", arg: 1 - // CHECK-SAME: line: 15 + // CHECK-SAME: line: 16 // CHECK-NOT: !DILexicalBlock( // CHECK: !DILocalVariable(name: "bbbb", arg: 2 - // CHECK-SAME: line: 15 + // CHECK-SAME: line: 16 aaaa + bbbb } diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 7fb850ca253..96cdff64dda 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -1,8 +1,16 @@ //@ compile-flags: -Copt-level=3 -//@ revisions: host x86-64-v3 +//@ revisions: host x86-64 x86-64-v3 //@ min-llvm-version: 20 -// This particular CPU regressed in #131563 +//@[host] ignore-x86_64 + +// Set the base cpu explicitly, in case the default has been changed. +//@[x86-64] only-x86_64 +//@[x86-64] compile-flags: -Ctarget-cpu=x86-64 + +// FIXME(cuviper) x86-64-v3 in particular regressed in #131563, and the workaround +// at the time still sometimes fails, so only verify it for the power-of-two size +// - https://github.com/llvm/llvm-project/issues/134735 //@[x86-64-v3] only-x86_64 //@[x86-64-v3] compile-flags: -Ctarget-cpu=x86-64-v3 @@ -11,7 +19,16 @@ #[no_mangle] pub fn test() -> usize { // CHECK-LABEL: @test( - // CHECK: ret {{i64|i32}} 165 + // host: ret {{i64|i32}} 165 + // x86-64: ret {{i64|i32}} 165 + + // FIXME: Now that this autovectorizes via a masked load, it doesn't actually + // const-fold for certain widths. The `test_eight` case below shows that, yes, + // what we're emitting *can* be const-folded, except that the way LLVM does it + // for certain widths doesn't today. We should be able to put this back to + // the same check after <https://github.com/llvm/llvm-project/issues/134513> + // x86-64-v3: masked.load + let values = [23, 16, 54, 3, 60, 9]; let mut acc = 0; for item in values { @@ -19,3 +36,15 @@ pub fn test() -> usize { } acc } + +#[no_mangle] +pub fn test_eight() -> usize { + // CHECK-LABEL: @test_eight( + // CHECK: ret {{i64|i32}} 220 + let values = [23, 16, 54, 3, 60, 9, 13, 42]; + let mut acc = 0; + for item in values { + acc += item; + } + acc +} diff --git a/tests/codegen/issues/issue-119422.rs b/tests/codegen/issues/issue-119422.rs index e1a082c377f..17ae71605b5 100644 --- a/tests/codegen/issues/issue-119422.rs +++ b/tests/codegen/issues/issue-119422.rs @@ -1,7 +1,8 @@ //! This test checks that compiler don't generate useless compares to zeros //! for `NonZero` integer types. //! -//@ compile-flags: -Copt-level=3 --edition=2021 -Zmerge-functions=disabled +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//@ edition: 2021 //@ only-64bit (because the LLVM type of i64 for usize shows up) #![crate_type = "lib"] diff --git a/tests/codegen/simd/extract-insert-dyn.rs b/tests/codegen/simd/extract-insert-dyn.rs new file mode 100644 index 00000000000..584e2c7887a --- /dev/null +++ b/tests/codegen/simd/extract-insert-dyn.rs @@ -0,0 +1,75 @@ +//@compile-flags: -C opt-level=3 -C no-prepopulate-passes + +#![feature(core_intrinsics, repr_simd)] +#![no_std] +#![crate_type = "lib"] +#![allow(non_camel_case_types)] + +// Test that `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}` +// lower to an LLVM extractelement or insertelement operation. + +use core::intrinsics::simd::{simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn}; + +#[repr(simd)] +#[derive(Clone, Copy)] +pub struct u32x16([u32; 16]); + +#[repr(simd)] +#[derive(Clone, Copy)] +pub struct i8x16([i8; 16]); + +// CHECK-LABEL: dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 %idx +#[no_mangle] +unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 { + simd_extract_dyn(x, idx) +} + +// CHECK-LABEL: literal_dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 { + simd_extract_dyn(x, 7) +} + +// CHECK-LABEL: const_dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 { + simd_extract_dyn(x, const { 3 + 4 }) +} + +// CHECK-LABEL: const_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 { + simd_extract(x, const { 3 + 4 }) +} + +// CHECK-LABEL: dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx +#[no_mangle] +unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 { + simd_insert_dyn(x, idx, e) +} + +// CHECK-LABEL: literal_dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert_dyn(x, 7, e) +} + +// CHECK-LABEL: const_dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert_dyn(x, const { 3 + 4 }, e) +} + +// CHECK-LABEL: const_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert(x, const { 3 + 4 }, e) +} diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs index fb9b61884e7..95117b2c748 100644 --- a/tests/codegen/simd/simd-wide-sum.rs +++ b/tests/codegen/simd/simd-wide-sum.rs @@ -1,5 +1,6 @@ //@ revisions: llvm mir-opt3 -//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021 +//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled +//@ edition: 2021 //@ only-x86_64 //@ [mir-opt3]compile-flags: -Zmir-opt-level=3 //@ [mir-opt3]build-pass diff --git a/tests/codegen/simd/swap-simd-types.rs b/tests/codegen/simd/swap-simd-types.rs index 69767d0a755..c063cc683a6 100644 --- a/tests/codegen/simd/swap-simd-types.rs +++ b/tests/codegen/simd/swap-simd-types.rs @@ -23,8 +23,8 @@ pub fn swap_single_m256(x: &mut __m256, y: &mut __m256) { #[no_mangle] pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { // CHECK-NOT: alloca - // CHECK: load <8 x float>{{.+}}align 32 - // CHECK: store <8 x float>{{.+}}align 32 + // CHECK-COUNT-2: load <4 x i64>{{.+}}align 32 + // CHECK-COUNT-2: store <4 x i64>{{.+}}align 32 if x.len() == y.len() { x.swap_with_slice(y); } @@ -34,7 +34,7 @@ pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { #[no_mangle] pub fn swap_bytes32(x: &mut [u8; 32], y: &mut [u8; 32]) { // CHECK-NOT: alloca - // CHECK: load <32 x i8>{{.+}}align 1 - // CHECK: store <32 x i8>{{.+}}align 1 + // CHECK-COUNT-2: load <4 x i64>{{.+}}align 1 + // CHECK-COUNT-2: store <4 x i64>{{.+}}align 1 swap(x, y) } diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs index 49a41bb1469..08c486affd9 100644 --- a/tests/codegen/swap-large-types.rs +++ b/tests/codegen/swap-large-types.rs @@ -12,6 +12,16 @@ type KeccakBuffer = [[u64; 5]; 5]; // to stack for large types, which is completely unnecessary as the lack of // overlap means we can just do whatever fits in registers at a time. +// The tests here (after the first one showing that the problem still exists) +// are less about testing *exactly* what the codegen is, and more about testing +// 1) That things are swapped directly from one argument to the other, +// never going through stack along the way, and +// 2) That we're doing the swapping for big things using large vector types, +// rather then `i64` or `<8 x i8>` (or, even worse, `i8`) at a time. +// +// (There are separate tests for intrinsics::typed_swap_nonoverlapping that +// check that it, as an intrinsic, are emitting exactly what it should.) + // CHECK-LABEL: @swap_basic #[no_mangle] pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { @@ -26,55 +36,55 @@ pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { } } -// This test verifies that the library does something smarter, and thus -// doesn't need any scratch space on the stack. - // CHECK-LABEL: @swap_std #[no_mangle] pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{2|4}} x i64> + // CHECK: store <{{2|4}} x i64> swap(x, y) } -// Verify that types with usize alignment are swapped via vectored usizes, -// not falling back to byte-level code. - // CHECK-LABEL: @swap_slice #[no_mangle] pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{2|4}} x i64> + // CHECK: store <{{2|4}} x i64> if x.len() == y.len() { x.swap_with_slice(y); } } -// But for a large align-1 type, vectorized byte copying is what we want. - type OneKilobyteBuffer = [u8; 1024]; // CHECK-LABEL: @swap_1kb_slices #[no_mangle] pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i8> - // CHECK: store <{{[0-9]+}} x i8> + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + + // CHECK: load <{{2|4}} x i64>{{.+}}align 1, + // CHECK: store <{{2|4}} x i64>{{.+}}align 1, + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + if x.len() == y.len() { x.swap_with_slice(y); } } -// This verifies that the 2×read + 2×write optimizes to just 3 memcpys -// for an unusual type like this. It's not clear whether we should do anything -// smarter in Rust for these, so for now it's fine to leave these up to the backend. -// That's not as bad as it might seem, as for example, LLVM will lower the -// memcpys below to VMOVAPS on YMMs if one enables the AVX target feature. -// Eventually we'll be able to pass `align_of::<T>` to a const generic and -// thus pick a smarter chunk size ourselves without huge code duplication. - #[repr(align(64))] pub struct BigButHighlyAligned([u8; 64 * 3]); @@ -82,9 +92,25 @@ pub struct BigButHighlyAligned([u8; 64 * 3]); #[no_mangle] pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) { // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + + // CHECK-COUNT-2: load <{{2|4}} x i64>{{.+}}align 64, + // CHECK-COUNT-2: store <{{2|4}} x i64>{{.+}}align 64, + + // CHECK-COUNT-2: load <{{2|4}} x i64>{{.+}}align 32, + // CHECK-COUNT-2: store <{{2|4}} x i64>{{.+}}align 32, + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 // CHECK-NOT: call void @llvm.memcpy swap(x, y) } diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 76bb853e642..7aa613ae9c2 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -1,5 +1,7 @@ //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled //@ only-x86_64 +//@ min-llvm-version: 20 +//@ ignore-std-debug-assertions (`ptr::swap_nonoverlapping` has one which blocks some optimizations) #![crate_type = "lib"] @@ -27,13 +29,19 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { // CHECK-NOT: alloca - // Whether `i8` is the best for this is unclear, but - // might as well record what's actually happening right now. - - // CHECK: load i8 - // CHECK: load i8 - // CHECK: store i8 - // CHECK: store i8 + // Swapping `i48` might be cleaner in LLVM-IR here, but `i32`+`i16` isn't bad, + // and is closer to the assembly it generates anyway. + + // CHECK-NOT: load{{ }} + // CHECK: load i32{{.+}}align 2 + // CHECK-NEXT: load i32{{.+}}align 2 + // CHECK-NEXT: store i32{{.+}}align 2 + // CHECK-NEXT: store i32{{.+}}align 2 + // CHECK: load i16{{.+}}align 2 + // CHECK-NEXT: load i16{{.+}}align 2 + // CHECK-NEXT: store i16{{.+}}align 2 + // CHECK-NEXT: store i16{{.+}}align 2 + // CHECK-NOT: store{{ }} swap(x, y) } @@ -76,30 +84,49 @@ pub fn swap_slices<'a>(x: &mut &'a [u32], y: &mut &'a [u32]) { swap(x, y) } -// LLVM doesn't vectorize a loop over 3-byte elements, -// so we chunk it down to bytes and loop over those instead. type RGB24 = [u8; 3]; // CHECK-LABEL: @swap_rgb24_slices #[no_mangle] pub fn swap_rgb24_slices(x: &mut [RGB24], y: &mut [RGB24]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i8> - // CHECK: store <{{[0-9]+}} x i8> + + // CHECK: mul nuw nsw i64 %{{x|y}}.1, 3 + + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> + + // CHECK-COUNT-2: load i32 + // CHECK-COUNT-2: store i32 + // CHECK-COUNT-2: load i16 + // CHECK-COUNT-2: store i16 + // CHECK-COUNT-2: load i8 + // CHECK-COUNT-2: store i8 if x.len() == y.len() { x.swap_with_slice(y); } } -// This one has a power-of-two size, so we iterate over it directly type RGBA32 = [u8; 4]; // CHECK-LABEL: @swap_rgba32_slices #[no_mangle] pub fn swap_rgba32_slices(x: &mut [RGBA32], y: &mut [RGBA32]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i32> - // CHECK: store <{{[0-9]+}} x i32> + + // Because the size in bytes in a multiple of 4, we can skip the smallest sizes. + + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> + + // CHECK-COUNT-2: load i32 + // CHECK-COUNT-2: store i32 + + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + if x.len() == y.len() { x.swap_with_slice(y); } @@ -113,8 +140,8 @@ const _: () = assert!(!std::mem::size_of::<String>().is_power_of_two()); #[no_mangle] pub fn swap_string_slices(x: &mut [String], y: &mut [String]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{[0-9]+}} x i64>{{.+}}, align 8, + // CHECK: store <{{[0-9]+}} x i64>{{.+}}, align 8, if x.len() == y.len() { x.swap_with_slice(y); } @@ -130,6 +157,26 @@ pub struct Packed { #[no_mangle] pub fn swap_packed_structs(x: &mut Packed, y: &mut Packed) { // CHECK-NOT: alloca + + // CHECK-NOT: load + // CHECK-NOT: store + + // CHECK: %[[A:.+]] = load i64, ptr %x, align 1, + // CHECK-NEXT: %[[B:.+]] = load i64, ptr %y, align 1, + // CHECK-NEXT: store i64 %[[B]], ptr %x, align 1, + // CHECK-NEXT: store i64 %[[A]], ptr %y, align 1, + + // CHECK-NOT: load + // CHECK-NOT: store + + // CHECK: %[[C:.+]] = load i8, ptr %[[X8:.+]], align 1, + // CHECK-NEXT: %[[D:.+]] = load i8, ptr %[[Y8:.+]], align 1, + // CHECK-NEXT: store i8 %[[D]], ptr %[[X8]], align 1, + // CHECK-NEXT: store i8 %[[C]], ptr %[[Y8]], align 1, + + // CHECK-NOT: load + // CHECK-NOT: store + // CHECK: ret void swap(x, y) } diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 9f68d742a75..398c9a580bc 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled --edition=2021 +//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled +//@ edition: 2021 //@ only-x86_64 //@ revisions: NINETEEN TWENTY //@[NINETEEN] exact-llvm-major-version: 19 diff --git a/tests/crashes/119095.rs b/tests/crashes/119095.rs index 28742e0d5da..9b6c976d3e5 100644 --- a/tests/crashes/119095.rs +++ b/tests/crashes/119095.rs @@ -1,5 +1,5 @@ //@ known-bug: #119095 -//@ compile-flags: --edition=2021 +//@ edition: 2021 fn any<T>() -> T { loop {} diff --git a/tests/crashes/120016.rs b/tests/crashes/120016.rs index faba1af91b4..7eda330e7ad 100644 --- a/tests/crashes/120016.rs +++ b/tests/crashes/120016.rs @@ -1,5 +1,6 @@ //@ known-bug: #120016 -//@ compile-flags: -Zcrate-attr=feature(const_async_blocks) --edition=2021 +//@ compile-flags: -Zcrate-attr=feature(const_async_blocks) +//@ edition: 2021 #![feature(type_alias_impl_trait, const_async_blocks)] diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs index 919c9dfd30e..52b880e4859 100644 --- a/tests/crashes/127033.rs +++ b/tests/crashes/127033.rs @@ -1,5 +1,5 @@ //@ known-bug: #127033 -//@ compile-flags: --edition=2021 +//@ edition: 2021 pub trait RaftLogStorage { fn save_vote(vote: ()) -> impl std::future::Future + Send; diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs index 5f0ae108f8f..56d09d78bed 100644 --- a/tests/crashes/128094.rs +++ b/tests/crashes/128094.rs @@ -1,5 +1,6 @@ //@ known-bug: rust-lang/rust#128094 -//@ compile-flags: -Zmir-enable-passes=+GVN --edition=2018 +//@ compile-flags: -Zmir-enable-passes=+GVN +//@ edition: 2018 pub enum Request { TestSome(T), diff --git a/tests/crashes/132103.rs b/tests/crashes/132103.rs index 5bf4792c44c..e2d8378efe6 100644 --- a/tests/crashes/132103.rs +++ b/tests/crashes/132103.rs @@ -1,5 +1,6 @@ //@ known-bug: #132103 -//@compile-flags: -Zvalidate-mir --edition=2018 -Zinline-mir=yes +//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes +//@ edition: 2018 use core::future::{async_drop_in_place, Future}; use core::mem::{self}; use core::pin::pin; diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs index 995bdf06224..81c8c6d6f7d 100644 --- a/tests/crashes/132430.rs +++ b/tests/crashes/132430.rs @@ -1,6 +1,7 @@ //@ known-bug: #132430 -//@compile-flags: --edition=2018 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2018 #![feature(cmse_nonsecure_entry)] struct Test; diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs index a8fd1ae1ff5..c718b758dc6 100644 --- a/tests/crashes/135128.rs +++ b/tests/crashes/135128.rs @@ -1,5 +1,6 @@ //@ known-bug: #135128 -//@ compile-flags: -Copt-level=1 --edition=2021 +//@ compile-flags: -Copt-level=1 +//@ edition: 2021 #![feature(trivial_bounds)] diff --git a/tests/crashes/135470.rs b/tests/crashes/135470.rs index 7d357a9317f..efa017b5457 100644 --- a/tests/crashes/135470.rs +++ b/tests/crashes/135470.rs @@ -1,5 +1,6 @@ //@ known-bug: #135470 -//@ compile-flags: --edition=2021 -Copt-level=0 +//@ compile-flags: -Copt-level=0 +//@ edition: 2021 use std::future::Future; trait Access { diff --git a/tests/crashes/135646.rs b/tests/crashes/135646.rs index 67b0ad93db4..841ea5b81b4 100644 --- a/tests/crashes/135646.rs +++ b/tests/crashes/135646.rs @@ -1,5 +1,7 @@ //@ known-bug: #135646 -//@ compile-flags: --edition=2024 -Zpolonius=next +//@ compile-flags: -Zpolonius=next +//@ edition: 2024 + fn main() { &{ [1, 2, 3][4] }; } diff --git a/tests/crashes/135668.rs b/tests/crashes/135668.rs index 8126a65606b..00d7b5db0c6 100644 --- a/tests/crashes/135668.rs +++ b/tests/crashes/135668.rs @@ -1,5 +1,5 @@ //@ known-bug: #135668 -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::future::Future; pub async fn foo() { diff --git a/tests/crashes/137467-1.rs b/tests/crashes/137467-1.rs index 1d62cba59a7..b6bff2bdc4e 100644 --- a/tests/crashes/137467-1.rs +++ b/tests/crashes/137467-1.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 enum Camera { Normal { base_transform: i32 }, Volume { transform: i32 }, diff --git a/tests/crashes/137467-2.rs b/tests/crashes/137467-2.rs index 151d6a0767f..a70ea92b22d 100644 --- a/tests/crashes/137467-2.rs +++ b/tests/crashes/137467-2.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 enum Camera { Normal { base_transform: i32 }, diff --git a/tests/crashes/137467-3.rs b/tests/crashes/137467-3.rs index 2140fe044a7..cb81a9a912e 100644 --- a/tests/crashes/137467-3.rs +++ b/tests/crashes/137467-3.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 fn meow(x: (u32, u32, u32)) { let f = || { diff --git a/tests/crashes/137916.rs b/tests/crashes/137916.rs index 3d6b0e0fbab..b25e7b200d9 100644 --- a/tests/crashes/137916.rs +++ b/tests/crashes/137916.rs @@ -1,5 +1,5 @@ //@ known-bug: #137916 -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::ptr::null; async fn a() -> Box<dyn Send> { diff --git a/tests/debuginfo/coroutine-closure.rs b/tests/debuginfo/coroutine-closure.rs index ffb6ae68a2b..002531084fb 100644 --- a/tests/debuginfo/coroutine-closure.rs +++ b/tests/debuginfo/coroutine-closure.rs @@ -1,6 +1,7 @@ #![feature(async_closure)] //@ only-cdb -//@ compile-flags:-g --edition=2021 +//@ compile-flags: -g +//@ edition: 2021 // === CDB TESTS ================================================================================== diff --git a/tests/incremental/issue-85360-eval-obligation-ice.rs b/tests/incremental/issue-85360-eval-obligation-ice.rs index 6efae1aa12d..70bb43f39ec 100644 --- a/tests/incremental/issue-85360-eval-obligation-ice.rs +++ b/tests/incremental/issue-85360-eval-obligation-ice.rs @@ -1,6 +1,7 @@ //@ revisions:cfail1 cfail2 -//@[cfail1] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=not-loaded -//@[cfail2] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=loaded +//@[cfail1] compile-flags: --crate-type=lib -Zassert-incr-state=not-loaded +//@[cfail2] compile-flags: --crate-type=lib -Zassert-incr-state=loaded +//@ edition: 2021 //@ build-pass use core::any::Any; diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff index 596ad70b3bf..f29bc5dfc6e 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff index 987c2166692..654cb2503df 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff @@ -15,7 +15,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff index d7ec6dcfa2c..82c89b7ce54 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp new file mode 100644 index 00000000000..872a6a45aed --- /dev/null +++ b/tests/pretty/hir-delegation.pp @@ -0,0 +1,23 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-delegation.pp + +#![allow(incomplete_features)]#![feature(fn_delegation)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn b<C>(e: C) { } + +trait G { + fn b(arg0: _) -> _ { b({ }) } +} + +mod m { + fn add(a: u32, b: u32) -> u32 { a + b } +} + +fn add(arg0: _, arg1: _) -> _ { m::add(arg0, arg1) } + +fn main() { { let _ = add(1, 2); }; } diff --git a/tests/pretty/hir-delegation.rs b/tests/pretty/hir-delegation.rs new file mode 100644 index 00000000000..9e351a1e32f --- /dev/null +++ b/tests/pretty/hir-delegation.rs @@ -0,0 +1,22 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-delegation.pp + +#![allow(incomplete_features)] +#![feature(fn_delegation)] + +fn b<C>(e: C) {} + +trait G { + reuse b {} +} + +mod m { + pub fn add(a: u32, b: u32) -> u32 { a + b } +} + +reuse m::add; + +fn main() { + _ = add(1, 2); +} diff --git a/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs new file mode 100644 index 00000000000..942b667814a --- /dev/null +++ b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs @@ -0,0 +1,32 @@ +//@ only-x86_64-unknown-linux-gnu + +// Regression test for the incremental bug in <https://github.com/rust-lang/rust/issues/139407>. +// +// A detailed explanation is described in <https://github.com/rust-lang/rust/pull/139453>, +// however the gist of the issue is that hard-linking temporary files can interact strangely +// across incremental sessions that are not finalized due to errors originating from the +// codegen backend. + +use run_make_support::{run, rustc}; + +fn main() { + let mk_rustc = || { + let mut rustc = rustc(); + rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test"); + rustc + }; + + // Revision 1 + mk_rustc().cfg("rpass1").run(); + + run("test"); + + // Revision 2 + mk_rustc().cfg("cfail2").run_fail(); + // Expected to fail. + + // Revision 3 + mk_rustc().cfg("rpass3").run(); + + run("test"); +} diff --git a/tests/run-make/dirty-incr-due-to-hard-link/test.rs b/tests/run-make/dirty-incr-due-to-hard-link/test.rs new file mode 100644 index 00000000000..dba5a6bbc82 --- /dev/null +++ b/tests/run-make/dirty-incr-due-to-hard-link/test.rs @@ -0,0 +1,31 @@ +#[inline(never)] +#[cfg(any(rpass1, rpass3))] +fn a() -> i32 { + 0 +} + +#[cfg(any(cfail2))] +fn a() -> i32 { + 1 +} + +fn main() { + evil::evil(); + assert_eq!(a(), 0); +} + +mod evil { + #[cfg(any(rpass1, rpass3))] + pub fn evil() { + unsafe { + std::arch::asm!("/* */"); + } + } + + #[cfg(any(cfail2))] + pub fn evil() { + unsafe { + std::arch::asm!("missing"); + } + } +} diff --git a/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs b/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs new file mode 100644 index 00000000000..f970d395b2c --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs @@ -0,0 +1,16 @@ +#![feature(ascii_char)] // random lib feature +#![feature(box_patterns)] // random lang feature + +// picked arbitrary unstable features, just need a random lib and lang feature, ideally ones that +// won't be stabilized any time soon so we don't have to update this test +fn main() { + for s in quix("foo/bar") { + print!("{s}"); + } + println!(); +} + +// need a latebound var to trigger the incremental compilation ICE +fn quix(foo: &str) -> impl Iterator<Item = &'_ str> + '_ { + foo.split('/') +} diff --git a/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs new file mode 100644 index 00000000000..7e070d80c79 --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs @@ -0,0 +1,94 @@ +//! This test checks if unstable feature usage metric dump files `unstable-feature-usage*.json` work +//! as expected. +//! +//! - Basic sanity checks on a default ICE dump. +//! +//! See <https://github.com/rust-lang/rust/issues/129485>. +//! +//! # Test history +//! +//! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming +//! those will be present in this test as well on the same platform + +//@ ignore-windows +//FIXME(#128911): still flakey on i686-mingw. + +use std::path::{Path, PathBuf}; + +use run_make_support::rfs::create_dir_all; +use run_make_support::{ + cwd, filename_contains, has_extension, rfs, run_in_tmpdir, rustc, serde_json, + shallow_find_files, +}; + +fn find_feature_usage_metrics<P: AsRef<Path>>(dir: P) -> Vec<PathBuf> { + shallow_find_files(dir, |path| { + if filename_contains(path, "unstable_feature_usage") && has_extension(path, "json") { + true + } else { + dbg!(path); + false + } + }) +} + +fn main() { + test_metrics_dump(); + test_metrics_errors(); +} + +#[track_caller] +fn test_metrics_dump() { + run_in_tmpdir(|| { + let metrics_dir = cwd().join("metrics"); + create_dir_all(&metrics_dir); + rustc() + .input("main.rs") + .incremental("incremental") + .env("RUST_BACKTRACE", "short") + .arg(format!("-Zmetrics-dir={}", metrics_dir.display())) + .run(); + let mut metrics = find_feature_usage_metrics(&metrics_dir); + let json_path = + metrics.pop().expect("there should be one metrics file in the output directory"); + + // After the `pop` above, there should be no files left. + assert!( + metrics.is_empty(), + "there should be no more than one metrics file in the output directory" + ); + + let message = rfs::read_to_string(json_path); + let mut parsed: serde_json::Value = + serde_json::from_str(&message).expect("metrics should be dumped as json"); + // remove timestamps + assert!(parsed["lib_features"][0]["timestamp"].is_number()); + assert!(parsed["lang_features"][0]["timestamp"].is_number()); + parsed["lib_features"][0]["timestamp"] = serde_json::json!(null); + parsed["lang_features"][0]["timestamp"] = serde_json::json!(null); + let expected = serde_json::json!( + { + "lib_features":[{"symbol":"ascii_char", "timestamp":null}], + "lang_features":[{"symbol":"box_patterns","since":null, "timestamp":null}] + } + ); + + assert_eq!(expected, parsed); + }); +} + +#[track_caller] +fn test_metrics_errors() { + run_in_tmpdir(|| { + rustc() + .input("main.rs") + .incremental("incremental") + .env("RUST_BACKTRACE", "short") + .arg("-Zmetrics-dir=invaliddirectorythatdefinitelydoesntexist") + .run_fail() + .assert_stderr_contains( + "error: cannot dump feature usage metrics: No such file or directory", + ) + .assert_stdout_not_contains("internal compiler error"); + }); +} diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs index d8c43100d2f..1ed67694a90 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs @@ -1,7 +1,8 @@ // FIXME: if/when the output of the test harness can be tested on its own, this test should be // adapted to use that, and that normalize line can go away -//@ compile-flags:--test --edition 2021 +//@ compile-flags: --test +//@ edition: 2021 //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout index 63d987de8a9..9f4d60e6f4d 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout @@ -1,14 +1,14 @@ running 1 test -test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) ... FAILED +test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) ... FAILED failures: ----- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) stdout ---- +---- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) stdout ---- Test executable succeeded, but it's marked `should_panic`. failures: - $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) + $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs index 636c3c8de42..bcfb790e55f 100644 --- a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs +++ b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs @@ -3,7 +3,8 @@ //@ check-pass //@ aux-build: inner-crate-doc.rs -//@ compile-flags: --extern inner_crate_doc --edition 2018 +//@ compile-flags: --extern inner_crate_doc +//@ edition: 2018 /// Import doc comment [inner_crate_doc] #[doc(inline)] diff --git a/tests/rustdoc-ui/multi-par-footnote.rs b/tests/rustdoc-ui/multi-par-footnote.rs new file mode 100644 index 00000000000..bb6a85db0db --- /dev/null +++ b/tests/rustdoc-ui/multi-par-footnote.rs @@ -0,0 +1,18 @@ +//@ check-pass +//@ compile-flags:--test +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +// Regression test for #139064. + +/// Example +/// +/// Footnote with multiple paragraphs[^multiple] +/// +/// [^multiple]: +/// One +/// +/// Two +/// +/// Three +pub fn add(left: u64, right: u64) -> u64 { + left + right +} diff --git a/tests/rustdoc-ui/multi-par-footnote.stdout b/tests/rustdoc-ui/multi-par-footnote.stdout new file mode 100644 index 00000000000..7326c0a25a0 --- /dev/null +++ b/tests/rustdoc-ui/multi-par-footnote.stdout @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/auxiliary/primitive-doc.rs index a7253ed2450..859716c38e4 100644 --- a/tests/rustdoc/auxiliary/primitive-doc.rs +++ b/tests/rustdoc/auxiliary/primitive-doc.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![feature(rustc_attrs)] #![feature(no_core)] diff --git a/tests/rustdoc/auxiliary/primitive-reexport.rs b/tests/rustdoc/auxiliary/primitive-reexport.rs index 18b57037634..7c85038674b 100644 --- a/tests/rustdoc/auxiliary/primitive-reexport.rs +++ b/tests/rustdoc/auxiliary/primitive-reexport.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --emit metadata --crate-type lib --edition 2018 +//@ compile-flags: --emit metadata --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] diff --git a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs index 7cec30c8b74..30834bd7210 100644 --- a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs +++ b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs @@ -6,7 +6,8 @@ //@ aux-build:empty2.rs //@ aux-crate:priv:empty2=empty2.rs //@ build-aux-docs -//@ compile-flags:-Z unstable-options --edition 2018 +//@ compile-flags:-Z unstable-options +//@ edition: 2018 //@ has extern_crate_only_used_in_link/index.html //@ has - '//a[@href="../issue_66159_1/struct.Something.html"]' 'issue_66159_1::Something' diff --git a/tests/rustdoc/primitive-reexport.rs b/tests/rustdoc/primitive-reexport.rs index eb255745392..9b23b24fc93 100644 --- a/tests/rustdoc/primitive-reexport.rs +++ b/tests/rustdoc/primitive-reexport.rs @@ -1,5 +1,6 @@ //@ aux-build: primitive-reexport.rs -//@ compile-flags:--extern foo --edition 2018 +//@ compile-flags: --extern foo +//@ edition: 2018 #![crate_name = "bar"] diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs index e78d1d94614..647c1cca948 100644 --- a/tests/rustdoc/primitive-slice-auto-trait.rs +++ b/tests/rustdoc/primitive-slice-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs index 045478e6b4f..51300bd6b2f 100644 --- a/tests/rustdoc/primitive-tuple-auto-trait.rs +++ b/tests/rustdoc/primitive-tuple-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index d142729d2a8..bab5eaae9a2 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustdoc_internals)] diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs index 6cae094c21c..7dada1f9832 100644 --- a/tests/rustdoc/primitive-unit-auto-trait.rs +++ b/tests/rustdoc/primitive-unit-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index ffc19b138a5..fa651baa7bc 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -70,6 +70,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path hash_untracked_state: None, register_lints: None, override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs index f6f895588f2..f7511367675 100644 --- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -51,7 +51,7 @@ fn test_assoc_items() -> ControlFlow<()> { check_items( &trait_assoc_item_defs, &[ - "ATrait::{synthetic#0}", + "ATrait::{anon_assoc#0}", "ATrait::rpitit", "ATrait::Assoc", "ATrait::assoc_fn_no_self", @@ -64,7 +64,7 @@ fn test_assoc_items() -> ControlFlow<()> { check_items( &impl_assoc_item_defs, &[ - "<AStruct as ATrait>::{synthetic#0}", + "<AStruct as ATrait>::{anon_assoc#0}", "<AStruct as ATrait>::rpitit", "<AStruct as ATrait>::Assoc", "<AStruct as ATrait>::assoc_fn_no_self", diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs index 069744a3282..12dca587e07 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3 +//@ compile-flags: -Zvalidate-mir --crate-type=lib -Copt-level=3 +//@ edition: 2018 fn main() {} diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index 52697bac509..03fa220b0bf 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `x` which is behind a mutable reference - --> $DIR/closure-shim-borrowck-error.rs:10:18 + --> $DIR/closure-shim-borrowck-error.rs:11:18 | LL | needs_fn_mut(async || { | ^^^^^^^^ `x` is moved here @@ -11,7 +11,7 @@ LL | x.hello(); | move occurs because `x` has type `Ty`, which does not implement the `Copy` trait | note: if `Ty` implemented `Clone`, you could clone the value - --> $DIR/closure-shim-borrowck-error.rs:16:1 + --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); | - you could clone this value diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs index 8634d6f7768..a3f54d70316 100644 --- a/tests/ui/async-await/issue-60709.rs +++ b/tests/ui/async-await/issue-60709.rs @@ -1,6 +1,7 @@ // This used to compile the future down to ud2, due to uninhabited types being // handled incorrectly in coroutines. -//@ compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 +//@ compile-flags: -Copt-level=z -Cdebuginfo=2 +//@ edition: 2018 //@ run-pass diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs index c30477fcd30..e64a856fab3 100644 --- a/tests/ui/async-await/issues/issue-59972.rs +++ b/tests/ui/async-await/issues/issue-59972.rs @@ -4,7 +4,8 @@ //@ run-pass -//@ compile-flags: --edition=2018 -Aunused +//@ compile-flags: -Aunused +//@ edition: 2018 pub enum Uninhabited { } diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs index 2f2cd8d9353..a916bd8b857 100644 --- a/tests/ui/autodiff/autodiff_illegal.rs +++ b/tests/ui/autodiff/autodiff_illegal.rs @@ -63,7 +63,7 @@ fn dummy() { // Malformed, where args? #[autodiff] pub fn f7(x: f64) { - //~^ ERROR autodiff must be applied to function + //~^ ERROR autodiff requires at least a name and mode unimplemented!() } @@ -77,7 +77,7 @@ pub fn f8(x: f64) { // Invalid attribute syntax #[autodiff = ""] pub fn f9(x: f64) { - //~^ ERROR autodiff must be applied to function + //~^ ERROR autodiff requires at least a name and mode unimplemented!() } diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr index 3752b27e7dd..b119f61b8ae 100644 --- a/tests/ui/autodiff/autodiff_illegal.stderr +++ b/tests/ui/autodiff/autodiff_illegal.stderr @@ -62,7 +62,7 @@ error: autodiff must be applied to function LL | let add_one_v2 = |x: u32| -> u32 { x + 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: autodiff must be applied to function +error: autodiff requires at least a name and mode --> $DIR/autodiff_illegal.rs:65:1 | LL | / pub fn f7(x: f64) { @@ -80,7 +80,7 @@ LL | | unimplemented!() LL | | } | |_^ -error: autodiff must be applied to function +error: autodiff requires at least a name and mode --> $DIR/autodiff_illegal.rs:79:1 | LL | / pub fn f9(x: f64) { diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr index 8ca33e088fc..29c1a71c0b7 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `tru` - --> $DIR/raw-keywords.rs:14:7 + --> $DIR/raw-keywords.rs:15:7 | LL | #[cfg(tru)] | ^^^ help: there is a config with a similar name: `r#true` @@ -9,7 +9,7 @@ LL | #[cfg(tru)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `r#false` - --> $DIR/raw-keywords.rs:19:7 + --> $DIR/raw-keywords.rs:20:7 | LL | #[cfg(r#false)] | ^^^^^^^ @@ -19,7 +19,7 @@ LL | #[cfg(r#false)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `await` - --> $DIR/raw-keywords.rs:27:29 + --> $DIR/raw-keywords.rs:28:29 | LL | #[cfg_attr(edition2015, cfg(await))] | ^^^^^ @@ -28,7 +28,7 @@ LL | #[cfg_attr(edition2015, cfg(await))] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `raw` - --> $DIR/raw-keywords.rs:33:7 + --> $DIR/raw-keywords.rs:34:7 | LL | #[cfg(r#raw)] | ^^^^^ diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr index cce55720bdd..cc3702685fd 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `tru` - --> $DIR/raw-keywords.rs:14:7 + --> $DIR/raw-keywords.rs:15:7 | LL | #[cfg(tru)] | ^^^ help: there is a config with a similar name: `r#true` @@ -9,7 +9,7 @@ LL | #[cfg(tru)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `r#false` - --> $DIR/raw-keywords.rs:19:7 + --> $DIR/raw-keywords.rs:20:7 | LL | #[cfg(r#false)] | ^^^^^^^ @@ -19,7 +19,7 @@ LL | #[cfg(r#false)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `r#await` - --> $DIR/raw-keywords.rs:28:29 + --> $DIR/raw-keywords.rs:29:29 | LL | #[cfg_attr(edition2021, cfg(r#await))] | ^^^^^^^ @@ -28,7 +28,7 @@ LL | #[cfg_attr(edition2021, cfg(r#await))] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `raw` - --> $DIR/raw-keywords.rs:33:7 + --> $DIR/raw-keywords.rs:34:7 | LL | #[cfg(r#raw)] | ^^^^^ diff --git a/tests/ui/check-cfg/raw-keywords.rs b/tests/ui/check-cfg/raw-keywords.rs index 5de13240d7e..b82eb5a64e9 100644 --- a/tests/ui/check-cfg/raw-keywords.rs +++ b/tests/ui/check-cfg/raw-keywords.rs @@ -6,7 +6,8 @@ //@ compile-flags: --cfg=true --cfg=async --check-cfg=cfg(r#true,r#async,edition2015,edition2021) // //@ revisions: edition2015 edition2021 -//@ [edition2021] compile-flags: --edition 2021 +//@ [edition2015] edition: 2015 +//@ [edition2021] edition: 2021 #[cfg(r#true)] fn foo() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue-89606.rs b/tests/ui/closures/2229_closure_analysis/issue-89606.rs index 8c88a4b8226..5494686356d 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-89606.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-89606.rs @@ -2,8 +2,8 @@ // //@ check-pass //@ revisions: twenty_eighteen twenty_twentyone -//@ [twenty_eighteen]compile-flags: --edition 2018 -//@ [twenty_twentyone]compile-flags: --edition 2021 +//@ [twenty_eighteen] edition: 2018 +//@ [twenty_twentyone] edition: 2021 struct S<'a>(Option<&'a mut i32>); diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs index 4fc2e6c903a..a771b815702 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs @@ -1,8 +1,8 @@ //@ run-pass //@ check-run-results //@ revisions: twenty_eighteen twenty_twentyone -//@ [twenty_eighteen]compile-flags: --edition 2018 -//@ [twenty_twentyone]compile-flags: --edition 2021 +//@ [twenty_eighteen] edition: 2018 +//@ [twenty_twentyone] edition: 2021 #[derive(Debug)] struct Dropable(&'static str); diff --git a/tests/ui/compiletest-self-test/trim-env-name.rs b/tests/ui/compiletest-self-test/trim-env-name.rs new file mode 100644 index 00000000000..0cb6efe9f76 --- /dev/null +++ b/tests/ui/compiletest-self-test/trim-env-name.rs @@ -0,0 +1,23 @@ +//@ edition: 2024 +//@ revisions: set unset +//@ run-pass +//@ ignore-cross-compile (assume that non-cross targets have working env vars) +//@ rustc-env: MY_RUSTC_ENV = my-rustc-value +//@ exec-env: MY_EXEC_ENV = my-exec-value +//@[unset] unset-rustc-env: MY_RUSTC_ENV +//@[unset] unset-exec-env: MY_EXEC_ENV + +// Check that compiletest trims whitespace from environment variable names +// specified in `rustc-env` and `exec-env` directives, so that +// `//@ exec-env: FOO=bar` sees the name as `FOO` and not ` FOO`. +// +// Values are currently not trimmed. +// +// Since this is a compiletest self-test, only run it on non-cross targets, +// to avoid having to worry about weird targets that don't support env vars. + +fn main() { + let is_set = cfg!(set); + assert_eq!(option_env!("MY_RUSTC_ENV"), is_set.then_some(" my-rustc-value")); + assert_eq!(std::env::var("MY_EXEC_ENV").ok().as_deref(), is_set.then_some(" my-exec-value")); +} diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs index 2ac57f35674..7753b7d64fb 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs +++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs @@ -1,6 +1,6 @@ //@ revisions: edition2015 edition2021 -//@ [edition2015]compile-flags: --edition=2015 -//@ [edition2021]compile-flags: --edition=2021 +//@ [edition2015] edition: 2015 +//@ [edition2021] edition: 2021 #![feature(extern_types)] #![feature(cfg_accessible)] diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr new file mode 100644 index 00000000000..d0a5da9676d --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr @@ -0,0 +1,53 @@ +error[E0658]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:24:16 + | +LL | let c: Foo<_> = Foo::<1>; + | ^ + | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:26:16 + | +LL | let c: Foo<(_)> = Foo::<1>; + | ^^^ + | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:28:16 + | +LL | let c: Foo<(((_)))> = Foo::<1>; + | ^^^^^^^ + | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/parend_infer.rs:17:17 + | +LL | let b: [u8; (_)] = [1; (((((_)))))]; + | ^^^ + | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/parend_infer.rs:17:28 + | +LL | let b: [u8; (_)] = [1; (((((_)))))]; + | ^^^^^^^^^^^ + | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs index 81c42183b38..3dc27a702de 100644 --- a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs @@ -1,7 +1,9 @@ -//@ check-pass +//@[gate] check-pass //@ revisions: gate nogate #![cfg_attr(gate, feature(generic_arg_infer))] +struct Foo<const N: usize>; + fn main() { // AST Types preserve parens for pretty printing reasons. This means // that this is parsed as a `TyKind::Paren(TyKind::Infer)`. Generic @@ -9,4 +11,20 @@ fn main() { // but `TyKind::Infer` wrapped in arbitrarily many `TyKind::Paren`. let a: Vec<(_)> = vec![1_u8]; let a: Vec<(((((_)))))> = vec![1_u8]; + + // AST Exprs similarly preserve parens for pretty printing reasons. + #[rustfmt::skip] + let b: [u8; (_)] = [1; (((((_)))))]; + //[nogate]~^ error: using `_` for array lengths is unstable + //[nogate]~| error: using `_` for array lengths is unstable + let b: [u8; 2] = b; + + // This is the same case as AST types as the parser doesn't distinguish between const + // and type args when they share syntax + let c: Foo<_> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` + let c: Foo<(_)> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` + let c: Foo<(((_)))> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` } diff --git a/tests/ui/consts/const-suggest-feature.rs b/tests/ui/consts/const-suggest-feature.rs index 0c940368976..dbb166dd6c5 100644 --- a/tests/ui/consts/const-suggest-feature.rs +++ b/tests/ui/consts/const-suggest-feature.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2018 +//@ edition: 2018 use std::cell::Cell; const WRITE: () = unsafe { diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index d6f07994e82..8f2bcd82c73 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![unstable(feature = "humans", reason = "who ever let humans program computers, we're apparently really bad at it", diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 2f3a65302bd..aad3d76dd26 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -12,10 +12,10 @@ note: inside `swap_nonoverlapping::<MaybeUninit<u8>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `swap_nonoverlapping::compiletime::<MaybeUninit<u8>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::swap_nonoverlapping_simple_untyped::<MaybeUninit<u8>>` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::read::<MaybeUninit<MaybeUninit<u8>>>` +note: inside `std::ptr::swap_nonoverlapping_const::<MaybeUninit<u8>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `copy_nonoverlapping::<MaybeUninit<u8>>` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs index ccf63f86fcf..d60fe7d409a 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs @@ -16,7 +16,7 @@ impl Bar for Foo<'_> { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration } fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index 33873f5c5a5..bb8365b0ae5 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -39,14 +39,14 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration --> $DIR/elided-lifetime.rs:16:17 | LL | const STATIC: &str; - | - lifetimes in impl do not match this const in trait + | - lifetimes in impl do not match this associated const in trait ... LL | const STATIC: &str = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: aborting due to 3 previous errors diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs index 1e12259e483..85746df146f 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs @@ -9,7 +9,7 @@ impl Bar<'_> for A { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration } struct B; diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index 116f28e8484..38d24db1317 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -21,14 +21,14 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration --> $DIR/static-trait-impl.rs:9:17 | LL | const STATIC: &'a str; - | - lifetimes in impl do not match this const in trait + | - lifetimes in impl do not match this associated const in trait ... LL | const STATIC: &str = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs index f85e4a52e9b..a9572ee9b0d 100644 --- a/tests/ui/coroutine/async-gen-deduce-yield.rs +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 +//@ edition: 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 583820c7aa3..53e3ce77f8a 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 +//@ edition: 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs index 7b850f32b4b..e926a337659 100644 --- a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs +++ b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs @@ -1,5 +1,6 @@ //@ run-pass -//@ compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3 +//@ compile-flags: -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3 +//@ edition: 2021 fn main() { TranslatorI.visit_pre(); diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index 2b0bcf9d84e..cb14d9f459a 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}` +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}` --> $DIR/unsupported.rs:22:25 | LL | reuse to_reuse::opaque_ret; @@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>` is well-formed --> $DIR/unsupported.rs:21:5 | @@ -17,7 +17,7 @@ LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}` +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}` --> $DIR/unsupported.rs:25:24 | LL | reuse ToReuse::opaque_ret; @@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>` is well-formed --> $DIR/unsupported.rs:24:5 | diff --git a/tests/ui/deprecation/try-macro-suggestion.rs b/tests/ui/deprecation/try-macro-suggestion.rs index 1e477ab9c88..0775f001100 100644 --- a/tests/ui/deprecation/try-macro-suggestion.rs +++ b/tests/ui/deprecation/try-macro-suggestion.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 fn foo() -> Result<(), ()> { Ok(try!()); //~ ERROR use of deprecated `try` macro Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 90bb715a052..6170250992c 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -1,12 +1,14 @@ -error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied +error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied --> $DIR/as_expression.rs:56:21 | LL | SelectInt.check("bar"); - | ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str` + | ----- ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str` | | | required by a bound introduced by this call | - = help: the trait `AsExpression<Text>` is implemented for `&str` + = help: the trait `AsExpression<Integer>` is not implemented for `&str` + but trait `AsExpression<Text>` is implemented for it + = help: for that trait implementation, expected `Text`, found `Integer` note: required by a bound in `Foo::check` --> $DIR/as_expression.rs:47:12 | @@ -16,11 +18,11 @@ LL | where LL | T: AsExpression<Self::SqlType>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text` +error[E0271]: type mismatch resolving `Integer == Text` --> $DIR/as_expression.rs:56:5 | LL | SelectInt.check("bar"); - | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` + | ^^^^^^^^^^^^^^^^^^^^^^ types differ error: aborting due to 2 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index b5ff76809a2..673adb82870 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -54,7 +54,6 @@ impl<T> Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //[current]~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied - //[next]~^^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied + //~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied //[next]~| ERROR type mismatch } diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs deleted file mode 100644 index 0c2a4f226d8..00000000000 --- a/tests/ui/error-codes/E0622.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(intrinsics)] - -extern "C" { - - #[rustc_intrinsic] - pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); - //~^ ERROR intrinsic must be a function [E0622] -} - -fn main() { - unsafe { - atomic_singlethreadfence_seqcst(); - } -} diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr deleted file mode 100644 index c0aea542af0..00000000000 --- a/tests/ui/error-codes/E0622.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0622]: intrinsic must be a function - --> $DIR/E0622.rs:6:5 - | -LL | pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0622`. diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.rs b/tests/ui/feature-gates/feature-gate-try_blocks.rs index f565dd014de..90816293624 100644 --- a/tests/ui/feature-gates/feature-gate-try_blocks.rs +++ b/tests/ui/feature-gates/feature-gate-try_blocks.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 pub fn main() { let try_result: Option<_> = try { //~ ERROR `try` expression is experimental diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs index 33fda822baa..a32ebed8dde 100644 --- a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs +++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2021 +//@ edition: 2021 pub fn demo() -> Option<i32> { #[cfg(FALSE)] diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr.rs b/tests/ui/feature-gates/feature-gate-yeet_expr.rs index 12cc17e1cc8..6604f496917 100644 --- a/tests/ui/feature-gates/feature-gate-yeet_expr.rs +++ b/tests/ui/feature-gates/feature-gate-yeet_expr.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 pub fn demo() -> Option<i32> { do yeet //~ ERROR `do yeet` expression is experimental diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr index 78992112a7c..a3d3a66a05c 100644 --- a/tests/ui/generic-associated-types/const_params_have_right_type.stderr +++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr @@ -1,4 +1,4 @@ -error[E0053]: type `Foo` has an incompatible generic parameter for trait `Trait` +error[E0053]: associated type `Foo` has an incompatible generic parameter for trait `Trait` --> $DIR/const_params_have_right_type.rs:6:14 | LL | trait Trait { diff --git a/tests/ui/generic-associated-types/issue-102114.current.stderr b/tests/ui/generic-associated-types/issue-102114.current.stderr index 03471d08d74..5aace1eeaa2 100644 --- a/tests/ui/generic-associated-types/issue-102114.current.stderr +++ b/tests/ui/generic-associated-types/issue-102114.current.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/issue-102114.rs:15:12 | LL | type B<'b>; diff --git a/tests/ui/generic-associated-types/issue-102114.next.stderr b/tests/ui/generic-associated-types/issue-102114.next.stderr index 03471d08d74..5aace1eeaa2 100644 --- a/tests/ui/generic-associated-types/issue-102114.next.stderr +++ b/tests/ui/generic-associated-types/issue-102114.next.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/issue-102114.rs:15:12 | LL | type B<'b>; diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs index c1381025ac2..a39a7aacc7b 100644 --- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -12,11 +12,11 @@ struct Fooy; impl Foo for Fooy { type A = u32; - //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `A` do not match the trait declaration type B<'a, T> = Vec<T>; //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters type C<'a> = u32; - //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `C` do not match the trait declaration } struct Fooer; @@ -25,7 +25,7 @@ impl Foo for Fooer { type A<T> = u32; //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters type B<'a> = u32; - //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `B` do not match the trait declaration type C<T> = T; //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters } diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr index fdd6d305ab2..f7c4a07589c 100644 --- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr @@ -1,13 +1,13 @@ -error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `A` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:14:11 | LL | type A<'a>; - | ---- lifetimes in impl do not match this type in trait + | ---- lifetimes in impl do not match this associated type in trait ... LL | type A = u32; - | ^ lifetimes do not match type in trait + | ^ lifetimes do not match associated type in trait -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:16:12 | LL | type B<'a, 'b>; @@ -20,16 +20,16 @@ LL | type B<'a, T> = Vec<T>; | | | found 1 type parameter -error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `C` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:18:11 | LL | type C; - | - lifetimes in impl do not match this type in trait + | - lifetimes in impl do not match this associated type in trait ... LL | type C<'a> = u32; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait -error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `A` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:25:12 | LL | type A<'a>; @@ -38,16 +38,16 @@ LL | type A<'a>; LL | type A<T> = u32; | ^ found 1 type parameter -error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `B` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:27:11 | LL | type B<'a, 'b>; - | -------- lifetimes in impl do not match this type in trait + | -------- lifetimes in impl do not match this associated type in trait ... LL | type B<'a> = u32; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait -error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `C` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:29:12 | LL | type C; diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs index 0c94a4262ef..dde47cf993e 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.rs +++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs @@ -14,7 +14,7 @@ impl Trait for () { //~| ERROR mismatched types const Q = ""; //~^ ERROR missing type for `const` item - //~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `Q` do not match the trait declaration } fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr index 5af119dffa7..9f6db575ec2 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr +++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr @@ -15,14 +15,14 @@ error: missing type for `const` item LL | const K<T> = (); | ^ help: provide a type for the associated constant: `()` -error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `Q` do not match the trait declaration --> $DIR/assoc-const-missing-type.rs:15:12 | LL | const Q<'a>: &'a str; - | ---- lifetimes in impl do not match this const in trait + | ---- lifetimes in impl do not match this associated const in trait ... LL | const Q = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: missing type for `const` item --> $DIR/assoc-const-missing-type.rs:15:12 diff --git a/tests/ui/generic-const-items/compare-impl-item.rs b/tests/ui/generic-const-items/compare-impl-item.rs index 21c958a0abe..b301cd0dae0 100644 --- a/tests/ui/generic-const-items/compare-impl-item.rs +++ b/tests/ui/generic-const-items/compare-impl-item.rs @@ -22,7 +22,7 @@ impl<P> Trait<P> for () { const D<const N: u16>: u16 = N; //~^ ERROR const `D` has an incompatible generic parameter for trait `Trait` const E: &'static () = &(); - //~^ ERROR lifetime parameters or bounds on const `E` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated const `E` do not match the trait declaration const F: usize = 1024 where diff --git a/tests/ui/generic-const-items/compare-impl-item.stderr b/tests/ui/generic-const-items/compare-impl-item.stderr index 3bf28e9da60..f7e3ff6501b 100644 --- a/tests/ui/generic-const-items/compare-impl-item.stderr +++ b/tests/ui/generic-const-items/compare-impl-item.stderr @@ -1,4 +1,4 @@ -error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated const `A` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/compare-impl-item.rs:16:13 | LL | const A: (); @@ -7,7 +7,7 @@ LL | const A: (); LL | const A<T>: () = (); | ^ found 1 type parameter -error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters +error[E0049]: associated const `B` has 1 const parameter but its trait declaration has 2 const parameters --> $DIR/compare-impl-item.rs:18:13 | LL | const B<const K: u64, const Q: u64>: u64; @@ -18,7 +18,7 @@ LL | const B<const K: u64, const Q: u64>: u64; LL | const B<const K: u64>: u64 = 0; | ^^^^^^^^^^^^ found 1 const parameter -error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated const `C` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/compare-impl-item.rs:20:13 | LL | const C<T>: T; @@ -27,7 +27,7 @@ LL | const C<T>: T; LL | const C<'a>: &'a str = ""; | ^^ found 0 type parameters -error[E0053]: const `D` has an incompatible generic parameter for trait `Trait` +error[E0053]: associated const `D` has an incompatible generic parameter for trait `Trait` --> $DIR/compare-impl-item.rs:22:13 | LL | trait Trait<P> { @@ -42,14 +42,14 @@ LL | impl<P> Trait<P> for () { LL | const D<const N: u16>: u16 = N; | ^^^^^^^^^^^^ found const parameter of type `u16` -error[E0195]: lifetime parameters or bounds on const `E` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `E` do not match the trait declaration --> $DIR/compare-impl-item.rs:24:12 | LL | const E<'a>: &'a (); - | ---- lifetimes in impl do not match this const in trait + | ---- lifetimes in impl do not match this associated const in trait ... LL | const E: &'static () = &(); - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error[E0276]: impl has stricter requirements than trait --> $DIR/compare-impl-item.rs:29:12 diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs index 53b28c2bea4..f33469796c2 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs @@ -1,5 +1,6 @@ //@ check-pass -//@ compile-flags: --edition=2021 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2021 use std::{ future::Future, diff --git a/tests/ui/impl-trait/auto-trait-contains-err.rs b/tests/ui/impl-trait/auto-trait-contains-err.rs index d7f094211d7..8a2ebe301f1 100644 --- a/tests/ui/impl-trait/auto-trait-contains-err.rs +++ b/tests/ui/impl-trait/auto-trait-contains-err.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::future::Future; diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr index c76415d8114..341262ac85b 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr @@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X` LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` -error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 | LL | type LineStream<'a, Repr> diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr index 4d72490ff95..9632d2ce624 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr @@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X` LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` -error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 | LL | type LineStream<'a, Repr> diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index fc3efb44ac7..a9dfac274d5 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -6,11 +6,11 @@ LL | fn bar() -> () {} | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `Foo::{synthetic#0}` +note: required by a bound in `Foo::{anon_assoc#0}` --> $DIR/doesnt-satisfy.rs:2:22 | LL | fn bar() -> impl std::fmt::Display; - | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{synthetic#0}` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs index 20b0e60702f..da3cfd099b5 100644 --- a/tests/ui/impl-trait/in-trait/dump.rs +++ b/tests/ui/impl-trait/in-trait/dump.rs @@ -8,7 +8,7 @@ trait Foo { } fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { -//~^ ERROR <T as Foo>::{synthetic#0}<'s/#1> +//~^ ERROR <T as Foo>::{anon_assoc#0}<'s/#1> x.hello() } diff --git a/tests/ui/impl-trait/in-trait/dump.stderr b/tests/ui/impl-trait/in-trait/dump.stderr index 95805840385..15b6f186ced 100644 --- a/tests/ui/impl-trait/in-trait/dump.stderr +++ b/tests/ui/impl-trait/in-trait/dump.stderr @@ -1,4 +1,4 @@ -error: <T as Foo>::{synthetic#0}<'s/#1> +error: <T as Foo>::{anon_assoc#0}<'s/#1> --> $DIR/dump.rs:10:35 | LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 5cb80386b35..6571ce2d5f0 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -14,11 +14,11 @@ LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { | ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>` | = help: the trait `Foo<char>` is implemented for `Bar` -note: required by a bound in `Foo::{synthetic#0}` +note: required by a bound in `Foo::{anon_assoc#0}` --> $DIR/return-dont-satisfy-bounds.rs:2:30 | LL | fn foo<F2>(self) -> impl Foo<T>; - | ^^^^^^ required by this bound in `Foo::{synthetic#0}` + | ^^^^^^ required by this bound in `Foo::{anon_assoc#0}` error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied --> $DIR/return-dont-satisfy-bounds.rs:8:34 diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs index ab21dae7dc5..7dc747bffba 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs @@ -8,7 +8,7 @@ pub trait Iterable { impl<'a, I: 'a + Iterable> Iterable for &'a I { type Item = u32; - //~^ ERROR lifetime parameters or bounds on type `Item` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>> {} //~^ ERROR binding for associated type `Item` references lifetime `'missing` diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr index d8a2eef94a1..eaa320455bb 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr @@ -12,17 +12,17 @@ LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missin | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `Item` do not match the trait declaration --> $DIR/span-bug-issue-121457.rs:10:14 | LL | type Item<'a> - | ---- lifetimes in impl do not match this type in trait + | ---- lifetimes in impl do not match this associated type in trait LL | where LL | Self: 'a; | -- this bound might be missing in the impl ... LL | type Item = u32; - | ^ lifetimes do not match type in trait + | ^ lifetimes do not match associated type in trait error[E0277]: `()` is not an iterator --> $DIR/span-bug-issue-121457.rs:13:23 diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs index 0064eaa9318..b573b8fc610 100644 --- a/tests/ui/imports/redundant-import-extern-prelude.rs +++ b/tests/ui/imports/redundant-import-extern-prelude.rs @@ -5,7 +5,8 @@ // See also the discussion in <https://github.com/rust-lang/rust/pull/122954>. -//@ compile-flags: --extern aux_issue_121915 --edition 2018 +//@ compile-flags: --extern aux_issue_121915 +//@ edition: 2018 //@ aux-build: aux-issue-121915.rs #[deny(redundant_imports)] diff --git a/tests/ui/imports/redundant-import-extern-prelude.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr index 6d2518c1284..06cce7e1725 100644 --- a/tests/ui/imports/redundant-import-extern-prelude.stderr +++ b/tests/ui/imports/redundant-import-extern-prelude.stderr @@ -1,11 +1,11 @@ error: the item `aux_issue_121915` is imported redundantly - --> $DIR/redundant-import-extern-prelude.rs:14:9 + --> $DIR/redundant-import-extern-prelude.rs:15:9 | LL | use aux_issue_121915; | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude | note: the lint level is defined here - --> $DIR/redundant-import-extern-prelude.rs:11:8 + --> $DIR/redundant-import-extern-prelude.rs:12:8 | LL | #[deny(redundant_imports)] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs index dc499bc40b6..7108776757e 100644 --- a/tests/ui/imports/redundant-import-issue-121915-2015.rs +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --extern aux_issue_121915 --edition 2015 +//@ compile-flags: --extern aux_issue_121915 +//@ edition: 2015 //@ aux-build: aux-issue-121915.rs extern crate aux_issue_121915; diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr index f4e9f604896..367a4f1cd15 100644 --- a/tests/ui/imports/redundant-import-issue-121915-2015.stderr +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -1,5 +1,5 @@ error: the item `aux_issue_121915` is imported redundantly - --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + --> $DIR/redundant-import-issue-121915-2015.rs:9:9 | LL | extern crate aux_issue_121915; | ------------------------------ the item `aux_issue_121915` is already imported here @@ -8,7 +8,7 @@ LL | use aux_issue_121915; | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/redundant-import-issue-121915-2015.rs:6:8 + --> $DIR/redundant-import-issue-121915-2015.rs:7:8 | LL | #[deny(redundant_imports)] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs index ee3ceb6e3a3..3c036b843fd 100644 --- a/tests/ui/imports/suggest-remove-issue-121315.rs +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2021 +//@ edition: 2021 #![deny(unused_imports, redundant_imports)] #![allow(dead_code)] diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs index 8ccce97f7bf..61b35cf8c64 100644 --- a/tests/ui/invalid-compile-flags/crate-type-flag.rs +++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs @@ -3,8 +3,6 @@ //! //! This test does not try to check if the output artifacts are valid. -// FIXME(#132309): add a proper `supports-crate-type` directive. - // Single valid crate types should pass //@ revisions: lib rlib staticlib dylib cdylib bin proc_dash_macro @@ -17,19 +15,18 @@ //@[staticlib] compile-flags: --crate-type=staticlib //@[staticlib] check-pass -//@[dylib] ignore-musl (dylib is supported, but musl libc is statically linked by default) -//@[dylib] ignore-wasm (dylib is not supported) +//@[dylib] needs-crate-type: dylib //@[dylib] compile-flags: --crate-type=dylib //@[dylib] check-pass -//@[cdylib] ignore-musl (cdylib is supported, but musl libc is statically linked by default) +//@[cdylib] needs-crate-type: cdylib //@[cdylib] compile-flags: --crate-type=cdylib //@[cdylib] check-pass //@[bin] compile-flags: --crate-type=bin //@[bin] check-pass -//@[proc_dash_macro] ignore-wasm (proc-macro is not supported) +//@[proc_dash_macro] needs-crate-type: proc-macro //@[proc_dash_macro] needs-unwind (panic=abort causes warning to be emitted) //@[proc_dash_macro] compile-flags: --crate-type=proc-macro //@[proc_dash_macro] check-pass diff --git a/tests/ui/label/label_break_value_desugared_break.rs b/tests/ui/label/label_break_value_desugared_break.rs index b7e7fd47c27..17ef1ba6d24 100644 --- a/tests/ui/label/label_break_value_desugared_break.rs +++ b/tests/ui/label/label_break_value_desugared_break.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] //@ run-pass diff --git a/tests/ui/let-else/issue-102317.rs b/tests/ui/let-else/issue-102317.rs index d94410e10a8..5afcacfc3aa 100644 --- a/tests/ui/let-else/issue-102317.rs +++ b/tests/ui/let-else/issue-102317.rs @@ -1,6 +1,7 @@ // issue #102317 //@ build-pass -//@ compile-flags: --edition 2021 -C opt-level=3 -Zvalidate-mir +//@ compile-flags: -C opt-level=3 -Zvalidate-mir +//@ edition: 2021 struct SegmentJob; diff --git a/tests/ui/lifetimes/issue-83737-binders-across-types.rs b/tests/ui/lifetimes/issue-83737-binders-across-types.rs index d20c84dae3f..6f399381294 100644 --- a/tests/ui/lifetimes/issue-83737-binders-across-types.rs +++ b/tests/ui/lifetimes/issue-83737-binders-across-types.rs @@ -1,5 +1,5 @@ //@ build-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ compile-flags: --crate-type rlib use std::future::Future; diff --git a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs index 466bcdc6be0..dcc8c7e94ba 100644 --- a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs +++ b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs @@ -1,5 +1,5 @@ //@ build-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ compile-flags: --crate-type rlib use std::future::Future; diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs index 21395475fb3..b3e8ad08ba1 100644 --- a/tests/ui/lifetimes/no_lending_iterators.rs +++ b/tests/ui/lifetimes/no_lending_iterators.rs @@ -25,7 +25,7 @@ impl Bar for usize { impl Bar for isize { type Item<'a> = &'a isize; - //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195] + //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195] fn poke(&mut self, item: Self::Item) { self += *item; diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr index 9ceaef2f9b1..340ef935885 100644 --- a/tests/ui/lifetimes/no_lending_iterators.stderr +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -16,14 +16,14 @@ error: in the trait associated type is declared without lifetime parameters, so LL | type Item = &usize; | ^ this lifetime must come from the implemented type -error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `Item` do not match the trait declaration --> $DIR/no_lending_iterators.rs:27:14 | LL | type Item; - | - lifetimes in impl do not match this type in trait + | - lifetimes in impl do not match this associated type in trait ... LL | type Item<'a> = &'a isize; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait error: aborting due to 3 previous errors diff --git a/tests/ui/linkage-attr/issue-12133-3.rs b/tests/ui/linkage-attr/issue-12133-3.rs index 473d5774c16..df1b0b2f728 100644 --- a/tests/ui/linkage-attr/issue-12133-3.rs +++ b/tests/ui/linkage-attr/issue-12133-3.rs @@ -2,8 +2,7 @@ //@ aux-build:issue-12133-rlib.rs //@ aux-build:issue-12133-dylib.rs //@ aux-build:issue-12133-dylib2.rs -//@ ignore-wasm32 no dylib support -//@ ignore-musl +//@ needs-crate-type: dylib //@ needs-dynamic-linking diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs index 6f701cd27c6..a63e9c5ddf2 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs @@ -10,28 +10,27 @@ // But should fire on non-binary crates. -// FIXME(#132309): dylib crate type is not supported on wasm; we need a proper -// supports-crate-type directive. Also, needs-dynamic-linking should rule out -// musl since it supports neither dylibs nor cdylibs. -//@[dylib_] ignore-wasm -//@[dylib_] ignore-musl -//@[cdylib_] ignore-musl - -//@[dylib_] needs-dynamic-linking +//@[cdylib_] compile-flags: --crate-type=cdylib //@[cdylib_] needs-dynamic-linking -//@[proc_macro_] force-host -//@[proc_macro_] no-prefer-dynamic +//@[cdylib_] needs-crate-type: cdylib -//@[cdylib_] compile-flags: --crate-type=cdylib //@[dylib_] compile-flags: --crate-type=dylib +//@[dylib_] needs-dynamic-linking +//@[dylib_] needs-crate-type: dylib + //@[lib_] compile-flags: --crate-type=lib + +//@[proc_macro_] force-host +//@[proc_macro_] no-prefer-dynamic //@[proc_macro_] compile-flags: --crate-type=proc-macro +// The compiler may emit a warning that causes stderr output that contains a warning this test does +// not wish to check. +//@[proc_macro_] needs-unwind +//@[proc_macro_] needs-crate-type: proc-macro + //@[rlib_] compile-flags: --crate-type=rlib -//@[staticlib_] compile-flags: --crate-type=staticlib -// The compiler may emit a warning that causes stderr output -// that contains a warning this test does not wish to check. -//@[proc_macro_] needs-unwind +//@[staticlib_] compile-flags: --crate-type=staticlib #![crate_name = "NonSnakeCase"] //[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr index 1192b690e29..a9c01886744 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/unqualified_local_imports.rs b/tests/ui/lint/unqualified_local_imports.rs index 9de71471342..b7036f9c68e 100644 --- a/tests/ui/lint/unqualified_local_imports.rs +++ b/tests/ui/lint/unqualified_local_imports.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2018 +//@ edition: 2018 #![feature(unqualified_local_imports)] #![deny(unqualified_local_imports)] diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs index 817dfe82114..890ba378263 100644 --- a/tests/ui/lint/unused/issue-70041.rs +++ b/tests/ui/lint/unused/issue-70041.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2018 +//@ edition: 2018 //@ run-pass macro_rules! regex { diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed index 061a4b98033..c0d27609358 100644 --- a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed +++ b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed @@ -1,6 +1,6 @@ //@ run-rustfix //@ check-pass -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![warn(edition_2024_expr_fragment_specifier)] macro_rules! m { diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.rs b/tests/ui/macros/expr_2021_cargo_fix_edition.rs index cd9cd965fad..b2c16fc7041 100644 --- a/tests/ui/macros/expr_2021_cargo_fix_edition.rs +++ b/tests/ui/macros/expr_2021_cargo_fix_edition.rs @@ -1,6 +1,6 @@ //@ run-rustfix //@ check-pass -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![warn(edition_2024_expr_fragment_specifier)] macro_rules! m { diff --git a/tests/ui/macros/reparse-expr-issue-139495.rs b/tests/ui/macros/reparse-expr-issue-139495.rs new file mode 100644 index 00000000000..38d24573a53 --- /dev/null +++ b/tests/ui/macros/reparse-expr-issue-139495.rs @@ -0,0 +1,7 @@ +macro_rules! m { + ($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern` +} + +fn main() { + m!(-2) +} diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr new file mode 100644 index 00000000000..73a8ed87ba0 --- /dev/null +++ b/tests/ui/macros/reparse-expr-issue-139495.stderr @@ -0,0 +1,13 @@ +error: expected expression, found keyword `extern` + --> $DIR/reparse-expr-issue-139495.rs:2:22 + | +LL | ($abi : expr) => { extern $abi } + | ^^^^^^ expected expression +... +LL | m!(-2) + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/mir/issue-105809.rs b/tests/ui/mir/issue-105809.rs index e7a8fb65268..a46dcf350ad 100644 --- a/tests/ui/mir/issue-105809.rs +++ b/tests/ui/mir/issue-105809.rs @@ -1,7 +1,8 @@ // Non-regression test ICE from issue #105809 and duplicates. //@ build-pass: the ICE is during codegen -//@ compile-flags: --edition 2018 -Zmir-opt-level=1 +//@ compile-flags: -Zmir-opt-level=1 +//@ edition: 2018 use std::{future::Future, pin::Pin}; diff --git a/tests/ui/no_std/simple-runs.rs b/tests/ui/no_std/simple-runs.rs new file mode 100644 index 00000000000..8931ac7ed11 --- /dev/null +++ b/tests/ui/no_std/simple-runs.rs @@ -0,0 +1,41 @@ +//! Check that `no_std` binaries can link and run without depending on `libstd`. + +//@ run-pass +//@ compile-flags: -Cpanic=abort +//@ ignore-wasm different `main` convention + +#![no_std] +#![no_main] + +use core::ffi::{c_char, c_int}; +use core::panic::PanicInfo; + +// # Linux +// +// Linking `libc` is required by crt1.o, otherwise the linker fails with: +// > /usr/bin/ld: in function `_start': undefined reference to `__libc_start_main' +// +// # Apple +// +// Linking `libSystem` is required, otherwise the linker fails with: +// > ld: dynamic executables or dylibs must link with libSystem.dylib +// +// With the new linker introduced in Xcode 15, the error is instead: +// > Undefined symbols: "dyld_stub_binder", referenced from: <initial-undefines> +// +// This _can_ be worked around by raising the deployment target with +// MACOSX_DEPLOYMENT_TARGET=13.0, though it's a bit hard to test that while +// still allowing the test suite to support running with older Xcode versions. +#[cfg_attr(all(not(target_vendor = "apple"), unix), link(name = "c"))] +#[cfg_attr(target_vendor = "apple", link(name = "System"))] +extern "C" {} + +#[panic_handler] +fn panic_handler(_info: &PanicInfo<'_>) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { + 0 +} diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs index 8b782413f6a..a691ceb566b 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs @@ -1,9 +1,7 @@ //@ build-fail //@ compile-flags:-C panic=abort -C prefer-dynamic //@ needs-unwind -//@ ignore-musl - no dylibs here -//@ ignore-emscripten -//@ ignore-sgx no dynamic lib support +//@ needs-crate-type: dylib // This is a test where the local crate, compiled with `panic=abort`, links to // the standard library **dynamically** which is already linked against diff --git a/tests/ui/parser/impl-parsing-2.rs b/tests/ui/parser/impl-parsing-2.rs new file mode 100644 index 00000000000..7a71217b21c --- /dev/null +++ b/tests/ui/parser/impl-parsing-2.rs @@ -0,0 +1,4 @@ +impl ! {} // OK + +default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` +//~^ ERROR `default` is not followed by an item diff --git a/tests/ui/parser/impl-parsing-2.stderr b/tests/ui/parser/impl-parsing-2.stderr new file mode 100644 index 00000000000..45e2c428242 --- /dev/null +++ b/tests/ui/parser/impl-parsing-2.stderr @@ -0,0 +1,18 @@ +error: `default` is not followed by an item + --> $DIR/impl-parsing-2.rs:3:1 + | +LL | default unsafe FAIL + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: expected item, found keyword `unsafe` + --> $DIR/impl-parsing-2.rs:3:9 + | +LL | default unsafe FAIL + | ^^^^^^ expected item + | + = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html> + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/impl-parsing.rs b/tests/ui/parser/impl-parsing.rs index 80ce8885570..7692a81dd42 100644 --- a/tests/ui/parser/impl-parsing.rs +++ b/tests/ui/parser/impl-parsing.rs @@ -2,9 +2,4 @@ impl ! {} // OK impl ! where u8: Copy {} // OK impl Trait Type {} //~ ERROR missing `for` in a trait impl -impl Trait .. {} //~ ERROR missing `for` in a trait impl impl ?Sized for Type {} //~ ERROR expected a trait, found type -impl ?Sized for .. {} //~ ERROR expected a trait, found type - -default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` -//~^ ERROR `default` is not followed by an item diff --git a/tests/ui/parser/impl-parsing.stderr b/tests/ui/parser/impl-parsing.stderr index 6a24a9453e6..b2512120dc8 100644 --- a/tests/ui/parser/impl-parsing.stderr +++ b/tests/ui/parser/impl-parsing.stderr @@ -9,44 +9,11 @@ help: add `for` here LL | impl Trait for Type {} | +++ -error: missing `for` in a trait impl - --> $DIR/impl-parsing.rs:5:11 - | -LL | impl Trait .. {} - | ^ - | -help: add `for` here - | -LL | impl Trait for .. {} - | +++ - error: expected a trait, found type - --> $DIR/impl-parsing.rs:6:6 + --> $DIR/impl-parsing.rs:5:6 | LL | impl ?Sized for Type {} | ^^^^^^ -error: expected a trait, found type - --> $DIR/impl-parsing.rs:7:6 - | -LL | impl ?Sized for .. {} - | ^^^^^^ - -error: `default` is not followed by an item - --> $DIR/impl-parsing.rs:9:1 - | -LL | default unsafe FAIL - | ^^^^^^^ the `default` qualifier - | - = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` - -error: expected item, found keyword `unsafe` - --> $DIR/impl-parsing.rs:9:9 - | -LL | default unsafe FAIL - | ^^^^^^ expected item - | - = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html> - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs index 27452f4d45e..795f32059f2 100644 --- a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs +++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 fn main() { let try = "foo"; //~ error: expected identifier, found reserved keyword `try` diff --git a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs index 20bbbff8fd2..4053ccdfbf1 100644 --- a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs +++ b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs @@ -3,7 +3,7 @@ extern crate foreign_trait_with_assoc; use foreign_trait_with_assoc::Foo; -// Make sure we don't try to call `fn_arg_names` on a non-fn item. +// Make sure we don't try to call `fn_arg_idents` on a non-fn item. impl Foo for Bar {} //~^ ERROR cannot find type `Bar` in this scope diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index f1f53e300ab..400969c279e 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied LL | fn main() -> Something { | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` | -note: required by a bound in `Main::{synthetic#0}` +note: required by a bound in `Main::{anon_assoc#0}` --> $DIR/issue-103052-2.rs:3:27 | LL | fn main() -> impl std::process::Termination; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}` error: aborting due to 1 previous error diff --git a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs index dd604b6bf7d..f4f383e008a 100644 --- a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs +++ b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs @@ -2,7 +2,8 @@ // trait object type to fail, causing an ICE. // //@ needs-sanitizer-cfi -//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021 +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/sanitizer/cfi/coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs index 3ad896afd00..39a754f1036 100644 --- a/tests/ui/sanitizer/cfi/coroutine.rs +++ b/tests/ui/sanitizer/cfi/coroutine.rs @@ -26,7 +26,7 @@ use std::async_iter::AsyncIterator; #[test] fn general_coroutine() { - let mut coro = #[coroutine] |x: i32| { + let coro = #[coroutine] |x: i32| { yield x; "done" }; diff --git a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs index e5b1e032257..7d0c73c2841 100644 --- a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs +++ b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs @@ -2,7 +2,8 @@ // encode_ty and caused the compiler to ICE. // //@ needs-sanitizer-cfi -//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021 +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 4dc2e4d5a80..e4d47cdb381 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -1,8 +1,10 @@ //@ run-pass -#![feature(repr_simd, core_intrinsics)] +#![feature(repr_simd, intrinsics, core_intrinsics)] -use std::intrinsics::simd::{simd_extract, simd_insert, simd_shuffle}; +use std::intrinsics::simd::{ + simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn, simd_shuffle, +}; #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] @@ -70,6 +72,41 @@ fn main() { all_eq!(simd_extract(x8, 6), 86); all_eq!(simd_extract(x8, 7), 87); } + unsafe { + all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21])); + all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100])); + + all_eq!(simd_insert_dyn(x4, 0, 100), i32x4([100, 41, 42, 43])); + all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43])); + all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43])); + all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 100])); + + all_eq!(simd_insert_dyn(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); + + all_eq!(simd_extract_dyn(x2, 0), 20); + all_eq!(simd_extract_dyn(x2, 1), 21); + + all_eq!(simd_extract_dyn(x4, 0), 40); + all_eq!(simd_extract_dyn(x4, 1), 41); + all_eq!(simd_extract_dyn(x4, 2), 42); + all_eq!(simd_extract_dyn(x4, 3), 43); + + all_eq!(simd_extract_dyn(x8, 0), 80); + all_eq!(simd_extract_dyn(x8, 1), 81); + all_eq!(simd_extract_dyn(x8, 2), 82); + all_eq!(simd_extract_dyn(x8, 3), 83); + all_eq!(simd_extract_dyn(x8, 4), 84); + all_eq!(simd_extract_dyn(x8, 5), 85); + all_eq!(simd_extract_dyn(x8, 6), 86); + all_eq!(simd_extract_dyn(x8, 7), 87); + } let y2 = i32x2([120, 121]); let y4 = i32x4([140, 141, 142, 143]); diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed index 611be9911d9..e097fa8cc1d 100644 --- a/tests/ui/suggestions/enum-method-probe.fixed +++ b/tests/ui/suggestions/enum-method-probe.fixed @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs index e183ebd25f2..665ee7d0aaa 100644 --- a/tests/ui/suggestions/enum-method-probe.rs +++ b/tests/ui/suggestions/enum-method-probe.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed index cfea66b57ec..3dc939d6b5c 100644 --- a/tests/ui/suggestions/inner_type.fixed +++ b/tests/ui/suggestions/inner_type.fixed @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix pub struct Struct<T> { diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs index 5fedf3f256e..81a05c25311 100644 --- a/tests/ui/suggestions/inner_type.rs +++ b/tests/ui/suggestions/inner_type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix pub struct Struct<T> { diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs index 1f37e9a5f6d..cc5b878b632 100644 --- a/tests/ui/suggestions/issue-86667.rs +++ b/tests/ui/suggestions/issue-86667.rs @@ -1,7 +1,7 @@ // Regression test for #86667, where a garbled suggestion was issued for // a missing named lifetime parameter. -//@ compile-flags: --edition 2018 +//@ edition: 2018 async fn a(s1: &str, s2: &str) -> &str { //~^ ERROR: missing lifetime specifier [E0106] diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index be761e49ba0..03e26615d7e 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -6,30 +6,134 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0277]: the trait bound `T: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:29:37 +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} - | ^ + | ^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires caching mir of `accept0::{constant#0}` for CTFE... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires borrow-checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building MIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building an abstract representation for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building THIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: ...which again requires evaluating type-level constant, completing the cycle +note: cycle used when checking that `accept0` is well-formed + --> $DIR/unsatisfied-const-trait-bound.rs:29:1 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0277]: the trait bound `T: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:33:50 +error[E0391]: cycle detected when caching mir of `accept1::{constant#0}` for CTFE + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} - | ^ - -error[E0277]: the trait bound `Ty: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:22:15 + | ^^^^^^^^^^^^^ + | +note: ...which requires elaborating drops for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires borrow-checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building MIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | -LL | require::<Ty>(); - | ^^ +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building an abstract representation for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building THIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | -note: required by a bound in `require` - --> $DIR/unsatisfied-const-trait-bound.rs:8:15 +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires evaluating type-level constant... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | -LL | fn require<T: const Trait>() {} - | ^^^^^^^^^^^ required by this bound in `require` +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: ...which again requires caching mir of `accept1::{constant#0}` for CTFE, completing the cycle +note: cycle used when const-evaluating + checking `accept1::{constant#0}` + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs new file mode 100644 index 00000000000..68e234b0f20 --- /dev/null +++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs @@ -0,0 +1,5 @@ +// Suggestion to use impl trait in closure parameter is invalid, see issue 138932 +fn main() { + let c = |f: dyn Fn()| f(); + //~^ ERROR: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time +} diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr new file mode 100644 index 00000000000..8218990503c --- /dev/null +++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + --> $DIR/dont-suggest-impl-as-closure-arg.rs:3:17 + | +LL | let c = |f: dyn Fn()| f(); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | let c = |f: &dyn Fn()| f(); + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index 931879a6722..f7c49049e2d 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![feature(rustc_attrs)] diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr index bc89842d16a..a76a10d20ee 100644 --- a/tests/ui/traits/next-solver/async.fail.stderr +++ b/tests/ui/traits/next-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` +error[E0271]: type mismatch resolving `() == i32` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ expected `i32`, found `()` + | ----------- ^^^^^^^^ types differ | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs index fded7743547..34c0ed02eeb 100644 --- a/tests/ui/traits/next-solver/async.rs +++ b/tests/ui/traits/next-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` + //[fail]~^ ERROR type mismatch resolving `() == i32` } #[cfg(pass)] diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 3d3fdc926f6..1dad1903a64 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {} fn transmute<A, B>(x: A) -> B { foo::<A, B, dyn Trait<A = A, B = B>>(x) - //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` + //~^ ERROR type mismatch resolving `A == B` } fn foo<A, B, T: ?Sized>(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 39849d4c865..d04376cc9c6 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,17 +1,9 @@ -error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` +error[E0271]: type mismatch resolving `A == B` --> $DIR/more-object-bound.rs:12:5 | -LL | fn transmute<A, B>(x: A) -> B { - | - - expected type parameter - | | - | found type parameter LL | foo::<A, B, dyn Trait<A = A, B = B>>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | - = note: expected type parameter `B` - found type parameter `A` - = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required because it appears within the type `dyn Trait<A = A, B = B>` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 diff --git a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs index e5208e3e47d..198e6199e92 100644 --- a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs +++ b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs @@ -1,7 +1,8 @@ // Regression test for #132335. This previously ICE'd due to ambiguity // in MIR typeck. -//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018 +//@ compile-flags: -Znext-solver=globally --crate-type lib +//@ edition: 2018 //@ check-pass use core::future::Future; use core::pin::Pin; diff --git a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs index 8388751fea6..b79926eebda 100644 --- a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs +++ b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs @@ -3,7 +3,7 @@ // of the async block. This caused borrowck of the recursive // call to ICE. -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ check-pass async fn test() { Box::pin(test()).await; diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index 94a9484ecdc..b2a8c8cb4ae 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {} fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() { needs_bar::<T::Assoc1>(); - //~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied + //~^ ERROR the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index 6f5111a6193..c4be47e3520 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied +error[E0277]: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied --> $DIR/recursive-self-normalization-2.rs:15:17 | LL | needs_bar::<T::Assoc1>(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1` + | ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo2>::Assoc2` | note: required by a bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:17 @@ -11,7 +11,7 @@ LL | fn needs_bar<S: Bar>() {} | ^^^ required by this bound in `needs_bar` help: consider further restricting the associated type | -LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar { +LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar { | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs index f8fa410b7d4..50851a5b0f8 100644 --- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2021 +//@ edition: 2021 fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize { //~^ ERROR expected trait, found builtin type `usize` diff --git a/tests/ui/try-block/issue-45124.rs b/tests/ui/try-block/issue-45124.rs index e9e0e767efa..26e1736faac 100644 --- a/tests/ui/try-block/issue-45124.rs +++ b/tests/ui/try-block/issue-45124.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unreachable_code)] -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs index bfff757a2df..9b45b0d9559 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-bad-lifetime.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-bad-type.rs b/tests/ui/try-block/try-block-bad-type.rs index 71eb832dd4e..00cd0af127c 100644 --- a/tests/ui/try-block/try-block-bad-type.rs +++ b/tests/ui/try-block/try-block-bad-type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-catch.rs b/tests/ui/try-block/try-block-catch.rs index c3aa442ba66..170d5bab3e5 100644 --- a/tests/ui/try-block/try-block-catch.rs +++ b/tests/ui/try-block/try-block-catch.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-edition2015.rs b/tests/ui/try-block/try-block-in-edition2015.rs index 423269df12d..4ebe2d31b81 100644 --- a/tests/ui/try-block/try-block-in-edition2015.rs +++ b/tests/ui/try-block/try-block-in-edition2015.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2015 +//@ edition: 2015 pub fn main() { let try_result: Option<_> = try { diff --git a/tests/ui/try-block/try-block-in-match-arm.rs b/tests/ui/try-block/try-block-in-match-arm.rs index cecbf724916..703b1c54bbb 100644 --- a/tests/ui/try-block/try-block-in-match-arm.rs +++ b/tests/ui/try-block/try-block-in-match-arm.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-match.rs b/tests/ui/try-block/try-block-in-match.rs index 5c62f41efdb..63a32000f62 100644 --- a/tests/ui/try-block/try-block-in-match.rs +++ b/tests/ui/try-block/try-block-in-match.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-return.rs b/tests/ui/try-block/try-block-in-return.rs index ee5ca696b6d..7dc023b90db 100644 --- a/tests/ui/try-block/try-block-in-return.rs +++ b/tests/ui/try-block/try-block-in-return.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-while.rs b/tests/ui/try-block/try-block-in-while.rs index 88a97136c59..d6232546cea 100644 --- a/tests/ui/try-block/try-block-in-while.rs +++ b/tests/ui/try-block/try-block-in-while.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs index 52ec0c44a05..14adee8944f 100644 --- a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-opt-init.rs b/tests/ui/try-block/try-block-opt-init.rs index fbe7f90d030..55ac5b4a37c 100644 --- a/tests/ui/try-block/try-block-opt-init.rs +++ b/tests/ui/try-block/try-block-opt-init.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-type-error.rs b/tests/ui/try-block/try-block-type-error.rs index 79cdb7a2e48..4e482b40140 100644 --- a/tests/ui/try-block/try-block-type-error.rs +++ b/tests/ui/try-block/try-block-type-error.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-unreachable-code-lint.rs b/tests/ui/try-block/try-block-unreachable-code-lint.rs index 62c74b76d59..9135882a57b 100644 --- a/tests/ui/try-block/try-block-unreachable-code-lint.rs +++ b/tests/ui/try-block/try-block-unreachable-code-lint.rs @@ -1,6 +1,6 @@ // Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324. -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ check-pass #![feature(try_blocks)] #![warn(unreachable_code)] diff --git a/tests/ui/try-block/try-block-unused-delims.fixed b/tests/ui/try-block/try-block-unused-delims.fixed index 348eb8f7965..4769c45d38c 100644 --- a/tests/ui/try-block/try-block-unused-delims.fixed +++ b/tests/ui/try-block/try-block-unused-delims.fixed @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ run-rustfix #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-unused-delims.rs b/tests/ui/try-block/try-block-unused-delims.rs index f119e1074f6..0520d1d620f 100644 --- a/tests/ui/try-block/try-block-unused-delims.rs +++ b/tests/ui/try-block/try-block-unused-delims.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ run-rustfix #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block.rs b/tests/ui/try-block/try-block.rs index 7520cbaad37..3fa0d2ba0f2 100644 --- a/tests/ui/try-block/try-block.rs +++ b/tests/ui/try-block/try-block.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-is-identifier-edition2015.rs b/tests/ui/try-block/try-is-identifier-edition2015.rs index 54bd049442f..99f4d206859 100644 --- a/tests/ui/try-block/try-is-identifier-edition2015.rs +++ b/tests/ui/try-block/try-is-identifier-edition2015.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(non_camel_case_types)] -//@ compile-flags: --edition 2015 +//@ edition: 2015 fn main() { let try = 2; diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs index 4f3f6d37eff..f69fd5747b6 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ build-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs index cad1cbf61a2..736a9dfb490 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --edition=2021 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2021 //@ rustc-env:RUST_BACKTRACE=0 //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr index 13f5d8b8ea6..c58d919c4b1 100644 --- a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr +++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `Baz` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14 | LL | type Baz<'a>; diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs index 11cbb876631..614d2d0471b 100644 --- a/tests/ui/type-alias-impl-trait/issue-93411.rs +++ b/tests/ui/type-alias-impl-trait/issue-93411.rs @@ -2,7 +2,7 @@ // this test used to stack overflow due to infinite recursion. //@ check-pass -//@ compile-flags: --edition=2018 +//@ edition: 2018 use std::future::Future; diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index 08f3c404bed..7f0f6a214aa 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] //@ check-pass //@ revisions: default edition2021 -//@[edition2021] compile-flags: --edition 2021 +//@[edition2021]edition: 2021 fn main() { type T = impl Copy; diff --git a/tests/ui/typeck/issue-65611.rs b/tests/ui/typeck/issue-65611.rs index 7645311496d..0dae75927a8 100644 --- a/tests/ui/typeck/issue-65611.rs +++ b/tests/ui/typeck/issue-65611.rs @@ -58,6 +58,5 @@ fn main() { let mut buffer = ArrayVec::new(); let x = buffer.last().unwrap().0.clone(); //~^ ERROR type annotations needed - //~| ERROR no field `0` on type `&_` buffer.reverse(); } diff --git a/tests/ui/typeck/issue-65611.stderr b/tests/ui/typeck/issue-65611.stderr index 2278450a6d8..52f0f0cffff 100644 --- a/tests/ui/typeck/issue-65611.stderr +++ b/tests/ui/typeck/issue-65611.stderr @@ -4,13 +4,6 @@ error[E0282]: type annotations needed LL | let x = buffer.last().unwrap().0.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` -error[E0609]: no field `0` on type `&_` - --> $DIR/issue-65611.rs:59:36 - | -LL | let x = buffer.last().unwrap().0.clone(); - | ^ unknown field - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0282, E0609. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs index 18aa329ae36..c21eea743e9 100644 --- a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs +++ b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs @@ -1,3 +1,3 @@ -//@ compile-flags: --edition=2018 +//@ edition: 2018 pub use u32; diff --git a/triagebot.toml b/triagebot.toml index 8a7797bd1ff..226f024c156 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1123,9 +1123,10 @@ cc = ["@ZuseZ4"] warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ + "fmease", "jyn514", - "saethlin", "Noratrieb", + "spastorino", ] [[assign.warn_non_default_branch.exceptions]] |
