diff --git a/Cargo.lock b/Cargo.lock index e4e080b94577..12970dd1ebf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2814,9 +2814,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] diff --git a/RELEASES.md b/RELEASES.md index 8702bb021184..99733bade32c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -503,7 +503,7 @@ Compatibility Notes * We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. - + The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. @@ -584,7 +584,7 @@ Stabilized APIs - [`impl Default for Arc`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3CCStr%3E) - [`impl Default for Arc<[T]>`](https://doc.rust-lang.org/beta/alloc/sync/struct.Arc.html#impl-Default-for-Arc%3C%5BT%5D%3E) - [`impl IntoIterator for Box<[T]>`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-IntoIterator-for-Box%3C%5BI%5D,+A%3E) -- [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E) +- [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3CString%3E-for-Box%3Cstr%3E) - [`impl FromIterator for Box`](https://doc.rust-lang.org/beta/alloc/boxed/struct.Box.html#impl-FromIterator%3Cchar%3E-for-Box%3Cstr%3E) - [`LazyCell`](https://doc.rust-lang.org/beta/core/cell/struct.LazyCell.html) - [`LazyLock`](https://doc.rust-lang.org/beta/std/sync/struct.LazyLock.html) @@ -1816,7 +1816,7 @@ Compiler - [Detect uninhabited types early in const eval](https://github.com/rust-lang/rust/pull/109435/) - [Switch to LLD as default linker for {arm,thumb}v4t-none-eabi](https://github.com/rust-lang/rust/pull/109721/) - [Add tier 3 target `loongarch64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/96971) -- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/), +- [Add tier 3 target for `i586-pc-nto-qnx700` (QNX Neutrino RTOS, version 7.0)](https://github.com/rust-lang/rust/pull/109173/), - [Insert alignment checks for pointer dereferences as debug assertions](https://github.com/rust-lang/rust/pull/98112) This catches undefined behavior at runtime, and may cause existing code to fail. @@ -2023,7 +2023,7 @@ Compatibility Notes If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the list. - + Internal Changes diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2f55a9eaedab..69ba78282f96 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -627,9 +627,11 @@ impl Pat { | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)), // Trivial wrappers over inner patterns. - PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => { - s.walk(it) - } + PatKind::Box(s) + | PatKind::Deref(s) + | PatKind::Ref(s, _) + | PatKind::Paren(s) + | PatKind::Guard(s, _) => s.walk(it), // These patterns do not contain subpatterns, skip. PatKind::Wild @@ -839,6 +841,9 @@ pub enum PatKind { // A never pattern `!`. Never, + /// A guard pattern (e.g., `x if guard(x)`). + Guard(P, P), + /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 622c260868ed..3a4a8ce266e9 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1525,6 +1525,10 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { visit_opt(e2, |e| vis.visit_expr(e)); vis.visit_span(span); } + PatKind::Guard(p, e) => { + vis.visit_pat(p); + vis.visit_expr(e); + } PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { visit_thin_vec(elems, |elem| vis.visit_pat(elem)) } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2f6998783fa3..0b000c8cef8a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -682,6 +682,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res visit_opt!(visitor, visit_expr, lower_bound); visit_opt!(visitor, visit_expr, upper_bound); } + PatKind::Guard(subpattern, guard_condition) => { + try_visit!(visitor.visit_pat(subpattern)); + try_visit!(visitor.visit_expr(guard_condition)); + } PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index ace7bfb5c73f..c4bae084a3f8 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -114,6 +114,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_range_end(end, e2.is_some()), ); } + // FIXME(guard_patterns): lower pattern guards to HIR + PatKind::Guard(inner, _) => pattern = inner, PatKind::Slice(pats) => break self.lower_pat_slice(pats), PatKind::Rest => { // If we reach here the `..` pattern is not semantically allowed. diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 893115160815..390a575a186b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -556,6 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); + gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 479677b0a5ad..49e4a559e738 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1709,6 +1709,14 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); } } + PatKind::Guard(subpat, condition) => { + self.popen(); + self.print_pat(subpat); + self.space(); + self.word_space("if"); + self.print_expr(condition, FixupContext::default()); + self.pclose(); + } PatKind::Slice(elts) => { self.word("["); self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c11103af476e..b42c99e1a6d9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1450,6 +1450,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Param(param_ty) => Ok(( generics.type_param(param_ty, tcx), predicate.trait_ref.print_trait_sugared().to_string(), + Some(predicate.trait_ref.def_id), )), _ => Err(()), } @@ -1463,9 +1464,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { tcx, hir_generics, err, - predicates - .iter() - .map(|(param, constraint)| (param.name.as_str(), &**constraint, None)), + predicates.iter().map(|(param, constraint, def_id)| { + (param.name.as_str(), &**constraint, *def_id) + }), None, ); } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index c9486a730e1c..9f552b3feb95 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -227,8 +227,6 @@ impl CodegenBackend for CraneliftCodegenBackend { sess: &Session, outputs: &OutputFilenames, ) -> (CodegenResults, FxIndexMap) { - let _timer = sess.timer("finish_ongoing_codegen"); - ongoing_codegen.downcast::().unwrap().join(sess, outputs) } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index d8b055137b35..c38c5d4c6442 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -352,84 +352,84 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | sym::saturating_add | sym::saturating_sub => { let ty = arg_tys[0]; - match int_type_width_signed(ty, self) { - Some((width, signed)) => match name { - sym::ctlz | sym::cttz => { - let y = self.const_bool(false); - let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[ - args[0].immediate(), - y, - ]); + if !ty.is_integral() { + tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { + span, + name, + ty, + }); + return Ok(()); + } + let (size, signed) = ty.int_size_and_signed(self.tcx); + let width = size.bits(); + match name { + sym::ctlz | sym::cttz => { + let y = self.const_bool(false); + let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[ + args[0].immediate(), + y, + ]); - self.intcast(ret, llret_ty, false) - } - sym::ctlz_nonzero => { - let y = self.const_bool(true); - let llvm_name = &format!("llvm.ctlz.i{width}"); - let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]); - self.intcast(ret, llret_ty, false) - } - sym::cttz_nonzero => { - let y = self.const_bool(true); - let llvm_name = &format!("llvm.cttz.i{width}"); - let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]); - self.intcast(ret, llret_ty, false) - } - sym::ctpop => { - let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[args - [0] - .immediate()]); - self.intcast(ret, llret_ty, false) - } - sym::bswap => { - if width == 8 { - args[0].immediate() // byte swap a u8/i8 is just a no-op - } else { - self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[ - args[0].immediate() - ]) - } - } - sym::bitreverse => self - .call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[ - args[0].immediate() - ]), - sym::rotate_left | sym::rotate_right => { - let is_left = name == sym::rotate_left; - let val = args[0].immediate(); - let raw_shift = args[1].immediate(); - // rotate = funnel shift with first two args the same - let llvm_name = - &format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width); - - // llvm expects shift to be the same type as the values, but rust - // always uses `u32`. - let raw_shift = self.intcast(raw_shift, self.val_ty(val), false); - - self.call_intrinsic(llvm_name, &[val, val, raw_shift]) - } - sym::saturating_add | sym::saturating_sub => { - let is_add = name == sym::saturating_add; - let lhs = args[0].immediate(); - let rhs = args[1].immediate(); - let llvm_name = &format!( - "llvm.{}{}.sat.i{}", - if signed { 's' } else { 'u' }, - if is_add { "add" } else { "sub" }, - width - ); - self.call_intrinsic(llvm_name, &[lhs, rhs]) - } - _ => bug!(), - }, - None => { - tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { - span, - name, - ty, - }); - return Ok(()); + self.intcast(ret, llret_ty, false) } + sym::ctlz_nonzero => { + let y = self.const_bool(true); + let llvm_name = &format!("llvm.ctlz.i{width}"); + let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]); + self.intcast(ret, llret_ty, false) + } + sym::cttz_nonzero => { + let y = self.const_bool(true); + let llvm_name = &format!("llvm.cttz.i{width}"); + let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]); + self.intcast(ret, llret_ty, false) + } + sym::ctpop => { + let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[ + args[0].immediate() + ]); + self.intcast(ret, llret_ty, false) + } + sym::bswap => { + if width == 8 { + args[0].immediate() // byte swap a u8/i8 is just a no-op + } else { + self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[ + args[0].immediate() + ]) + } + } + sym::bitreverse => self + .call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[ + args[0].immediate() + ]), + sym::rotate_left | sym::rotate_right => { + let is_left = name == sym::rotate_left; + let val = args[0].immediate(); + let raw_shift = args[1].immediate(); + // rotate = funnel shift with first two args the same + let llvm_name = + &format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width); + + // llvm expects shift to be the same type as the values, but rust + // always uses `u32`. + let raw_shift = self.intcast(raw_shift, self.val_ty(val), false); + + self.call_intrinsic(llvm_name, &[val, val, raw_shift]) + } + sym::saturating_add | sym::saturating_sub => { + let is_add = name == sym::saturating_add; + let lhs = args[0].immediate(); + let rhs = args[1].immediate(); + let llvm_name = &format!( + "llvm.{}{}.sat.i{}", + if signed { 's' } else { 'u' }, + if is_add { "add" } else { "sub" }, + width + ); + self.call_intrinsic(llvm_name, &[lhs, rhs]) + } + _ => bug!(), } } @@ -2531,19 +2531,3 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span_bug!(span, "unknown SIMD intrinsic"); } - -// Returns the width of an int Ty, and if it's signed or not -// Returns None if the type is not an integer -// FIXME: there’s multiple of this functions, investigate using some of the already existing -// stuffs. -fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> { - match ty.kind() { - ty::Int(t) => { - Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), true)) - } - ty::Uint(t) => { - Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), false)) - } - _ => None, - } -} diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 3dfb86d422dd..5235891a18df 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -36,7 +36,7 @@ use rustc_codegen_ssa::back::write::{ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; +use rustc_errors::{DiagCtxtHandle, FatalError}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; @@ -370,19 +370,14 @@ impl CodegenBackend for LlvmCodegenBackend { (codegen_results, work_products) } - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { use rustc_codegen_ssa::back::link::link_binary; use crate::back::archive::LlvmArchiveBuilderBuilder; // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs) + link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs); } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ad81ff272c62..f8b3ba79c0d5 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -15,7 +15,7 @@ use rustc_ast::CRATE_NODE_ID; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; +use rustc_errors::{DiagCtxtHandle, FatalError}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; @@ -71,7 +71,7 @@ pub fn link_binary( archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: CodegenResults, outputs: &OutputFilenames, -) -> Result<(), ErrorGuaranteed> { +) { let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); let mut tempfiles_for_stdout_output: Vec = Vec::new(); @@ -119,7 +119,7 @@ pub fn link_binary( &codegen_results, RlibFlavor::Normal, &path, - )? + ) .build(&out_filename); } CrateType::Staticlib => { @@ -129,7 +129,7 @@ pub fn link_binary( &codegen_results, &out_filename, &path, - )?; + ); } _ => { link_natively( @@ -139,7 +139,7 @@ pub fn link_binary( &out_filename, &codegen_results, path.as_ref(), - )?; + ); } } if sess.opts.json_artifact_notifications { @@ -225,8 +225,6 @@ pub fn link_binary( maybe_remove_temps_from_module(preserve_objects, preserve_dwarf_objects, module); } }); - - Ok(()) } // Crate type is not passed when calculating the dylibs to include for LTO. In that case all @@ -298,7 +296,7 @@ fn link_rlib<'a>( codegen_results: &CodegenResults, flavor: RlibFlavor, tmpdir: &MaybeTempDir, -) -> Result, ErrorGuaranteed> { +) -> Box { let mut ab = archive_builder_builder.new_archive_builder(sess); let trailing_metadata = match flavor { @@ -374,7 +372,7 @@ fn link_rlib<'a>( { let path = find_native_static_library(filename.as_str(), true, sess); let src = read(path) - .map_err(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }))?; + .unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e })); let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src); let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); packed_bundled_libs.push(wrapper_file); @@ -392,7 +390,7 @@ fn link_rlib<'a>( codegen_results.crate_info.used_libraries.iter(), tmpdir.as_ref(), true, - )? { + ) { ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); }); @@ -433,7 +431,7 @@ fn link_rlib<'a>( ab.add_file(&lib) } - Ok(ab) + ab } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -445,7 +443,7 @@ fn link_rlib<'a>( fn collate_raw_dylibs<'a>( sess: &Session, used_libraries: impl IntoIterator, -) -> Result)>, ErrorGuaranteed> { +) -> Vec<(String, Vec)> { // Use index maps to preserve original order of imports and libraries. let mut dylib_table = FxIndexMap::>::default(); @@ -469,15 +467,13 @@ fn collate_raw_dylibs<'a>( } } } - if let Some(guar) = sess.dcx().has_errors() { - return Err(guar); - } - Ok(dylib_table + sess.dcx().abort_if_errors(); + dylib_table .into_iter() .map(|(name, imports)| { (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) }) - .collect()) + .collect() } fn create_dll_import_libs<'a>( @@ -486,8 +482,8 @@ fn create_dll_import_libs<'a>( used_libraries: impl IntoIterator, tmpdir: &Path, is_direct_dependency: bool, -) -> Result, ErrorGuaranteed> { - Ok(collate_raw_dylibs(sess, used_libraries)? +) -> Vec { + collate_raw_dylibs(sess, used_libraries) .into_iter() .map(|(raw_dylib_name, raw_dylib_imports)| { let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; @@ -537,7 +533,7 @@ fn create_dll_import_libs<'a>( output_path }) - .collect()) + .collect() } /// Create a static archive. @@ -557,7 +553,7 @@ fn link_staticlib( codegen_results: &CodegenResults, out_filename: &Path, tempdir: &MaybeTempDir, -) -> Result<(), ErrorGuaranteed> { +) { info!("preparing staticlib to {:?}", out_filename); let mut ab = link_rlib( sess, @@ -565,7 +561,7 @@ fn link_staticlib( codegen_results, RlibFlavor::StaticlibBase, tempdir, - )?; + ); let mut all_native_libs = vec![]; let res = each_linked_rlib( @@ -656,8 +652,6 @@ fn link_staticlib( print_native_static_libs(sess, &print.out, &all_native_libs, &all_rust_dylibs); } } - - Ok(()) } /// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a @@ -773,7 +767,7 @@ fn link_natively( out_filename: &Path, codegen_results: &CodegenResults, tmpdir: &Path, -) -> Result<(), ErrorGuaranteed> { +) { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); let self_contained_components = self_contained_components(sess, crate_type); @@ -797,7 +791,7 @@ fn link_natively( temp_filename, codegen_results, self_contained_components, - )?; + ); linker::disable_localization(&mut cmd); @@ -1177,8 +1171,6 @@ fn link_natively( ab.add_file(temp_filename); ab.build(out_filename); } - - Ok(()) } fn strip_symbols_with_external_utility( @@ -2232,7 +2224,7 @@ fn linker_with_args( out_filename: &Path, codegen_results: &CodegenResults, self_contained_components: LinkSelfContainedComponents, -) -> Result { +) -> Command { let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled(); let cmd = &mut *super::linker::get_linker( sess, @@ -2356,7 +2348,7 @@ fn linker_with_args( codegen_results.crate_info.used_libraries.iter(), tmpdir, true, - )? { + ) { cmd.add_object(&output_path); } // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case @@ -2388,7 +2380,7 @@ fn linker_with_args( native_libraries_from_nonstatics, tmpdir, false, - )? { + ) { cmd.add_object(&output_path); } @@ -2435,7 +2427,7 @@ fn linker_with_args( // to it and remove the option. Currently the last holdout is wasm32-unknown-emscripten. add_post_link_args(cmd, sess, flavor); - Ok(cmd.take_cmd()) + cmd.take_cmd() } fn add_order_independent_options( diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7c0e9cfd5a76..90d48d6ee7ec 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1883,7 +1883,11 @@ impl Translate for SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) { + fn emit_diagnostic( + &mut self, + mut diag: rustc_errors::DiagInner, + _registry: &rustc_errors::registry::Registry, + ) { // Check that we aren't missing anything interesting when converting to // the cut-down local `DiagInner`. assert_eq!(diag.span, MultiSpan::new()); @@ -2028,8 +2032,6 @@ pub struct OngoingCodegen { impl OngoingCodegen { pub fn join(self, sess: &Session) -> (CodegenResults, FxIndexMap) { - let _timer = sess.timer("finish_ongoing_codegen"); - self.shared_emitter_main.check(sess, true); let compiled_modules = sess.time("join_worker_thread", || match self.coordinator.join() { Ok(Ok(compiled_modules)) => compiled_modules, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 7eab889edf05..5b4a51fc301c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -4,7 +4,6 @@ use std::hash::Hash; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; -use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::MetadataLoaderDyn; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -84,13 +83,8 @@ pub trait CodegenBackend { ) -> (CodegenResults, FxIndexMap); /// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen). - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { - link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs) + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { + link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs); } /// Returns `true` if this backend can be safely called from multiple threads. diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 489bb54a6f98..23f2aa4d0296 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -140,7 +140,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { err, param_ty.name.as_str(), &constraint, - None, + Some(trait_ref.def_id), None, ); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 2beec544fad9..f54a932e1b6f 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -1018,29 +1018,48 @@ where self.allocate_dyn(layout, kind, MemPlaceMeta::None) } - /// Returns a wide MPlace of type `str` to a new 1-aligned allocation. - /// Immutable strings are deduplicated and stored in global memory. + /// Allocates a sequence of bytes in the interpreter's memory. + /// For immutable allocations, uses deduplication to reuse existing memory. + /// For mutable allocations, creates a new unique allocation. + pub fn allocate_bytes( + &mut self, + bytes: &[u8], + align: Align, + kind: MemoryKind, + mutbl: Mutability, + ) -> InterpResult<'tcx, Pointer> { + // Use cache for immutable strings. + if mutbl.is_not() { + // Use dedup'd allocation function. + let salt = M::get_global_alloc_salt(self, None); + let id = self.tcx.allocate_bytes_dedup(bytes, salt); + + // Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation. + M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind)) + } else { + // Allocate new memory for mutable data. + self.allocate_bytes_ptr(bytes, align, kind, mutbl) + } + } + + /// Allocates a string in the interpreter's memory with metadata for length. + /// Uses `allocate_bytes` internally but adds string-specific metadata handling. pub fn allocate_str( &mut self, str: &str, kind: MemoryKind, mutbl: Mutability, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - let tcx = self.tcx.tcx; + let bytes = str.as_bytes(); + let ptr = self.allocate_bytes(bytes, Align::ONE, kind, mutbl)?; - // Use cache for immutable strings. - let ptr = if mutbl.is_not() { - // Use dedup'd allocation function. - let salt = M::get_global_alloc_salt(self, None); - let id = tcx.allocate_bytes_dedup(str.as_bytes(), salt); + // Create length metadata for the string. + let meta = Scalar::from_target_usize(u64::try_from(bytes.len()).unwrap(), self); - // Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation. - M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))? - } else { - self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)? - }; - let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self); + // Get layout for Rust's str type. let layout = self.layout_of(self.tcx.types.str_).unwrap(); + + // Combine pointer and metadata into a wide pointer. interp_ok(self.ptr_with_meta_to_mplace( ptr.into(), MemPlaceMeta::Meta(meta), diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index 28574457389f..2fc767b37508 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -99,10 +99,7 @@ impl Expander { /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -pub fn arg_expand_all( - early_dcx: &EarlyDiagCtxt, - at_args: &[String], -) -> Result, ErrorGuaranteed> { +pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec { let mut expander = Expander::default(); let mut result = Ok(()); for arg in at_args { @@ -110,7 +107,10 @@ pub fn arg_expand_all( result = Err(early_dcx.early_err(format!("failed to load argument file: {err}"))); } } - result.map(|()| expander.finish()) + if let Err(guar) = result { + guar.raise_fatal(); + } + expander.finish() } /// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b7d64f75bf3d..2e01c385a667 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -42,9 +42,7 @@ use rustc_data_structures::profiling::{ }; use rustc_errors::emitter::stderr_destination; use rustc_errors::registry::Registry; -use rustc_errors::{ - ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, markdown, -}; +use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, get_codegen_backend}; use rustc_interface::{Linker, Queries, interface, passes}; @@ -271,14 +269,14 @@ impl<'a> RunCompiler<'a> { } /// Parse args and run the compiler. - pub fn run(self) -> interface::Result<()> { + pub fn run(self) { run_compiler( self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend, self.using_internal_features, - ) + ); } } @@ -290,7 +288,7 @@ fn run_compiler( Box Box + Send>, >, using_internal_features: Arc, -) -> interface::Result<()> { +) { let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // Throw away the first argument, the name of the binary. @@ -303,9 +301,11 @@ fn run_compiler( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = args::arg_expand_all(&default_early_dcx, at_args)?; + let args = args::arg_expand_all(&default_early_dcx, at_args); - let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) }; + let Some(matches) = handle_options(&default_early_dcx, &args) else { + return; + }; let sopts = config::build_session_options(&mut default_early_dcx, &matches); // fully initialize ice path static once unstable options are available as context @@ -313,7 +313,7 @@ fn run_compiler( if let Some(ref code) = matches.opt_str("explain") { handle_explain(&default_early_dcx, diagnostics_registry(), code, sopts.color); - return Ok(()); + return; } let (odir, ofile) = make_output(&matches); @@ -338,7 +338,7 @@ fn run_compiler( expanded_args: args, }; - let has_input = match make_input(&default_early_dcx, &matches.free)? { + let has_input = match make_input(&default_early_dcx, &matches.free) { Some(input) => { config.input = input; true // has input: normal compilation @@ -358,7 +358,7 @@ fn run_compiler( // printing some information without compiling, or exiting immediately // after parsing, etc. let early_exit = || { - if let Some(guar) = sess.dcx().has_errors() { Err(guar) } else { Ok(()) } + sess.dcx().abort_if_errors(); }; // This implements `-Whelp`. It should be handled very early, like @@ -389,22 +389,25 @@ fn run_compiler( } let linker = compiler.enter(|queries| { - let early_exit = || early_exit().map(|_| None); + let early_exit = || { + sess.dcx().abort_if_errors(); + None + }; // Parse the crate root source code (doesn't parse submodules yet) // Everything else is parsed during macro expansion. - queries.parse()?; + queries.parse(); // If pretty printing is requested: Figure out the representation, print it and exit if let Some(pp_mode) = sess.opts.pretty { if pp_mode.needs_ast_map() { - queries.global_ctxt()?.enter(|tcx| { + queries.global_ctxt().enter(|tcx| { tcx.ensure().early_lint_checks(()); pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx }); passes::write_dep_info(tcx); }); } else { - let krate = queries.parse()?; + let krate = queries.parse(); pretty::print(sess, pp_mode, pretty::PrintExtra::AfterParsing { krate: &*krate.borrow(), }); @@ -423,17 +426,17 @@ fn run_compiler( } // Make sure name resolution and macro expansion is run. - queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering()); + queries.global_ctxt().enter(|tcx| tcx.resolver_for_lowering()); if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { - queries.global_ctxt()?.enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir)); + queries.global_ctxt().enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir)); } if callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); } - queries.global_ctxt()?.enter(|tcx| { + queries.global_ctxt().enter(|tcx| { passes::write_dep_info(tcx); if sess.opts.output_types.contains_key(&OutputType::DepInfo) @@ -446,24 +449,21 @@ fn run_compiler( return early_exit(); } - tcx.analysis(())?; + tcx.ensure().analysis(()); if callbacks.after_analysis(compiler, tcx) == Compilation::Stop { return early_exit(); } - Ok(Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)?)) + Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)) }) - })?; + }); // Linking is done outside the `compiler.enter()` so that the // `GlobalCtxt` within `Queries` can be freed as early as possible. if let Some(linker) = linker { - let _timer = sess.timer("link"); - linker.link(sess, codegen_backend)? + linker.link(sess, codegen_backend); } - - Ok(()) }) } @@ -496,21 +496,17 @@ fn make_output(matches: &getopts::Matches) -> (Option, Option Result, ErrorGuaranteed> { +fn make_input(early_dcx: &EarlyDiagCtxt, free_matches: &[String]) -> Option { match free_matches { - [] => Ok(None), // no input: we will exit early, + [] => None, // no input: we will exit early, [ifile] if ifile == "-" => { // read from stdin as `Input::Str` let mut input = String::new(); if io::stdin().read_to_string(&mut input).is_err() { // Immediately stop compilation if there was an issue reading // the input (for example if the input stream is not UTF-8). - let reported = early_dcx - .early_err("couldn't read from stdin, as it did not contain valid UTF-8"); - return Err(reported); + early_dcx + .early_fatal("couldn't read from stdin, as it did not contain valid UTF-8"); } let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") { @@ -526,9 +522,9 @@ fn make_input( Err(_) => FileName::anon_source_code(&input), }; - Ok(Some(Input::Str { name, input })) + Some(Input::Str { name, input }) } - [ifile] => Ok(Some(Input::File(PathBuf::from(ifile)))), + [ifile] => Some(Input::File(PathBuf::from(ifile))), [ifile1, ifile2, ..] => early_dcx.early_fatal(format!( "multiple input filenames provided (first two filenames are `{}` and `{}`)", ifile1, ifile2 @@ -663,9 +659,7 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) { }; } }; - if compiler.codegen_backend.link(sess, codegen_results, &outputs).is_err() { - FatalError.raise(); - } + compiler.codegen_backend.link(sess, codegen_results, &outputs); } else { dcx.emit_fatal(RlinkNotAFile {}); } @@ -1608,7 +1602,8 @@ pub fn main() -> ! { let exit_code = catch_with_exit_code(|| { RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks) .set_using_internal_features(using_internal_features) - .run() + .run(); + Ok(()) }); if let Some(format) = callbacks.time_passes { diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 0733b8c0b98a..5df960be307b 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -222,8 +222,8 @@ impl<'tcx> PrintExtra<'tcx> { } pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { - if ppm.needs_analysis() && ex.tcx().analysis(()).is_err() { - FatalError.raise(); + if ppm.needs_analysis() { + ex.tcx().ensure().analysis(()); } let (src, src_name) = get_source(sess); diff --git a/compiler/rustc_error_codes/src/error_codes/E0751.md b/compiler/rustc_error_codes/src/error_codes/E0751.md index 8794f7868f30..825809b229aa 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0751.md +++ b/compiler/rustc_error_codes/src/error_codes/E0751.md @@ -9,4 +9,4 @@ impl !MyTrait for i32 { } // error! ``` Negative implementations are a promise that the trait will never be implemented -for the given types. Therefore, both cannot exists at the same time. +for the given types. Therefore, both cannot exist at the same time. diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index b4a651b10b10..b337e2794002 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -12,6 +12,7 @@ use rustc_span::SourceFile; use rustc_span::source_map::SourceMap; use crate::emitter::FileWithAnnotatedLines; +use crate::registry::Registry; use crate::snippet::Line; use crate::translation::{Translate, to_fluent_args}; use crate::{ @@ -45,7 +46,7 @@ impl Translate for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, mut diag: DiagInner) { + fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { let fluent_args = to_fluent_args(diag.args.iter()); let mut suggestions = diag.suggestions.unwrap_tag(); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index a386129e8145..1b6c6edcc614 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -27,6 +27,7 @@ use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStr use tracing::{debug, instrument, trace, warn}; use crate::diagnostic::DiagLocation; +use crate::registry::Registry; use crate::snippet::{ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, }; @@ -181,7 +182,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors. pub trait Emitter: Translate { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: DiagInner); + fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -189,7 +190,7 @@ pub trait Emitter: Translate { /// Emit a report about future breakage. /// Currently only supported for the JSON format. - fn emit_future_breakage_report(&mut self, _diags: Vec) {} + fn emit_future_breakage_report(&mut self, _diags: Vec, _registry: &Registry) {} /// Emit list of unused externs. /// Currently only supported for the JSON format. @@ -500,7 +501,7 @@ impl Emitter for HumanEmitter { self.sm.as_deref() } - fn emit_diagnostic(&mut self, mut diag: DiagInner) { + fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { let fluent_args = to_fluent_args(diag.args.iter()); let mut suggestions = diag.suggestions.unwrap_tag(); @@ -561,7 +562,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, mut diag: DiagInner) { + fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { if self.emit_fatal_diagnostic && diag.level == Level::Fatal { if let Some(fatal_note) = &self.fatal_note { diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index e3b6dcea8920..97df7f9265aa 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -44,7 +44,6 @@ mod tests; pub struct JsonEmitter { #[setters(skip)] dst: IntoDynSyncSend>, - registry: Option, #[setters(skip)] sm: Lrc, fluent_bundle: Option>, @@ -74,7 +73,6 @@ impl JsonEmitter { ) -> JsonEmitter { JsonEmitter { dst: IntoDynSyncSend(dst), - registry: None, sm, fluent_bundle: None, fallback_bundle, @@ -121,8 +119,8 @@ impl Translate for JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: crate::DiagInner) { - let data = Diagnostic::from_errors_diagnostic(diag, self); + fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) { + let data = Diagnostic::from_errors_diagnostic(diag, self, registry); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { panic!("failed to print diagnostics: {e:?}"); @@ -137,7 +135,7 @@ impl Emitter for JsonEmitter { } } - fn emit_future_breakage_report(&mut self, diags: Vec) { + fn emit_future_breakage_report(&mut self, diags: Vec, registry: &Registry) { let data: Vec> = diags .into_iter() .map(|mut diag| { @@ -151,7 +149,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - diag, self, + diag, self, registry, )), } }) @@ -291,7 +289,11 @@ struct UnusedExterns<'a> { impl Diagnostic { /// Converts from `rustc_errors::DiagInner` to `Diagnostic`. - fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { + fn from_errors_diagnostic( + diag: crate::DiagInner, + je: &JsonEmitter, + registry: &Registry, + ) -> Diagnostic { let args = to_fluent_args(diag.args.iter()); let sugg_to_diag = |sugg: &CodeSuggestion| { let translated_message = @@ -344,7 +346,7 @@ impl Diagnostic { let code = if let Some(code) = diag.code { Some(DiagnosticCode { code: code.to_string(), - explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), + explanation: registry.try_find_description(code).ok(), }) } else if let Some(IsLint { name, .. }) = &diag.is_lint { Some(DiagnosticCode { code: name.to_string(), explanation: None }) @@ -382,7 +384,7 @@ impl Diagnostic { } else { OutputTheme::Ascii }) - .emit_diagnostic(diag); + .emit_diagnostic(diag, registry); let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap(); let buf = String::from_utf8(buf).unwrap(); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 98200c367f98..6232c875ee81 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -55,7 +55,6 @@ pub use diagnostic_impls::{ }; pub use emitter::ColorConfig; use emitter::{DynEmitter, Emitter, is_case_difference, is_different}; -use registry::Registry; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; @@ -77,6 +76,8 @@ pub use snippet::Style; pub use termcolor::{Color, ColorSpec, WriteColor}; use tracing::debug; +use crate::registry::Registry; + pub mod annotate_snippet_emitter_writer; pub mod codes; mod diagnostic; @@ -483,6 +484,8 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { struct DiagCtxtInner { flags: DiagCtxtFlags, + registry: Registry, + /// The error guarantees from all emitted errors. The length gives the error count. err_guars: Vec, /// The error guarantee from all emitted lint errors. The length gives the @@ -619,9 +622,7 @@ impl Drop for DiagCtxtInner { // Important: it is sound to produce an `ErrorGuaranteed` when emitting // delayed bugs because they are guaranteed to be emitted here if // necessary. - if self.err_guars.is_empty() { - self.flush_delayed() - } + self.flush_delayed(); // Sanity check: did we use some of the expensive `trimmed_def_paths` functions // unexpectedly, that is, without producing diagnostics? If so, for debugging purposes, we @@ -664,6 +665,11 @@ impl DiagCtxt { self } + pub fn with_registry(mut self, registry: Registry) -> Self { + self.inner.get_mut().registry = registry; + self + } + pub fn new(emitter: Box) -> Self { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } @@ -694,7 +700,7 @@ impl DiagCtxt { struct FalseEmitter; impl Emitter for FalseEmitter { - fn emit_diagnostic(&mut self, _: DiagInner) { + fn emit_diagnostic(&mut self, _: DiagInner, _: &Registry) { unimplemented!("false emitter must only used during `wrap_emitter`") } @@ -759,6 +765,7 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); let DiagCtxtInner { flags: _, + registry: _, err_guars, lint_err_guars, delayed_bugs, @@ -964,7 +971,7 @@ impl<'a> DiagCtxtHandle<'a> { self.inner.borrow().has_errors_or_delayed_bugs() } - pub fn print_error_count(&self, registry: &Registry) { + pub fn print_error_count(&self) { let mut inner = self.inner.borrow_mut(); // Any stashed diagnostics should have been handled by @@ -1014,7 +1021,7 @@ impl<'a> DiagCtxtHandle<'a> { .emitted_diagnostic_codes .iter() .filter_map(|&code| { - if registry.try_find_description(code).is_ok() { + if inner.registry.try_find_description(code).is_ok() { Some(code.to_string()) } else { None @@ -1075,10 +1082,10 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn emit_future_breakage_report(&self) { - let mut inner = self.inner.borrow_mut(); + let inner = &mut *self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.future_breakage_diagnostics); if !diags.is_empty() { - inner.emitter.emit_future_breakage_report(diags); + inner.emitter.emit_future_breakage_report(diags, &inner.registry); } } @@ -1409,6 +1416,7 @@ impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, + registry: Registry::new(&[]), err_guars: Vec::new(), lint_err_guars: Vec::new(), delayed_bugs: Vec::new(), @@ -1582,7 +1590,7 @@ impl DiagCtxtInner { } self.has_printed = true; - self.emitter.emit_diagnostic(diagnostic); + self.emitter.emit_diagnostic(diagnostic, &self.registry); } if is_error { @@ -1695,7 +1703,13 @@ impl DiagCtxtInner { // eventually happened. assert!(self.stashed_diagnostics.is_empty()); + if !self.err_guars.is_empty() { + // If an error happened already. We shouldn't expose delayed bugs. + return; + } + if self.delayed_bugs.is_empty() { + // Nothing to do. return; } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e5500c8bba1c..6a6496f98270 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -990,7 +990,7 @@ pub fn parse_ast_fragment<'a>( } } AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), - AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt( + AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::Yes, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index abc7200699c6..bf26b5d25d2b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -505,6 +505,8 @@ declare_features! ( (incomplete, generic_const_items, "1.73.0", Some(113521)), /// Allows registering static items globally, possibly across crates, to iterate over at runtime. (unstable, global_registration, "1.80.0", Some(125119)), + /// Allows using guards in patterns. + (incomplete, guard_patterns, "CURRENT_RUSTC_VERSION", Some(129967)), /// Allows using `..=X` as a patterns in slices. (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. 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 ff449a858d67..2e227ead14a9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -279,7 +279,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { let mut err = self.dcx().create_err(err); if suggest_constraining_type_param( - tcx, generics, &mut err, &qself_str, &trait_ref, None, None, + tcx, + generics, + &mut err, + &qself_str, + &trait_ref, + Some(best_trait), + None, ) && !identically_named { // We suggested constraining a type parameter, but the associated item on it diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index f6c3e8ebbcbd..4ea171ab4a93 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -114,7 +114,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; -use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize}; use rustc_middle::bug; use rustc_session::config::CrateType; @@ -212,9 +211,9 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// The garbage collection will take care of it. /// /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph -pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuaranteed> { +pub(crate) fn prepare_session_directory(sess: &Session) { if sess.opts.incremental.is_none() { - return Ok(()); + return; } let _timer = sess.timer("incr_comp_prepare_session_directory"); @@ -224,7 +223,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuara // {incr-comp-dir}/{crate-name-and-disambiguator} let crate_dir = crate_path(sess); debug!("crate-dir: {}", crate_dir.display()); - create_dir(sess, &crate_dir, "crate")?; + create_dir(sess, &crate_dir, "crate"); // Hack: canonicalize the path *after creating the directory* // because, on windows, long paths can cause problems; @@ -233,7 +232,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuara let crate_dir = match try_canonicalize(&crate_dir) { Ok(v) => v, Err(err) => { - return Err(sess.dcx().emit_err(errors::CanonicalizePath { path: crate_dir, err })); + sess.dcx().emit_fatal(errors::CanonicalizePath { path: crate_dir, err }); } }; @@ -248,11 +247,11 @@ pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuara // Lock the new session directory. If this fails, return an // error without retrying - let (directory_lock, lock_file_path) = lock_directory(sess, &session_dir)?; + let (directory_lock, lock_file_path) = lock_directory(sess, &session_dir); // Now that we have the lock, we can actually create the session // directory - create_dir(sess, &session_dir, "session")?; + create_dir(sess, &session_dir, "session"); // Find a suitable source directory to copy from. Ignore those that we // have already tried before. @@ -266,7 +265,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuara ); sess.init_incr_comp_session(session_dir, directory_lock); - return Ok(()); + return; }; debug!("attempting to copy data from source: {}", source_directory.display()); @@ -280,7 +279,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuara } sess.init_incr_comp_session(session_dir, directory_lock); - return Ok(()); + return; } else { debug!("copying failed - trying next directory"); @@ -459,21 +458,17 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf { directory_path } -fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGuaranteed> { +fn create_dir(sess: &Session, path: &Path, dir_tag: &str) { match std_fs::create_dir_all(path) { Ok(()) => { debug!("{} directory created successfully", dir_tag); - Ok(()) } - Err(err) => Err(sess.dcx().emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })), + Err(err) => sess.dcx().emit_fatal(errors::CreateIncrCompDir { tag: dir_tag, path, err }), } } /// Allocate the lock-file and lock it. -fn lock_directory( - sess: &Session, - session_dir: &Path, -) -> Result<(flock::Lock, PathBuf), ErrorGuaranteed> { +fn lock_directory(sess: &Session, session_dir: &Path) -> (flock::Lock, PathBuf) { let lock_file_path = lock_file_path(session_dir); debug!("lock_directory() - lock_file: {}", lock_file_path.display()); @@ -484,15 +479,15 @@ fn lock_directory( true, ) { // the lock should be exclusive - Ok(lock) => Ok((lock, lock_file_path)), + Ok(lock) => (lock, lock_file_path), Err(lock_err) => { let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err); - Err(sess.dcx().emit_err(errors::CreateLock { + sess.dcx().emit_fatal(errors::CreateLock { lock_err, session_dir, is_unsupported_lock, is_cargo: rustc_session::utils::was_invoked_from_cargo(), - })) + }); } } } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index c74804cc7983..48df84f3d099 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -11,7 +11,6 @@ use rustc_serialize::Decodable; use rustc_serialize::opaque::MemDecoder; use rustc_session::Session; use rustc_session::config::IncrementalStateAssertion; -use rustc_span::ErrorGuaranteed; use tracing::{debug, warn}; use super::data::*; @@ -182,7 +181,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(Arc, WorkPr /// If we are not in incremental compilation mode, returns `None`. /// Otherwise, tries to load the query result cache from disk, /// creating an empty cache if it could not be loaded. -pub fn load_query_result_cache(sess: &Session) -> Option> { +pub fn load_query_result_cache(sess: &Session) -> Option { if sess.opts.incremental.is_none() { return None; } @@ -194,19 +193,19 @@ pub fn load_query_result_cache(sess: &Session) -> Option> { LoadResult::Ok { data: (bytes, start_pos) } => { let cache = OnDiskCache::new(sess, bytes, start_pos).unwrap_or_else(|()| { sess.dcx().emit_warn(errors::CorruptFile { path: &path }); - OnDiskCache::new_empty(sess.source_map()) + OnDiskCache::new_empty() }); Some(cache) } - _ => Some(OnDiskCache::new_empty(sess.source_map())), + _ => Some(OnDiskCache::new_empty()), } } /// Setups the dependency graph by loading an existing graph from disk and set up streaming of a /// new graph to an incremental session directory. -pub fn setup_dep_graph(sess: &Session) -> Result { +pub fn setup_dep_graph(sess: &Session) -> DepGraph { // `load_dep_graph` can only be called after `prepare_session_directory`. - prepare_session_directory(sess)?; + prepare_session_directory(sess); let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess)); @@ -222,10 +221,9 @@ pub fn setup_dep_graph(sess: &Session) -> Result { }); } - Ok(res - .and_then(|result| { - let (prev_graph, prev_work_products) = result.open(sess); - build_dep_graph(sess, prev_graph, prev_work_products) - }) - .unwrap_or_else(DepGraph::new_disabled)) + res.and_then(|result| { + let (prev_graph, prev_work_products) = result.open(sess); + build_dep_graph(sess, prev_graph, prev_work_products) + }) + .unwrap_or_else(DepGraph::new_disabled) } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3920d3077d36..07ae24ee6d32 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -5,9 +5,9 @@ use std::sync::Arc; use rustc_ast::{LitKind, MetaItemKind, token}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::jobserver; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::{defer, jobserver}; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; @@ -441,7 +441,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se temps_dir, }, bundle, - config.registry.clone(), + config.registry, locale_resources, config.lint_caps, target, @@ -492,32 +492,34 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se // There are two paths out of `f`. // - Normal exit. - // - Panic, e.g. triggered by `abort_if_errors`. + // - Panic, e.g. triggered by `abort_if_errors` or a fatal error. // // We must run `finish_diagnostics` in both cases. - let res = { - // If `f` panics, `finish_diagnostics` will run during - // unwinding because of the `defer`. - let sess_abort_guard = defer(|| { - compiler.sess.finish_diagnostics(&config.registry); - }); + let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&compiler))); - let res = f(&compiler); + compiler.sess.finish_diagnostics(); - // If `f` doesn't panic, `finish_diagnostics` will run - // normally when `sess_abort_guard` is dropped. - drop(sess_abort_guard); - - // If error diagnostics have been emitted, we can't return an - // error directly, because the return type of this function - // is `R`, not `Result`. But we need to communicate the - // errors' existence to the caller, otherwise the caller might - // mistakenly think that no errors occurred and return a zero - // exit code. So we abort (panic) instead, similar to if `f` - // had panicked. + // If error diagnostics have been emitted, we can't return an + // error directly, because the return type of this function + // is `R`, not `Result`. But we need to communicate the + // errors' existence to the caller, otherwise the caller might + // mistakenly think that no errors occurred and return a zero + // exit code. So we abort (panic) instead, similar to if `f` + // had panicked. + if res.is_ok() { compiler.sess.dcx().abort_if_errors(); + } - res + // Also make sure to flush delayed bugs as if we panicked, the + // bugs would be flushed by the Drop impl of DiagCtxt while + // unwinding, which would result in an abort with + // "panic in a destructor during cleanup". + compiler.sess.dcx().flush_delayed(); + + let res = match res { + Ok(res) => res, + // Resume unwinding if a panic happened. + Err(err) => std::panic::resume_unwind(err), }; let prof = compiler.sess.prof.clone(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f53c7b5cc2d8..62f353330156 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -33,15 +33,15 @@ use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_ use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{Symbol, sym}; -use rustc_span::{FileName, SourceFileHash, SourceFileHashAlgorithm}; +use rustc_span::{ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm}; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use tracing::{info, instrument}; -use crate::interface::{Compiler, Result}; +use crate::interface::Compiler; use crate::{errors, proc_macro_decls, util}; -pub(crate) fn parse<'a>(sess: &'a Session) -> Result { +pub(crate) fn parse<'a>(sess: &'a Session) -> ast::Crate { let krate = sess .time("parse_crate", || { let mut parser = unwrap_or_emit_fatal(match &sess.io.input { @@ -52,13 +52,16 @@ pub(crate) fn parse<'a>(sess: &'a Session) -> Result { }); parser.parse_crate_mod() }) - .map_err(|parse_error| parse_error.emit())?; + .unwrap_or_else(|parse_error| { + let guar: ErrorGuaranteed = parse_error.emit(); + guar.raise_fatal(); + }); if sess.opts.unstable_opts.input_stats { input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1"); } - Ok(krate) + krate } fn pre_expansion_lint<'a>( @@ -712,7 +715,7 @@ pub(crate) fn create_global_ctxt<'tcx>( gcx_cell: &'tcx OnceLock>, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, -) -> Result<&'tcx GlobalCtxt<'tcx>> { +) -> &'tcx GlobalCtxt<'tcx> { let sess = &compiler.sess; rustc_builtin_macros::cmdline_attrs::inject( @@ -733,7 +736,7 @@ pub(crate) fn create_global_ctxt<'tcx>( sess.cfg_version, ); let outputs = util::build_output_filenames(&pre_configured_attrs, sess); - let dep_graph = setup_dep_graph(sess)?; + let dep_graph = setup_dep_graph(sess); let cstore = FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _); @@ -796,7 +799,7 @@ pub(crate) fn create_global_ctxt<'tcx>( feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); }); - Ok(qcx) + qcx }) } @@ -906,7 +909,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. -fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { +fn analysis(tcx: TyCtxt<'_>, (): ()) { run_required_analyses(tcx); let sess = tcx.sess; @@ -920,7 +923,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // But we exclude lint errors from this, because lint errors are typically // less serious and we're more likely to want to continue (#87337). if let Some(guar) = sess.dcx().has_errors_excluding_lint_errors() { - return Err(guar); + guar.raise_fatal(); } sess.time("misc_checking_3", || { @@ -1048,8 +1051,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }) } } - - Ok(()) } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -1091,12 +1092,12 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, -) -> Result> { +) -> Box { // Don't do code generation if there were any errors. Likewise if // there were any delayed bugs, because codegen will likely cause // more ICEs, obscuring the original problem. if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() { - return Err(guar); + guar.raise_fatal(); } // Hook for UI tests. @@ -1124,7 +1125,7 @@ pub(crate) fn start_codegen<'tcx>( } } - Ok(codegen) + codegen } fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index cd3a2fb70490..7e3a1332630d 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -16,7 +16,7 @@ use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; use crate::errors::FailedWritingFile; -use crate::interface::{Compiler, Result}; +use crate::interface::Compiler; use crate::passes; /// Represent the result of a query. @@ -27,19 +27,17 @@ use crate::passes; /// [`compute`]: Self::compute pub struct Query { /// `None` means no value has been computed yet. - result: RefCell>>>, + result: RefCell>>, } impl Query { - fn compute Result>(&self, f: F) -> Result> { - RefMut::filter_map( + fn compute T>(&self, f: F) -> QueryResult<'_, T> { + QueryResult(RefMut::map( self.result.borrow_mut(), - |r: &mut Option>>| -> Option<&mut Steal> { - r.get_or_insert_with(|| f().map(Steal::new)).as_mut().ok() + |r: &mut Option>| -> &mut Steal { + r.get_or_insert_with(|| Steal::new(f())) }, - ) - .map_err(|r| *r.as_ref().unwrap().as_ref().map(|_| ()).unwrap_err()) - .map(QueryResult) + )) } } @@ -95,13 +93,13 @@ impl<'tcx> Queries<'tcx> { } } - pub fn parse(&self) -> Result> { + pub fn parse(&self) -> QueryResult<'_, ast::Crate> { self.parse.compute(|| passes::parse(&self.compiler.sess)) } - pub fn global_ctxt(&'tcx self) -> Result>> { + pub fn global_ctxt(&'tcx self) -> QueryResult<'tcx, &'tcx GlobalCtxt<'tcx>> { self.gcx.compute(|| { - let krate = self.parse()?.steal(); + let krate = self.parse().steal(); passes::create_global_ctxt( self.compiler, @@ -126,8 +124,8 @@ impl Linker { pub fn codegen_and_build_linker( tcx: TyCtxt<'_>, codegen_backend: &dyn CodegenBackend, - ) -> Result { - let ongoing_codegen = passes::start_codegen(codegen_backend, tcx)?; + ) -> Linker { + let ongoing_codegen = passes::start_codegen(codegen_backend, tcx); // This must run after monomorphization so that all generic types // have been instantiated. @@ -141,7 +139,7 @@ impl Linker { tcx.sess.code_stats.print_vtable_sizes(crate_name); } - Ok(Linker { + Linker { dep_graph: tcx.dep_graph.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), crate_hash: if tcx.needs_crate_hash() { @@ -150,16 +148,17 @@ impl Linker { None }, ongoing_codegen, - }) + } } - pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { - let (codegen_results, work_products) = - codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames); + pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) { + let (codegen_results, work_products) = sess.time("finish_ongoing_codegen", || { + codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames) + }); - if let Some(guar) = sess.dcx().has_errors() { - return Err(guar); - } + sess.dcx().abort_if_errors(); + + let _timer = sess.timer("link"); sess.time("serialize_work_products", || { rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products) @@ -178,7 +177,7 @@ impl Linker { .keys() .any(|&i| i == OutputType::Exe || i == OutputType::Metadata) { - return Ok(()); + return; } if sess.opts.unstable_opts.no_link { @@ -189,10 +188,10 @@ impl Linker { &codegen_results, &*self.output_filenames, ) - .map_err(|error| { + .unwrap_or_else(|error| { sess.dcx().emit_fatal(FailedWritingFile { path: &rlink_file, error }) - })?; - return Ok(()); + }); + return; } let _timer = sess.prof.verbose_generic_activity("link_crate"); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 49e6b763590b..422629cd11d0 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -359,7 +359,6 @@ lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stab lint_improper_ctypes_array_help = consider passing a pointer to the array lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe -lint_improper_ctypes_box = box cannot be represented as a single pointer lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead @@ -377,7 +376,9 @@ lint_improper_ctypes_enum_repr_help = lint_improper_ctypes_enum_repr_reason = enum has no representation hint lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead +lint_improper_ctypes_fnptr_indirect_reason = the function pointer to `{$ty}` is FFI-unsafe due to `{$inner_ty}` lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention + lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants @@ -388,7 +389,11 @@ lint_improper_ctypes_opaque = opaque types have no C equivalent lint_improper_ctypes_pat_help = consider using the base type instead lint_improper_ctypes_pat_reason = pattern types have no C equivalent -lint_improper_ctypes_slice_help = consider using a raw pointer instead + +lint_improper_ctypes_sized_ptr_to_unsafe_type = + this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout + +lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead lint_improper_ctypes_slice_reason = slices have no C equivalent lint_improper_ctypes_str_help = consider using `*const u8` and a length instead @@ -414,6 +419,10 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re lint_improper_ctypes_union_layout_reason = this union has unspecified layout lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive +lint_improper_ctypes_unsized_box = this box for an unsized type contains metadata, which makes it incompatible with a C pointer +lint_improper_ctypes_unsized_ptr = this pointer to an unsized type contains metadata, which makes it incompatible with a C pointer +lint_improper_ctypes_unsized_ref = this reference to an unsized type contains metadata, which makes it incompatible with a C pointer + lint_incomplete_include = include macro expected single expression in source diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 4f3184f1d7cf..a68a2a7f9838 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -245,6 +245,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_lifetime(&mut self, lt: &'a ast::Lifetime, _: ast_visit::LifetimeCtxt) { self.check_id(lt.id); + ast_visit::walk_lifetime(self, lt); } fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) { @@ -259,6 +260,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_attribute(&mut self, attr: &'a ast::Attribute) { lint_callback!(self, check_attribute, attr); + ast_visit::walk_attribute(self, attr); } fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) { diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index 025fd4520406..28368e1ab462 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -9,6 +9,7 @@ use crate::lints::{ use crate::{EarlyContext, EarlyLintPass, LintContext}; declare_lint! { + #[allow(text_direction_codepoint_in_literal)] /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the /// visual representation of text on screen in a way that does not correspond to their on /// memory representation. diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20822f23bf15..9fa263799ebf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1851,13 +1851,44 @@ pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> { pub right: Span, } +pub(crate) struct ImproperCTypesLayer<'a> { + pub ty: Ty<'a>, + pub inner_ty: Option>, + pub note: DiagMessage, + pub span_note: Option, + pub help: Option, +} + +impl<'a> Subdiagnostic for ImproperCTypesLayer<'a> { + fn add_to_diag_with>( + self, + diag: &mut Diag<'_, G>, + f: &F, + ) { + diag.arg("ty", self.ty); + if let Some(ty) = self.inner_ty { + diag.arg("inner_ty", ty); + } + + if let Some(help) = self.help { + let msg = f(diag, help.into()); + diag.help(msg); + } + + let msg = f(diag, self.note.into()); + diag.note(msg); + if let Some(note) = self.span_note { + let msg = f(diag, fluent::lint_note.into()); + diag.span_note(note, msg); + }; + } +} + pub(crate) struct ImproperCTypes<'a> { pub ty: Ty<'a>, pub desc: &'a str, pub label: Span, - pub help: Option, - pub note: DiagMessage, - pub span_note: Option, + pub reasons: Vec>, } // Used because of the complexity of Option, DiagMessage, and Option @@ -1867,12 +1898,8 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { diag.arg("ty", self.ty); diag.arg("desc", self.desc); diag.span_label(self.label, fluent::lint_label); - if let Some(help) = self.help { - diag.help(help); - } - diag.note(self.note); - if let Some(note) = self.span_note { - diag.span_note(note, fluent::lint_note); + for reason in self.reasons.into_iter() { + diag.subdiagnostic(reason); } } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 33650be056dd..90d44371ab5a 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -22,10 +22,10 @@ mod improper_ctypes; use crate::lints::{ AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion, AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad, - AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, - InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons, - UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, - VariantSizeDifferencesDiag, + AtomicOrderingStore, ImproperCTypes, ImproperCTypesLayer, InvalidAtomicOrderingDiag, + InvalidNanComparisons, InvalidNanComparisonsSuggestion, + UnpredictableFunctionPointerComparisons, UnpredictableFunctionPointerComparisonsSuggestion, + UnusedComparisons, VariantSizeDifferencesDiag, }; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -727,7 +727,109 @@ struct CTypesVisitorState<'tcx> { enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), - FfiUnsafe { ty: Ty<'tcx>, reason: DiagMessage, help: Option }, + FfiUnsafe { + ty: Ty<'tcx>, + reason: DiagMessage, + help: Option, + }, + FfiUnsafeWrapper { + ty: Ty<'tcx>, + reason: DiagMessage, + help: Option, + wrapped: Box>, + }, +} + +/// Determine if a type is sized or not, and wether it affects references/pointers/boxes to it +#[derive(Clone, Copy)] +enum TypeSizedness { + /// type of definite size (pointers are C-compatible) + Definite, + /// unsized type because it includes an opaque/foreign type (pointers are C-compatible) + UnsizedWithExternType, + /// unsized type for other reasons (slice, string, dyn Trait, closure, ...) (pointers are not C-compatible) + UnsizedWithMetadata, +} + +/// Is this type unsized because it contains (or is) a foreign type? +/// (Returns Err if the type happens to be sized after all) +fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> TypeSizedness { + let tcx = cx.tcx; + + if ty.is_sized(tcx, cx.typing_env()) { + TypeSizedness::Definite + } else { + match ty.kind() { + ty::Slice(_) => TypeSizedness::UnsizedWithMetadata, + ty::Str => TypeSizedness::UnsizedWithMetadata, + ty::Dynamic(..) => TypeSizedness::UnsizedWithMetadata, + ty::Foreign(..) => TypeSizedness::UnsizedWithExternType, + // While opaque types are checked for earlier, if a projection in a struct field + // normalizes to an opaque type, then it will reach this branch. + ty::Alias(ty::Opaque, ..) => todo!("We... don't know enough about this type yet?"), + ty::Adt(def, args) => { + // for now assume: boxes and phantoms don't mess with this + match def.adt_kind() { + AdtKind::Union | AdtKind::Enum => { + bug!("unions and enums are necessarily sized") + } + AdtKind::Struct => { + if let Some(sym::cstring_type | sym::cstr_type) = + tcx.get_diagnostic_name(def.did()) + { + return TypeSizedness::UnsizedWithMetadata; + } + // FIXME: how do we deal with non-exhaustive unsized structs/unions? + + if def.non_enum_variant().fields.is_empty() { + bug!("an empty struct is necessarily sized"); + } + + let variant = def.non_enum_variant(); + + // only the last field may be unsized + let n_fields = variant.fields.len(); + let last_field = &variant.fields[(n_fields - 1).into()]; + let field_ty = last_field.ty(cx.tcx, args); + let field_ty = cx + .tcx + .try_normalize_erasing_regions(cx.typing_env(), field_ty) + .unwrap_or(field_ty); + match get_type_sizedness(cx, field_ty) { + s @ (TypeSizedness::UnsizedWithMetadata + | TypeSizedness::UnsizedWithExternType) => s, + TypeSizedness::Definite => { + bug!("failed to find the reason why struct `{:?}` is unsized", ty) + } + } + } + } + } + ty::Tuple(tuple) => { + // only the last field may be unsized + let n_fields = tuple.len(); + let field_ty: Ty<'tcx> = tuple[n_fields - 1]; + //let field_ty = last_field.ty(cx.tcx, args); + let field_ty = cx + .tcx + .try_normalize_erasing_regions(cx.typing_env(), field_ty) + .unwrap_or(field_ty); + match get_type_sizedness(cx, field_ty) { + s @ (TypeSizedness::UnsizedWithMetadata + | TypeSizedness::UnsizedWithExternType) => s, + TypeSizedness::Definite => { + bug!("failed to find the reason why tuple `{:?}` is unsized", ty) + } + } + } + ty => { + bug!( + "we shouldn't be trying to determine if this is unsized for a reason or another: `{:?}`", + ty + ) + } + } + } } pub(crate) fn nonnull_optimization_guaranteed<'tcx>( @@ -764,7 +866,7 @@ fn ty_is_known_nonnull<'tcx>( match ty.kind() { ty::FnPtr(..) => true, ty::Ref(..) => true, - ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true, + ty::Adt(def, _) if def.is_box() => true, ty::Adt(def, args) if def.repr().transparent() && !def.is_union() => { let marked_non_null = nonnull_optimization_guaranteed(tcx, *def); @@ -933,12 +1035,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Check if the type is array and emit an unsafe type lint. fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { if let ty::Array(..) = ty.kind() { - self.emit_ffi_unsafe_type_lint( + self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer { ty, - sp, - fluent::lint_improper_ctypes_array_reason, - Some(fluent::lint_improper_ctypes_array_help), - ); + note: fluent::lint_improper_ctypes_array_reason, + help: Some(fluent::lint_improper_ctypes_array_help), + inner_ty: None, + span_note: None, + }]); true } else { false @@ -995,9 +1098,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { all_phantom &= match self.check_field_type_for_ffi(acc, field, args) { FfiSafe => false, // `()` fields are FFI-safe! - FfiUnsafe { ty, .. } if ty.is_unit() => false, + FfiUnsafe { ty, .. } | FfiUnsafeWrapper { ty, .. } if ty.is_unit() => false, FfiPhantom(..) => true, - r @ FfiUnsafe { .. } => return r, + r @ (FfiUnsafe { .. } | FfiUnsafeWrapper { .. }) => return r, } } @@ -1031,16 +1134,47 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match *ty.kind() { ty::Adt(def, args) => { - if let Some(boxed) = ty.boxed_ty() - && matches!(self.mode, CItemKind::Definition) - { - if boxed.is_sized(tcx, self.cx.typing_env()) { - return FfiSafe; + if let Some(inner_ty) = ty.boxed_ty() { + if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite = + get_type_sizedness(self.cx, inner_ty) + { + // discussion on declaration vs definition: + // see the `ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _)` arm + // of this `match *ty.kind()` block + if matches!(self.mode, CItemKind::Definition) { + return FfiSafe; + } else { + let inner_res = self.check_type_for_ffi(acc, inner_ty); + return match inner_res { + FfiUnsafe { .. } | FfiUnsafeWrapper { .. } => FfiUnsafeWrapper { + ty, + reason: fluent::lint_improper_ctypes_sized_ptr_to_unsafe_type, + wrapped: Box::new(inner_res), + help: None, + }, + _ => inner_res, + }; + } } else { + let help = match inner_ty.kind() { + ty::Str => Some(fluent::lint_improper_ctypes_str_help), + ty::Slice(_) => Some(fluent::lint_improper_ctypes_slice_help), + ty::Adt(def, _) + if matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union) + && matches!( + tcx.get_diagnostic_name(def.did()), + Some(sym::cstring_type | sym::cstr_type) + ) + && !acc.base_ty.is_mutable_ptr() => + { + Some(fluent::lint_improper_ctypes_cstr_help) + } + _ => None, + }; return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_box, - help: None, + reason: fluent::lint_improper_ctypes_unsized_box, + help, }; } } @@ -1196,15 +1330,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: Some(fluent::lint_improper_ctypes_tuple_help), }, - ty::RawPtr(ty, _) | ty::Ref(_, ty, _) - if { - matches!(self.mode, CItemKind::Definition) - && ty.is_sized(self.cx.tcx, self.cx.typing_env()) - } => - { - FfiSafe - } - ty::RawPtr(ty, _) if match ty.kind() { ty::Tuple(tuple) => tuple.is_empty(), @@ -1214,7 +1339,70 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(acc, ty), + ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _) => { + if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite = + get_type_sizedness(self.cx, inner_ty) + { + // there's a nuance on what this lint should do for + // function definitions (`extern "C" fn fn_name(...) {...}`) + // versus declarations (`unsafe extern "C" {fn fn_name(...);}`). + // This is touched upon in https://github.com/rust-lang/rust/issues/66220 + // and https://github.com/rust-lang/rust/pull/72700 + // + // The big question is: what does "ABI safety" mean? if you have something translated to a C pointer + // (which has a stable layout) but points to FFI-unsafe type, is it safe? + // On one hand, the function's ABI will match that of a similar C-declared function API, + // on the other, dereferencing the pointer on the other side of the FFI boundary will be painful. + // In this code, the opinion on is split between function declarations and function definitions, + // with the idea that at least one side of the FFI boundary needs to treat the pointee as an opaque type. + // For declarations, we see this as unsafe, but for definitions, we see this as safe. + // + // For extern function declarations, the actual definition of the function is written somewhere else, + // meaning the declaration is free to express this opaqueness with an extern type (opaque caller-side) or a std::ffi::c_void (opaque callee-side) + // For extern function definitions, however, in the case where the type is opaque caller-side, it is not opaque callee-side, + // and having the full type information is necessary to compile the function. + if matches!(self.mode, CItemKind::Definition) { + return FfiSafe; + } else if matches!(ty.kind(), ty::RawPtr(..)) + && matches!(inner_ty.kind(), ty::Tuple(tuple) if tuple.is_empty()) + { + FfiSafe + } else { + let inner_res = self.check_type_for_ffi(acc, inner_ty); + return match inner_res { + FfiSafe => inner_res, + _ => FfiUnsafeWrapper { + ty, + reason: fluent::lint_improper_ctypes_sized_ptr_to_unsafe_type, + wrapped: Box::new(inner_res), + help: None, + }, + }; + } + } else { + let help = match inner_ty.kind() { + ty::Str => Some(fluent::lint_improper_ctypes_str_help), + ty::Slice(_) => Some(fluent::lint_improper_ctypes_slice_help), + ty::Adt(def, _) + if matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union) + && matches!( + tcx.get_diagnostic_name(def.did()), + Some(sym::cstring_type | sym::cstr_type) + ) + && !acc.base_ty.is_mutable_ptr() => + { + Some(fluent::lint_improper_ctypes_cstr_help) + } + _ => None, + }; + let reason = match ty.kind() { + ty::RawPtr(..) => fluent::lint_improper_ctypes_unsized_ptr, + ty::Ref(..) => fluent::lint_improper_ctypes_unsized_ref, + _ => unreachable!(), + }; + FfiUnsafe { ty, reason, help } + } + } ty::Array(inner_ty, _) => self.check_type_for_ffi(acc, inner_ty), @@ -1232,7 +1420,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { for arg in sig.inputs() { match self.check_type_for_ffi(acc, *arg) { FfiSafe => {} - r => return r, + r => { + return FfiUnsafeWrapper { + ty, + reason: fluent::lint_improper_ctypes_fnptr_indirect_reason, + help: None, + wrapped: Box::new(r), + }; + } } } @@ -1241,7 +1436,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } - self.check_type_for_ffi(acc, ret_ty) + match self.check_type_for_ffi(acc, ret_ty) { + r @ (FfiSafe | FfiPhantom(_)) => r, + r => FfiUnsafeWrapper { + ty: ty.clone(), + reason: fluent::lint_improper_ctypes_fnptr_indirect_reason, + help: None, + wrapped: Box::new(r), + }, + } } ty::Foreign(..) => FfiSafe, @@ -1278,8 +1481,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { &mut self, ty: Ty<'tcx>, sp: Span, - note: DiagMessage, - help: Option, + mut reasons: Vec>, ) { let lint = match self.mode { CItemKind::Declaration => IMPROPER_CTYPES, @@ -1289,21 +1491,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { CItemKind::Declaration => "block", CItemKind::Definition => "fn", }; - let span_note = if let ty::Adt(def, _) = ty.kind() - && let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) - { - Some(sp) - } else { - None - }; - self.cx.emit_span_lint(lint, sp, ImproperCTypes { - ty, - desc, - label: sp, - help, - note, - span_note, - }); + for reason in reasons.iter_mut() { + reason.span_note = if let ty::Adt(def, _) = reason.ty.kind() + && let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) + { + Some(sp) + } else { + None + }; + } + + self.cx.emit_span_lint(lint, sp, ImproperCTypes { ty, desc, label: sp, reasons }); } fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { @@ -1332,7 +1530,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { .visit_with(&mut ProhibitOpaqueTypes) .break_value() { - self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None); + self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer { + ty, + note: fluent::lint_improper_ctypes_opaque, + span_note: Some(sp), + help: None, + inner_ty: None, + }]); true } else { false @@ -1371,15 +1575,71 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match self.check_type_for_ffi(&mut acc, ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { - self.emit_ffi_unsafe_type_lint( + self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer { ty, - sp, - fluent::lint_improper_ctypes_only_phantomdata, - None, - ); + note: fluent::lint_improper_ctypes_only_phantomdata, + span_note: None, // filled later + help: None, + inner_ty: None, + }]); } FfiResult::FfiUnsafe { ty, reason, help } => { - self.emit_ffi_unsafe_type_lint(ty, sp, reason, help); + self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer { + ty, + help, + note: reason, + span_note: None, // filled later + inner_ty: None, + }]); + } + ffir @ FfiResult::FfiUnsafeWrapper { .. } => { + let mut ffiresult_recursor = ControlFlow::Continue(&ffir); + let mut cimproper_layers: Vec> = vec![]; + + // this whole while block converts the arbitrarily-deep + // FfiResult stack to an ImproperCTypesLayer Vec + while let ControlFlow::Continue(ref ffir_rec) = ffiresult_recursor { + match ffir_rec { + FfiResult::FfiPhantom(ty) => { + if let Some(layer) = cimproper_layers.last_mut() { + layer.inner_ty = Some(ty.clone()); + } + cimproper_layers.push(ImproperCTypesLayer { + ty: ty.clone(), + inner_ty: None, + help: None, + note: fluent::lint_improper_ctypes_only_phantomdata, + span_note: None, // filled later + }); + ffiresult_recursor = ControlFlow::Break(()); + } + FfiResult::FfiUnsafe { ty, reason, help } + | FfiResult::FfiUnsafeWrapper { ty, reason, help, .. } => { + if let Some(layer) = cimproper_layers.last_mut() { + layer.inner_ty = Some(ty.clone()); + } + cimproper_layers.push(ImproperCTypesLayer { + ty: ty.clone(), + inner_ty: None, + help: help.clone(), + note: reason.clone(), + span_note: None, // filled later + }); + + if let FfiResult::FfiUnsafeWrapper { wrapped, .. } = ffir_rec { + ffiresult_recursor = ControlFlow::Continue(wrapped.as_ref()); + } else { + ffiresult_recursor = ControlFlow::Break(()); + } + } + FfiResult::FfiSafe => { + bug!("malformed FfiResult stack: it should be unsafe all the way down") + } + }; + } + // should always have at least one type + let last_ty = cimproper_layers.last().unwrap().ty.clone(); + self.emit_ffi_unsafe_type_lint(last_ty, sp, cimproper_layers); } } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b775cd374091..9cad5d98562b 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1235,7 +1235,7 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); }, // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. - Ident(.., Some(p)) | Box(p) | Deref(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space), + Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space), // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d2b7ae620e2b..54e927df3c42 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3929,6 +3929,7 @@ declare_lint! { } declare_lint! { + #[allow(text_direction_codepoint_in_literal)] /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that /// change the visual representation of text on screen in a way that does not correspond to /// their on memory representation. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d04876d0bef0..a3976c3dda11 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -276,7 +276,7 @@ rustc_queries! { } /// The root query triggering all analysis passes like typeck or borrowck. - query analysis(key: ()) -> Result<(), ErrorGuaranteed> { + query analysis(key: ()) { eval_always desc { "running analysis passes on this crate" } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 3849cb72668f..119a99e1bf7a 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -23,7 +23,7 @@ use rustc_session::Session; use rustc_span::hygiene::{ ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, }; -use rustc_span::source_map::{SourceMap, Spanned}; +use rustc_span::source_map::Spanned; use rustc_span::{ BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span, SpanDecoder, SpanEncoder, StableSourceFileId, Symbol, @@ -49,7 +49,7 @@ const SYMBOL_PREINTERNED: u8 = 2; /// previous compilation session. This data will eventually include the results /// of a few selected queries (like `typeck` and `mir_optimized`) and /// any side effects that have been emitted during a query. -pub struct OnDiskCache<'sess> { +pub struct OnDiskCache { // The complete cache data in serialized form. serialized_data: RwLock>, @@ -57,7 +57,6 @@ pub struct OnDiskCache<'sess> { // session. current_side_effects: Lock>, - source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap, // Caches that are populated lazily during decoding. @@ -151,12 +150,12 @@ impl EncodedSourceFileId { } } -impl<'sess> OnDiskCache<'sess> { +impl OnDiskCache { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. /// /// The serialized cache has some basic integrity checks, if those checks indicate that the /// on-disk data is corrupt, an error is returned. - pub fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Result { + pub fn new(sess: &Session, data: Mmap, start_pos: usize) -> Result { assert!(sess.opts.incremental.is_some()); let mut decoder = MemDecoder::new(&data, start_pos)?; @@ -175,7 +174,6 @@ impl<'sess> OnDiskCache<'sess> { serialized_data: RwLock::new(Some(data)), file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), - source_map: sess.source_map(), current_side_effects: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), prev_side_effects_index: footer.side_effects_index.into_iter().collect(), @@ -187,12 +185,11 @@ impl<'sess> OnDiskCache<'sess> { }) } - pub fn new_empty(source_map: &'sess SourceMap) -> Self { + pub fn new_empty() -> Self { Self { serialized_data: RwLock::new(None), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), - source_map, current_side_effects: Default::default(), query_result_index: Default::default(), prev_side_effects_index: Default::default(), @@ -423,7 +420,7 @@ impl<'sess> OnDiskCache<'sess> { } fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>( - &'sess self, + &self, tcx: TyCtxt<'tcx>, pos: AbsoluteBytePos, f: F, @@ -436,7 +433,6 @@ impl<'sess> OnDiskCache<'sess> { tcx, opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()) .unwrap(), - source_map: self.source_map, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), @@ -457,7 +453,6 @@ impl<'sess> OnDiskCache<'sess> { pub struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, opaque: MemDecoder<'a>, - source_map: &'a SourceMap, file_index_to_file: &'a Lock>>, file_index_to_stable_id: &'a FxHashMap, alloc_decoding_session: AllocDecodingSession<'a>, @@ -470,8 +465,7 @@ pub struct CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { #[inline] fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc { - let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, source_map, .. } = - *self; + let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, .. } = *self; Lrc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| { let source_file_id = &file_index_to_stable_id[&index]; @@ -490,7 +484,8 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { self.tcx.import_source_files(source_file_cnum); } - source_map + tcx.sess + .source_map() .source_file_by_stable_id(source_file_id.stable_source_file_id) .expect("failed to lookup `SourceFile` in new context") })) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 20ba1b27c0ed..c8675660e0fd 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -66,7 +66,7 @@ pub struct QuerySystem<'tcx> { /// Do not access this directly. It is only meant to be used by /// `DepGraph::try_mark_green()` and the query infrastructure. /// This is `None` if we are not incremental compilation mode - pub on_disk_cache: Option>, + pub on_disk_cache: Option, pub fns: QuerySystemFns<'tcx>, diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index fd807882e0f7..604f1da26c64 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,11 +1,12 @@ //! Diagnostics related methods for `Ty`. -use std::borrow::Cow; use std::fmt::Write; use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display}; +use rustc_errors::{ + Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize, +}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind}; @@ -161,7 +162,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>( true } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] enum SuggestChangingConstraintsMessage<'a> { RestrictBoundFurther, RestrictType { ty: &'a str }, @@ -172,7 +173,7 @@ enum SuggestChangingConstraintsMessage<'a> { fn suggest_changing_unsized_bound( generics: &hir::Generics<'_>, - suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>, + suggestions: &mut Vec<(Span, String, String, SuggestChangingConstraintsMessage<'_>)>, param: &hir::GenericParam<'_>, def_id: Option, ) { @@ -207,7 +208,8 @@ fn suggest_changing_unsized_bound( continue; } - let mut push_suggestion = |sp, msg| suggestions.push((sp, String::new(), msg)); + let mut push_suggestion = + |sp, msg| suggestions.push((sp, "Sized".to_string(), String::new(), msg)); if predicate.bounds.len() == unsized_bounds.len() { // All the bounds are unsized bounds, e.g. @@ -278,8 +280,25 @@ pub fn suggest_constraining_type_params<'a>( span_to_replace: Option, ) -> bool { let mut grouped = FxHashMap::default(); + let mut unstable_suggestion = false; param_names_and_constraints.for_each(|(param_name, constraint, def_id)| { - grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id)) + let stable = match def_id { + Some(def_id) => match tcx.lookup_stability(def_id) { + Some(s) => s.level.is_stable(), + None => true, + }, + None => true, + }; + if stable || tcx.sess.is_nightly_build() { + grouped.entry(param_name).or_insert(Vec::new()).push(( + constraint, + def_id, + if stable { "" } else { "unstable " }, + )); + if !stable { + unstable_suggestion = true; + } + } }); let mut applicability = Applicability::MachineApplicable; @@ -290,16 +309,21 @@ pub fn suggest_constraining_type_params<'a>( let Some(param) = param else { return false }; { - let mut sized_constraints = constraints.extract_if(|(_, def_id)| { + let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| { def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)) }); - if let Some((_, def_id)) = sized_constraints.next() { + if let Some((_, def_id, _)) = sized_constraints.next() { applicability = Applicability::MaybeIncorrect; err.span_label(param.span, "this type parameter needs to be `Sized`"); suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id); } } + let bound_message = if constraints.iter().any(|(_, def_id, _)| def_id.is_none()) { + SuggestChangingConstraintsMessage::RestrictBoundFurther + } else { + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name } + }; // in the scenario like impl has stricter requirements than trait, // we should not suggest restrict bound on the impl, here we double check @@ -312,15 +336,54 @@ pub fn suggest_constraining_type_params<'a>( .collect(); constraints - .retain(|(_, def_id)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def))); + .retain(|(_, def_id, _)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def))); if constraints.is_empty() { continue; } - let mut constraint = constraints.iter().map(|&(c, _)| c).collect::>(); + let mut constraint = constraints.iter().map(|&(c, _, _)| c).collect::>(); constraint.sort(); constraint.dedup(); + let all_known = constraints.iter().all(|&(_, def_id, _)| def_id.is_some()); + let all_stable = constraints.iter().all(|&(_, _, stable)| stable.is_empty()); + let all_unstable = constraints.iter().all(|&(_, _, stable)| !stable.is_empty()); + let post = if all_stable || all_unstable { + // Don't redundantly say "trait `X`, trait `Y`", instead "traits `X` and `Y`" + let mut trait_names = constraints + .iter() + .map(|&(c, def_id, _)| match def_id { + None => format!("`{c}`"), + Some(def_id) => format!("`{}`", tcx.item_name(def_id)), + }) + .collect::>(); + trait_names.sort(); + trait_names.dedup(); + let n = trait_names.len(); + let stable = if all_stable { "" } else { "unstable " }; + let trait_ = if all_known { format!("trait{}", pluralize!(n)) } else { String::new() }; + format!("{stable}{trait_}{}", match &trait_names[..] { + [t] => format!(" {t}"), + [ts @ .., last] => format!(" {} and {last}", ts.join(", ")), + [] => return false, + },) + } else { + // We're more explicit when there's a mix of stable and unstable traits. + let mut trait_names = constraints + .iter() + .map(|&(c, def_id, stable)| match def_id { + None => format!("`{c}`"), + Some(def_id) => format!("{stable}trait `{}`", tcx.item_name(def_id)), + }) + .collect::>(); + trait_names.sort(); + trait_names.dedup(); + match &trait_names[..] { + [t] => t.to_string(), + [ts @ .., last] => format!("{} and {last}", ts.join(", ")), + [] => return false, + } + }; let constraint = constraint.join(" + "); let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| { let suggestion = if span_to_replace.is_some() { @@ -333,13 +396,11 @@ pub fn suggest_constraining_type_params<'a>( format!(" {constraint}") }; - use SuggestChangingConstraintsMessage::RestrictBoundFurther; - if let Some(open_paren_sp) = open_paren_sp { - suggestions.push((open_paren_sp, "(".to_string(), RestrictBoundFurther)); - suggestions.push((span, format!("){suggestion}"), RestrictBoundFurther)); + suggestions.push((open_paren_sp, post.clone(), "(".to_string(), bound_message)); + suggestions.push((span, post.clone(), format!("){suggestion}"), bound_message)); } else { - suggestions.push((span, suggestion, RestrictBoundFurther)); + suggestions.push((span, post.clone(), suggestion, bound_message)); } }; @@ -397,7 +458,8 @@ pub fn suggest_constraining_type_params<'a>( // - insert: `, X: Bar` suggestions.push(( generics.tail_span_for_predicate_suggestion(), - constraints.iter().fold(String::new(), |mut string, &(constraint, _)| { + post, + constraints.iter().fold(String::new(), |mut string, &(constraint, _, _)| { write!(string, ", {param_name}: {constraint}").unwrap(); string }), @@ -426,6 +488,7 @@ pub fn suggest_constraining_type_params<'a>( // default (``), so we suggest adding `where T: Bar`. suggestions.push(( generics.tail_span_for_predicate_suggestion(), + post, format!("{where_prefix} {param_name}: {constraint}"), SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name }, )); @@ -439,6 +502,7 @@ pub fn suggest_constraining_type_params<'a>( if let Some(colon_span) = param.colon_span { suggestions.push(( colon_span.shrink_to_hi(), + post, format!(" {constraint}"), SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, )); @@ -451,6 +515,7 @@ pub fn suggest_constraining_type_params<'a>( // - help: consider restricting this type parameter with `T: Foo` suggestions.push(( param.span.shrink_to_hi(), + post, format!(": {constraint}"), SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, )); @@ -459,39 +524,46 @@ pub fn suggest_constraining_type_params<'a>( // FIXME: remove the suggestions that are from derive, as the span is not correct suggestions = suggestions .into_iter() - .filter(|(span, _, _)| !span.in_derive_expansion()) + .filter(|(span, _, _, _)| !span.in_derive_expansion()) .collect::>(); - + let suggested = !suggestions.is_empty(); if suggestions.len() == 1 { - let (span, suggestion, msg) = suggestions.pop().unwrap(); + let (span, post, suggestion, msg) = suggestions.pop().unwrap(); let msg = match msg { SuggestChangingConstraintsMessage::RestrictBoundFurther => { - Cow::from("consider further restricting this bound") + format!("consider further restricting this bound") + } + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } + | SuggestChangingConstraintsMessage::RestrictType { ty } + if ty.starts_with("impl ") => + { + format!("consider restricting opaque type `{ty}` with {post}") } SuggestChangingConstraintsMessage::RestrictType { ty } => { - Cow::from(format!("consider restricting type parameter `{ty}`")) + format!("consider restricting type parameter `{ty}` with {post}") } SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => { - Cow::from(format!("consider further restricting type parameter `{ty}`")) + format!("consider further restricting type parameter `{ty}` with {post}") } SuggestChangingConstraintsMessage::RemoveMaybeUnsized => { - Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`") + format!("consider removing the `?Sized` bound to make the type parameter `Sized`") } SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => { - Cow::from("consider replacing `?Sized` with `Sized`") + format!("consider replacing `?Sized` with `Sized`") } }; err.span_suggestion_verbose(span, msg, suggestion, applicability); } else if suggestions.len() > 1 { + let post = if unstable_suggestion { " (some of them are unstable traits)" } else { "" }; err.multipart_suggestion_verbose( - "consider restricting type parameters", - suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(), + format!("consider restricting type parameters{post}"), + suggestions.into_iter().map(|(span, _, suggestion, _)| (span, suggestion)).collect(), applicability, ); } - true + suggested } /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 561229cf7255..f844e8fbe030 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -2,19 +2,186 @@ use std::borrow::Cow; use std::cell::RefCell; +use std::ffi::OsString; +use std::path::PathBuf; use std::sync::OnceLock; use std::{io, ops, str}; use regex::Regex; -use rustc_graphviz as dot; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, BasicBlock, Body, Location, graphviz_safe_def_name}; +use rustc_middle::mir::{ + self, BasicBlock, Body, Location, create_dump_file, dump_enabled, graphviz_safe_def_name, + traversal, +}; +use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_span::symbol::{Symbol, sym}; +use tracing::debug; +use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor}; +use crate::errors::{ + DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, +}; + +/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via +/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are +/// the same. +pub(super) fn write_graphviz_results<'tcx, A>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + results: &mut Results<'tcx, A>, + pass_name: Option<&'static str>, +) -> std::io::Result<()> +where + A: Analysis<'tcx>, + A::Domain: DebugWithContext, +{ + use std::fs; + use std::io::Write; + + let def_id = body.source.def_id(); + let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { + // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` + return Ok(()); + }; + + let file = try { + match attrs.output_path(A::NAME) { + Some(path) => { + debug!("printing dataflow results for {:?} to {}", def_id, path.display()); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + fs::File::create_buffered(&path)? + } + + None if dump_enabled(tcx, A::NAME, def_id) => { + create_dump_file(tcx, "dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? + } + + _ => return Ok(()), + } + }; + let mut file = match file { + Ok(f) => f, + Err(e) => return Err(e), + }; + + let style = match attrs.formatter { + Some(sym::two_phase) => OutputStyle::BeforeAndAfter, + _ => OutputStyle::AfterOnly, + }; + + let mut buf = Vec::new(); + + let graphviz = Formatter::new(body, results, style); + let mut render_opts = + vec![dot::RenderOption::Fontname(tcx.sess.opts.unstable_opts.graphviz_font.clone())]; + if tcx.sess.opts.unstable_opts.graphviz_dark_mode { + render_opts.push(dot::RenderOption::DarkTheme); + } + let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)); + + let lhs = try { + r?; + file.write_all(&buf)?; + }; + + lhs +} + +#[derive(Default)] +struct RustcMirAttrs { + basename_and_suffix: Option, + formatter: Option, +} + +impl RustcMirAttrs { + fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { + let mut result = Ok(()); + let mut ret = RustcMirAttrs::default(); + + let rustc_mir_attrs = tcx + .get_attrs(def_id, sym::rustc_mir) + .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); + + for attr in rustc_mir_attrs { + let attr_result = if attr.has_name(sym::borrowck_graphviz_postflow) { + Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| { + let path = PathBuf::from(s.to_string()); + match path.file_name() { + Some(_) => Ok(path), + None => { + tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); + Err(()) + } + } + }) + } else if attr.has_name(sym::borrowck_graphviz_format) { + Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s { + sym::gen_kill | sym::two_phase => Ok(s), + _ => { + tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); + Err(()) + } + }) + } else { + Ok(()) + }; + + result = result.and(attr_result); + } + + result.map(|()| ret) + } + + fn set_field( + field: &mut Option, + tcx: TyCtxt<'_>, + attr: &ast::MetaItemInner, + mapper: impl FnOnce(Symbol) -> Result, + ) -> Result<(), ()> { + if field.is_some() { + tcx.dcx() + .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() }); + + return Err(()); + } + + if let Some(s) = attr.value_str() { + *field = Some(mapper(s)?); + Ok(()) + } else { + tcx.dcx() + .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() }); + Err(()) + } + } + + /// Returns the path where dataflow results should be written, or `None` + /// `borrowck_graphviz_postflow` was not specified. + /// + /// This performs the following transformation to the argument of `borrowck_graphviz_postflow`: + /// + /// "path/suffix.dot" -> "path/analysis_name_suffix.dot" + fn output_path(&self, analysis_name: &str) -> Option { + let mut ret = self.basename_and_suffix.as_ref().cloned()?; + let suffix = ret.file_name().unwrap(); // Checked when parsing attrs + + let mut file_name: OsString = analysis_name.into(); + file_name.push("_"); + file_name.push(suffix); + ret.set_file_name(file_name); + + Some(ret) + } +} #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) enum OutputStyle { +enum OutputStyle { AfterOnly, BeforeAndAfter, } @@ -28,7 +195,7 @@ impl OutputStyle { } } -pub(crate) struct Formatter<'mir, 'tcx, A> +struct Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { @@ -45,12 +212,12 @@ impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { - pub(crate) fn new( + fn new( body: &'mir Body<'tcx>, results: &'mir mut Results<'tcx, A>, style: OutputStyle, ) -> Self { - let reachable = mir::traversal::reachable_as_bitset(body); + let reachable = traversal::reachable_as_bitset(body); Formatter { cursor: results.as_results_cursor(body).into(), style, reachable } } @@ -61,7 +228,7 @@ where /// A pair of a basic block and an index into that basic blocks `successors`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(crate) struct CfgEdge { +struct CfgEdge { source: BasicBlock, index: usize, } @@ -520,7 +687,7 @@ struct StateDiffCollector { impl StateDiffCollector { fn run<'tcx, A>( - body: &mir::Body<'tcx>, + body: &Body<'tcx>, block: BasicBlock, results: &mut Results<'tcx, A>, style: OutputStyle, diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index b9407882ec5d..13384d6f2855 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -42,7 +42,7 @@ use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, Terminator use rustc_middle::ty::TyCtxt; use tracing::error; -use self::results::write_graphviz_results; +use self::graphviz::write_graphviz_results; use super::fmt::DebugWithContext; mod cursor; diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index c4321c454e6e..a7dbd99b8abd 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -1,22 +1,9 @@ //! Dataflow analysis results. -use std::ffi::OsString; -use std::path::PathBuf; - -use rustc_hir::def_id::DefId; use rustc_index::IndexVec; -use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal}; -use rustc_middle::ty::TyCtxt; -use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_span::symbol::{Symbol, sym}; -use tracing::debug; -use {rustc_ast as ast, rustc_graphviz as dot}; +use rustc_middle::mir::{BasicBlock, Body, traversal}; -use super::fmt::DebugWithContext; -use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results}; -use crate::errors::{ - DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, -}; +use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results}; use crate::framework::cursor::ResultsHandle; pub type EntrySets<'tcx, A> = IndexVec>::Domain>; @@ -41,16 +28,13 @@ where /// `Results` is also used outside the cursor. pub fn as_results_cursor<'mir>( &'mir mut self, - body: &'mir mir::Body<'tcx>, + body: &'mir Body<'tcx>, ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, ResultsHandle::BorrowedMut(self)) } /// Creates a `ResultsCursor` that takes ownership of the `Results`. - pub fn into_results_cursor<'mir>( - self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A> { + pub fn into_results_cursor<'mir>(self, body: &'mir Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, ResultsHandle::Owned(self)) } @@ -61,7 +45,7 @@ where pub fn visit_with<'mir>( &mut self, - body: &'mir mir::Body<'tcx>, + body: &'mir Body<'tcx>, blocks: impl IntoIterator, vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { @@ -70,166 +54,10 @@ where pub fn visit_reachable_with<'mir>( &mut self, - body: &'mir mir::Body<'tcx>, + body: &'mir Body<'tcx>, vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) } } - -// Graphviz - -/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via -/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are -/// the same. -pub(super) fn write_graphviz_results<'tcx, A>( - tcx: TyCtxt<'tcx>, - body: &mir::Body<'tcx>, - results: &mut Results<'tcx, A>, - pass_name: Option<&'static str>, -) -> std::io::Result<()> -where - A: Analysis<'tcx>, - A::Domain: DebugWithContext, -{ - use std::fs; - use std::io::Write; - - let def_id = body.source.def_id(); - let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { - // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return Ok(()); - }; - - let file = try { - match attrs.output_path(A::NAME) { - Some(path) => { - debug!("printing dataflow results for {:?} to {}", def_id, path.display()); - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; - } - fs::File::create_buffered(&path)? - } - - None if dump_enabled(tcx, A::NAME, def_id) => { - create_dump_file(tcx, "dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? - } - - _ => return Ok(()), - } - }; - let mut file = match file { - Ok(f) => f, - Err(e) => return Err(e), - }; - - let style = match attrs.formatter { - Some(sym::two_phase) => graphviz::OutputStyle::BeforeAndAfter, - _ => graphviz::OutputStyle::AfterOnly, - }; - - let mut buf = Vec::new(); - - let graphviz = graphviz::Formatter::new(body, results, style); - let mut render_opts = - vec![dot::RenderOption::Fontname(tcx.sess.opts.unstable_opts.graphviz_font.clone())]; - if tcx.sess.opts.unstable_opts.graphviz_dark_mode { - render_opts.push(dot::RenderOption::DarkTheme); - } - let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)); - - let lhs = try { - r?; - file.write_all(&buf)?; - }; - - lhs -} - -#[derive(Default)] -struct RustcMirAttrs { - basename_and_suffix: Option, - formatter: Option, -} - -impl RustcMirAttrs { - fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { - let mut result = Ok(()); - let mut ret = RustcMirAttrs::default(); - - let rustc_mir_attrs = tcx - .get_attrs(def_id, sym::rustc_mir) - .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); - - for attr in rustc_mir_attrs { - let attr_result = if attr.has_name(sym::borrowck_graphviz_postflow) { - Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| { - let path = PathBuf::from(s.to_string()); - match path.file_name() { - Some(_) => Ok(path), - None => { - tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); - Err(()) - } - } - }) - } else if attr.has_name(sym::borrowck_graphviz_format) { - Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s { - sym::gen_kill | sym::two_phase => Ok(s), - _ => { - tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); - Err(()) - } - }) - } else { - Ok(()) - }; - - result = result.and(attr_result); - } - - result.map(|()| ret) - } - - fn set_field( - field: &mut Option, - tcx: TyCtxt<'_>, - attr: &ast::MetaItemInner, - mapper: impl FnOnce(Symbol) -> Result, - ) -> Result<(), ()> { - if field.is_some() { - tcx.dcx() - .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() }); - - return Err(()); - } - - if let Some(s) = attr.value_str() { - *field = Some(mapper(s)?); - Ok(()) - } else { - tcx.dcx() - .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() }); - Err(()) - } - } - - /// Returns the path where dataflow results should be written, or `None` - /// `borrowck_graphviz_postflow` was not specified. - /// - /// This performs the following transformation to the argument of `borrowck_graphviz_postflow`: - /// - /// "path/suffix.dot" -> "path/analysis_name_suffix.dot" - fn output_path(&self, analysis_name: &str) -> Option { - let mut ret = self.basename_and_suffix.as_ref().cloned()?; - let suffix = ret.file_name().unwrap(); // Checked when parsing attrs - - let mut file_name: OsString = analysis_name.into(); - file_name.push("_"); - file_name.push(suffix); - ret.set_file_name(file_name); - - Some(ret) - } -} diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index b9e194b00c54..d69a8019c8d0 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -1,7 +1,3 @@ -//! Dataflow analyses are built upon some interpretation of the -//! bitvectors attached to each basic block, represented via a -//! zero-sized structure. - mod borrowed_locals; mod initialized; mod liveness; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8d16d44b0a26..3a9e9b480ecf 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2631,7 +2631,7 @@ impl<'a> Parser<'a> { }; self.bump(); // Eat `let` token let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt( + let pat = self.parse_pat_no_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, @@ -2778,7 +2778,7 @@ impl<'a> Parser<'a> { }; // Try to parse the pattern `for ($PAT) in $EXPR`. let pat = match ( - self.parse_pat_allow_top_alt( + self.parse_pat_allow_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, @@ -3241,7 +3241,7 @@ impl<'a> Parser<'a> { // then we should recover. let mut snapshot = this.create_snapshot_for_diagnostic(); let pattern_follows = snapshot - .parse_pat_allow_top_alt( + .parse_pat_no_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, @@ -3315,43 +3315,37 @@ impl<'a> Parser<'a> { fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P, Option>)> { if self.token == token::OpenDelim(Delimiter::Parenthesis) { - // Detect and recover from `($pat if $cond) => $arm`. let left = self.token.span; - match self.parse_pat_allow_top_alt( + let pat = self.parse_pat_no_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, CommaRecoveryMode::EitherTupleOrPipe, - ) { - Ok(pat) => Ok((pat, self.parse_match_arm_guard()?)), - Err(err) - if let prev_sp = self.prev_token.span - && let true = self.eat_keyword(kw::If) => - { - // We know for certain we've found `($pat if` so far. - let mut cond = match self.parse_match_guard_condition() { - Ok(cond) => cond, - Err(cond_err) => { - cond_err.cancel(); - return Err(err); - } - }; - err.cancel(); - CondChecker::new(self).visit_expr(&mut cond); - self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]); - self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; - let right = self.prev_token.span; - self.dcx().emit_err(errors::ParenthesesInMatchPat { - span: vec![left, right], - sugg: errors::ParenthesesInMatchPatSugg { left, right }, - }); - Ok((self.mk_pat(left.to(prev_sp), ast::PatKind::Wild), Some(cond))) - } - Err(err) => Err(err), + )?; + if let ast::PatKind::Paren(subpat) = &pat.kind + && let ast::PatKind::Guard(..) = &subpat.kind + { + // Detect and recover from `($pat if $cond) => $arm`. + // FIXME(guard_patterns): convert this to a normal guard instead + let span = pat.span; + let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() }; + let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else { + unreachable!() + }; + self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span); + CondChecker::new(self).visit_expr(&mut cond); + let right = self.prev_token.span; + self.dcx().emit_err(errors::ParenthesesInMatchPat { + span: vec![left, right], + sugg: errors::ParenthesesInMatchPatSugg { left, right }, + }); + Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond))) + } else { + Ok((pat, self.parse_match_arm_guard()?)) } } else { // Regular parser flow: - let pat = self.parse_pat_allow_top_alt( + let pat = self.parse_pat_no_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 8fb6f85d0dd8..752a52b382b3 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -174,7 +174,7 @@ impl<'a> Parser<'a> { NonterminalKind::Pat(pat_kind) => { NtPat(self.collect_tokens_no_attrs(|this| match pat_kind { PatParam { .. } => this.parse_pat_no_top_alt(None, None), - PatWithOr => this.parse_pat_allow_top_alt( + PatWithOr => this.parse_pat_no_top_guard( None, RecoverComma::No, RecoverColon::No, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e08b925f0089..4cda887a02bd 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -99,9 +99,34 @@ pub enum PatternLocation { impl<'a> Parser<'a> { /// Parses a pattern. /// - /// Corresponds to `pat` in RFC 2535 and does not admit or-patterns - /// at the top level. Used when parsing the parameters of lambda expressions, - /// functions, function pointers, and `pat` macro fragments. + /// Corresponds to `Pattern` in RFC 3637 and admits guard patterns at the top level. + /// Used when parsing patterns in all cases where neither `PatternNoTopGuard` nor + /// `PatternNoTopAlt` (see below) are used. + pub fn parse_pat_allow_top_guard( + &mut self, + expected: Option, + rc: RecoverComma, + ra: RecoverColon, + rt: CommaRecoveryMode, + ) -> PResult<'a, P> { + let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?; + + if self.eat_keyword(kw::If) { + let cond = self.parse_expr()?; + // Feature-gate guard patterns + self.psess.gated_spans.gate(sym::guard_patterns, cond.span); + let span = pat.span.to(cond.span); + Ok(self.mk_pat(span, PatKind::Guard(pat, cond))) + } else { + Ok(pat) + } + } + + /// Parses a pattern. + /// + /// Corresponds to `PatternNoTopAlt` in RFC 3637 and does not admit or-patterns + /// or guard patterns at the top level. Used when parsing the parameters of lambda + /// expressions, functions, function pointers, and `pat_param` macro fragments. pub fn parse_pat_no_top_alt( &mut self, expected: Option, @@ -112,25 +137,26 @@ impl<'a> Parser<'a> { /// Parses a pattern. /// - /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. - /// Used for parsing patterns in all cases when `pat` is not used. + /// Corresponds to `PatternNoTopGuard` in RFC 3637 and allows or-patterns, but not + /// guard patterns, at the top level. Used for parsing patterns in `pat` fragments (until + /// the next edition) and `let`, `if let`, and `while let` expressions. /// /// Note that after the FCP in , /// a leading vert is allowed in nested or-patterns, too. This allows us to /// simplify the grammar somewhat. - pub fn parse_pat_allow_top_alt( + pub fn parse_pat_no_top_guard( &mut self, expected: Option, rc: RecoverComma, ra: RecoverColon, rt: CommaRecoveryMode, ) -> PResult<'a, P> { - self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat) + self.parse_pat_no_top_guard_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat) } /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = /// recovered). - fn parse_pat_allow_top_alt_inner( + fn parse_pat_no_top_guard_inner( &mut self, expected: Option, rc: RecoverComma, @@ -231,7 +257,7 @@ impl<'a> Parser<'a> { // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level // or-patterns so that we can detect when a user tries to use it. This allows us to print a // better error message. - let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner( + let (pat, trailing_vert) = self.parse_pat_no_top_guard_inner( expected, rc, RecoverColon::No, @@ -696,7 +722,7 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(Delimiter::Bracket)) { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq(Delimiter::Bracket, |p| { - p.parse_pat_allow_top_alt( + p.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::No, @@ -944,7 +970,7 @@ impl<'a> Parser<'a> { let open_paren = self.token.span; let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt( + p.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::No, @@ -1361,7 +1387,7 @@ impl<'a> Parser<'a> { path: Path, ) -> PResult<'a, PatKind> { let (fields, _) = self.parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt( + p.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::No, @@ -1396,7 +1422,7 @@ impl<'a> Parser<'a> { self.parse_builtin(|self_, _lo, ident| { Ok(match ident.name { // builtin#deref(PAT) - sym::deref => Some(ast::PatKind::Deref(self_.parse_pat_allow_top_alt( + sym::deref => Some(ast::PatKind::Deref(self_.parse_pat_allow_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, @@ -1671,7 +1697,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form `fieldname: pat`. let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_allow_top_alt( + let pat = self.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::No, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 2f19a9b6b20b..6a7029a8f1c8 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -469,7 +469,7 @@ impl<'a> Parser<'a> { PathStyle::Pat if let Ok(_) = self .parse_paren_comma_seq(|p| { - p.parse_pat_allow_top_alt( + p.parse_pat_allow_top_guard( None, RecoverComma::No, RecoverColon::No, diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index b8f66a2b2ec3..f2a37307ceeb 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -555,6 +555,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Slice, Rest, Never, + Guard, Paren, MacCall, Err diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index a1917fed4d9c..d2bb0b3f2771 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -198,12 +198,12 @@ trait QueryConfigRestored<'tcx> { -> Self::RestoredValue; } -pub fn query_system<'tcx>( +pub fn query_system<'a>( local_providers: Providers, extern_providers: ExternProviders, - on_disk_cache: Option>, + on_disk_cache: Option, incremental: bool, -) -> QuerySystem<'tcx> { +) -> QuerySystem<'a> { QuerySystem { states: Default::default(), arenas: Default::default(), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7db3b7b7d9df..993d111466be 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -19,7 +19,6 @@ use rustc_errors::emitter::{ DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination, }; use rustc_errors::json::JsonEmitter; -use rustc_errors::registry::Registry; use rustc_errors::{ Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, FluentBundle, LazyFallbackBundle, TerminalUrl, fallback_fluent_bundle, @@ -276,11 +275,11 @@ impl Session { } /// Invoked all the way at the end to finish off diagnostics printing. - pub fn finish_diagnostics(&self, registry: &Registry) -> Option { + pub fn finish_diagnostics(&self) -> Option { let mut guar = None; guar = guar.or(self.check_miri_unleashed_features()); guar = guar.or(self.dcx().emit_stashed_diagnostics()); - self.dcx().print_error_count(registry); + self.dcx().print_error_count(); if self.opts.json_future_incompat { self.dcx().emit_future_breakage_report(); } @@ -880,7 +879,6 @@ impl Session { #[allow(rustc::bad_opt_access)] fn default_emitter( sopts: &config::Options, - registry: rustc_errors::registry::Registry, source_map: Lrc, bundle: Option>, fallback_bundle: LazyFallbackBundle, @@ -943,7 +941,6 @@ fn default_emitter( json_rendered, color_config, ) - .registry(Some(registry)) .fluent_bundle(bundle) .ui_testing(sopts.unstable_opts.ui_testing) .ignored_directories_in_source_blocks( @@ -999,11 +996,11 @@ pub fn build_session( sopts.unstable_opts.translate_directionality_markers, ); let source_map = rustc_span::source_map::get_source_map().unwrap(); - let emitter = - default_emitter(&sopts, registry, Lrc::clone(&source_map), bundle, fallback_bundle); + let emitter = default_emitter(&sopts, Lrc::clone(&source_map), bundle, fallback_bundle); - let mut dcx = - DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)); + let mut dcx = DiagCtxt::new(emitter) + .with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)) + .with_registry(registry); if let Some(ice_file) = ice_file { dcx = dcx.with_ice_file(ice_file); } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index d4b034ea2190..614c9169d660 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -342,8 +342,9 @@ macro_rules! run_driver { /// Runs the compiler against given target and tests it with `test_function` pub fn run(&mut self) -> Result> { - let compiler_result = rustc_driver::catch_fatal_errors(|| { - RunCompiler::new(&self.args.clone(), self).run() + let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> { + RunCompiler::new(&self.args.clone(), self).run(); + Ok(()) }); match (compiler_result, self.result.take()) { (Ok(Ok(())), Some(ControlFlow::Continue(value))) => Ok(value), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 57c645bfaba5..958d4f0c2514 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -51,6 +51,7 @@ pub mod source_map; use source_map::{SourceMap, SourceMapInputs}; pub use self::caching_source_map_view::CachingSourceMapView; +use crate::fatal_error::FatalError; pub mod edition; use edition::Edition; @@ -2614,6 +2615,10 @@ impl ErrorGuaranteed { pub fn unchecked_error_guaranteed() -> Self { ErrorGuaranteed(()) } + + pub fn raise_fatal(self) -> ! { + FatalError.raise() + } } impl Encodable for ErrorGuaranteed { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a7dc20a874b4..818d4afffc66 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -999,6 +999,7 @@ symbols! { global_registration, globs, gt, + guard_patterns, half_open_range_patterns, half_open_range_patterns_in_slices, hash, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 8ba7969207e8..f856a8d7abbe 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -52,7 +52,9 @@ use std::{cmp, fmt, iter}; use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; +use rustc_errors::{ + Applicability, Diag, DiagStyledString, IntoDiagArg, MultiSpan, StringPart, pluralize, +}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -67,6 +69,7 @@ use rustc_middle::ty::{ self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{BytePos, DesugaringKind, Pos, Span, sym}; use tracing::{debug, instrument}; @@ -211,7 +214,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } /// Adds a note if the types come from similarly named crates - fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) { + fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) -> bool { + // FIXME(estebank): unify with `report_similar_impl_candidates`. The message is similar, + // even if the logic needed to detect the case is very different. use hir::def_id::CrateNum; use rustc_hir::definitions::DisambiguatedDefPathData; use ty::GenericArg; @@ -285,7 +290,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId| { + let report_path_match = |err: &mut Diag<'_>, did1: DefId, did2: DefId, ty: &str| -> bool { // Only report definitions from different crates. If both definitions // are from a local module we could have false positives, e.g. // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; @@ -297,24 +302,112 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // We compare strings because DefPath can be different // for imported and non-imported crates + let expected_str = self.tcx.def_path_str(did1); + let found_str = self.tcx.def_path_str(did2); + let Ok(expected_abs) = abs_path(did1) else { return false }; + let Ok(found_abs) = abs_path(did2) else { return false }; let same_path = || -> Result<_, PrintError> { - Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) - || abs_path(did1)? == abs_path(did2)?) + Ok(expected_str == found_str || expected_abs == found_abs) + }; + // We want to use as unique a type path as possible. If both types are "locally + // known" by the same name, we use the "absolute path" which uses the original + // crate name instead. + let (expected, found) = if expected_str == found_str { + (expected_abs.join("::"), found_abs.join("::")) + } else { + (expected_str.clone(), found_str.clone()) }; if same_path().unwrap_or(false) { - let crate_name = self.tcx.crate_name(did1.krate); - let msg = if did1.is_local() || did2.is_local() { + // We've displayed "expected `a::b`, found `a::b`". We add context to + // differentiate the different cases where that might happen. + let expected_crate_name = self.tcx.crate_name(did1.krate); + let found_crate_name = self.tcx.crate_name(did2.krate); + let same_crate = expected_crate_name == found_crate_name; + let expected_sp = self.tcx.def_span(did1); + let found_sp = self.tcx.def_span(did2); + + let both_direct_dependencies = if !did1.is_local() + && !did2.is_local() + && let Some(data1) = self.tcx.extern_crate(did1.krate) + && let Some(data2) = self.tcx.extern_crate(did2.krate) + && data1.dependency_of == LOCAL_CRATE + && data2.dependency_of == LOCAL_CRATE + { + // If both crates are directly depended on, we don't want to mention that + // in the final message, as it is redundant wording. + // We skip the case of semver trick, where one version of the local crate + // depends on another version of itself by checking that both crates at play + // are not the current one. + true + } else { + false + }; + + let mut span: MultiSpan = vec![expected_sp, found_sp].into(); + span.push_span_label( + self.tcx.def_span(did1), + format!("this is the expected {ty} `{expected}`"), + ); + span.push_span_label( + self.tcx.def_span(did2), + format!("this is the found {ty} `{found}`"), + ); + for def_id in [did1, did2] { + let crate_name = self.tcx.crate_name(def_id.krate); + if !def_id.is_local() + && let Some(data) = self.tcx.extern_crate(def_id.krate) + { + let descr = if same_crate { + "one version of".to_string() + } else { + format!("one {ty} comes from") + }; + let dependency = if both_direct_dependencies { + if let rustc_session::cstore::ExternCrateSource::Extern(def_id) = + data.src + && let Some(name) = self.tcx.opt_item_name(def_id) + { + format!(", which is renamed locally to `{name}`") + } else { + String::new() + } + } else if data.dependency_of == LOCAL_CRATE { + ", as a direct dependency of the current crate".to_string() + } else { + let dep = self.tcx.crate_name(data.dependency_of); + format!(", as a dependency of crate `{dep}`") + }; + span.push_span_label( + data.span, + format!("{descr} crate `{crate_name}` used here{dependency}"), + ); + } + } + let msg = if (did1.is_local() || did2.is_local()) && same_crate { format!( - "the crate `{crate_name}` is compiled multiple times, possibly with different configurations" + "the crate `{expected_crate_name}` is compiled multiple times, \ + possibly with different configurations", + ) + } else if same_crate { + format!( + "two different versions of crate `{expected_crate_name}` are being \ + used; two types coming from two different versions of the same crate \ + are different types even if they look the same", ) } else { format!( - "perhaps two different versions of crate `{crate_name}` are being used?" + "two types coming from two different crates are different types even \ + if they look the same", ) }; - err.note(msg); + err.span_note(span, msg); + if same_crate { + err.help("you can use `cargo tree` to explore your dependency tree"); + } + return true; } } + false }; match terr { TypeError::Sorts(ref exp_found) => { @@ -323,14 +416,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) = (exp_found.expected.kind(), exp_found.found.kind()) { - report_path_match(err, exp_adt.did(), found_adt.did()); + return report_path_match(err, exp_adt.did(), found_adt.did(), "type"); } } TypeError::Traits(ref exp_found) => { - report_path_match(err, exp_found.expected, exp_found.found); + return report_path_match(err, exp_found.expected, exp_found.found, "trait"); } _ => (), // FIXME(#22750) handle traits and stuff } + false } fn note_error_origin( @@ -1409,6 +1503,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { label_or_note(span, terr.to_string(self.tcx)); } + if self.check_and_note_conflicting_crates(diag, terr) { + return; + } + if let Some((expected, found, path)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( @@ -1470,15 +1568,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |prim: Ty<'tcx>, shadow: Ty<'tcx>, defid: DefId, diag: &mut Diag<'_>| { let name = shadow.sort_string(self.tcx); diag.note(format!( - "{prim} and {name} have similar names, but are actually distinct types" + "`{prim}` and {name} have similar names, but are actually distinct types" + )); + diag.note(format!( + "one `{prim}` is a primitive defined by the language", )); - diag.note(format!("{prim} is a primitive defined by the language")); let def_span = self.tcx.def_span(defid); let msg = if defid.is_local() { - format!("{name} is defined in the current crate") + format!("the other {name} is defined in the current crate") } else { let crate_name = self.tcx.crate_name(defid.krate); - format!("{name} is defined in crate `{crate_name}`") + format!("the other {name} is defined in crate `{crate_name}`") }; diag.span_note(def_span, msg); }; @@ -1666,8 +1766,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - self.check_and_note_conflicting_crates(diag, terr); - self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id()); if let Some(exp_found) = exp_found && let exp_found = TypeError::Sorts(exp_found) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 90b182536290..4fb02f609438 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1745,9 +1745,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; ( data.span, - format!( - "one version of crate `{crate_name}` is used here, as a {dependency}" - ), + format!("one version of crate `{crate_name}` used here, as a {dependency}"), ) }) { diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 58a870d2e072..1590b9f29fca 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -54,6 +54,7 @@ impl bool { /// // `then`. /// assert_eq!(a, 1); /// ``` + #[doc(alias = "then_with")] #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "bool_then")] #[inline] diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 802b571c5106..3e53c0497cc7 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3577,34 +3577,44 @@ pub const fn discriminant_value(_v: &T) -> ::Discrimin unimplemented!() } -extern "rust-intrinsic" { - /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the - /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. - /// - /// `catch_fn` must not unwind. - /// - /// The third argument is a function called if an unwind occurs (both Rust `panic` and foreign - /// unwinds). This function takes the data pointer and a pointer to the target- and - /// runtime-specific exception object that was caught. - /// - /// Note that in the case of a foreign unwinding operation, the exception object data may not be - /// safely usable from Rust, and should not be directly exposed via the standard library. To - /// prevent unsafe access, the library implementation may either abort the process or present an - /// opaque error type to the user. - /// - /// For more information, see the compiler's source, as well as the documentation for the stable - /// version of this intrinsic, `std::panic::catch_unwind`. - #[rustc_nounwind] - pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; +/// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the +/// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. +/// +/// `catch_fn` must not unwind. +/// +/// The third argument is a function called if an unwind occurs (both Rust `panic` and foreign +/// unwinds). This function takes the data pointer and a pointer to the target- and +/// runtime-specific exception object that was caught. +/// +/// Note that in the case of a foreign unwinding operation, the exception object data may not be +/// safely usable from Rust, and should not be directly exposed via the standard library. To +/// prevent unsafe access, the library implementation may either abort the process or present an +/// opaque error type to the user. +/// +/// For more information, see the compiler's source, as well as the documentation for the stable +/// version of this intrinsic, `std::panic::catch_unwind`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn catch_unwind( + _try_fn: fn(*mut u8), + _data: *mut u8, + _catch_fn: fn(*mut u8, *mut u8), +) -> i32 { + unreachable!() +} - /// Emits a `nontemporal` store, which gives a hint to the CPU that the data should not be held - /// in cache. Except for performance, this is fully equivalent to `ptr.write(val)`. - /// - /// Not all architectures provide such an operation. For instance, x86 does not: while `MOVNT` - /// exists, that operation is *not* equivalent to `ptr.write(val)` (`MOVNT` writes can be reordered - /// in ways that are not allowed for regular writes). - #[rustc_nounwind] - pub fn nontemporal_store(ptr: *mut T, val: T); +/// Emits a `nontemporal` store, which gives a hint to the CPU that the data should not be held +/// in cache. Except for performance, this is fully equivalent to `ptr.write(val)`. +/// +/// Not all architectures provide such an operation. For instance, x86 does not: while `MOVNT` +/// exists, that operation is *not* equivalent to `ptr.write(val)` (`MOVNT` writes can be reordered +/// in ways that are not allowed for regular writes). +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nontemporal_store(_ptr: *mut T, _val: T) { + unreachable!() } /// See documentation of `<*const T>::offset_from` for details. diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 043747d0bc5e..535236ff89a3 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -597,6 +597,13 @@ impl Error for JoinPathsError { /// Returns the path of the current user's home directory if known. /// +/// This may return `None` if getting the directory fails or if the platform does not have user home directories. +/// +/// For storing user data and configuration it is often preferable to use more specific directories. +/// For example, [XDG Base Directories] on Unix or the `LOCALAPPDATA` and `APPDATA` environment variables on Windows. +/// +/// [XDG Base Directories]: https://specifications.freedesktop.org/basedir-spec/latest/ +/// /// # Unix /// /// - Returns the value of the 'HOME' environment variable if it is set diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 56cf438bd9bb..2313f4b5beb1 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -12,7 +12,7 @@ use crate::cell::{Cell, RefCell}; use crate::error::Error; use crate::fmt; -/// A thread local storage key which owns its contents. +/// A thread local storage (TLS) key which owns its contents. /// /// This key uses the fastest possible implementation available to it for the /// target platform. It is instantiated with the [`thread_local!`] macro and the diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands index 4be2dba34f6f..ef0c3740f032 100644 --- a/src/etc/lldb_commands +++ b/src/etc/lldb_commands @@ -1,4 +1,25 @@ -type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)String$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?str$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?\\[.+\\]$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^core::num::([a-z_]+::)*NonZero.+$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::([a-z_]+::)+)PathBuf$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust +type synthetic add -l lldb_lookup.synthetic_lookup -x "^(.*)$" --category Rust +type summary add -F _ -e -x -h "^.*$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a562a9eee717..0dda3466a717 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -5,12 +5,12 @@ use std::{io, mem}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; +use rustc_errors::TerminalUrl; use rustc_errors::codes::*; use rustc_errors::emitter::{ DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination, }; use rustc_errors::json::JsonEmitter; -use rustc_errors::{ErrorGuaranteed, TerminalUrl}; use rustc_feature::UnstableFeatures; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId}; @@ -326,7 +326,7 @@ pub(crate) fn run_global_ctxt( show_coverage: bool, render_options: RenderOptions, output_format: OutputFormat, -) -> Result<(clean::Crate, RenderOptions, Cache), ErrorGuaranteed> { +) -> (clean::Crate, RenderOptions, Cache) { // Certain queries assume that some checks were run elsewhere // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), // so type-check everything other than function bodies in this crate before running lints. @@ -340,9 +340,7 @@ pub(crate) fn run_global_ctxt( tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module)) }); - if let Some(guar) = tcx.dcx().has_errors() { - return Err(guar); - } + tcx.dcx().abort_if_errors(); tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); tcx.sess.time("check_mod_attrs", || { @@ -446,11 +444,9 @@ pub(crate) fn run_global_ctxt( LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous }; collector.resolve_ambiguities(); - if let Some(guar) = tcx.dcx().has_errors() { - return Err(guar); - } + tcx.dcx().abort_if_errors(); - Ok((krate, ctxt.render_options, ctxt.cache)) + (krate, ctxt.render_options, ctxt.cache) } /// Due to , diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index da1316a19cc3..70d9269ae5cd 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -16,7 +16,7 @@ pub(crate) use markdown::test as test_markdown; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError}; +use rustc_errors::{ColorConfig, DiagCtxtHandle}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LOCAL_CRATE; use rustc_interface::interface; @@ -89,11 +89,7 @@ fn get_doctest_dir() -> io::Result { TempFileBuilder::new().prefix("rustdoctest").tempdir() } -pub(crate) fn run( - dcx: DiagCtxtHandle<'_>, - input: Input, - options: RustdocOptions, -) -> Result<(), ErrorGuaranteed> { +pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions) { let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name; // See core::create_config for what's going on here. @@ -167,7 +163,7 @@ pub(crate) fn run( Err(error) => return crate::wrap_return(dcx, Err(error)), }; let args_path = temp_dir.path().join("rustdoc-cfgs"); - crate::wrap_return(dcx, generate_args_file(&args_path, &options))?; + crate::wrap_return(dcx, generate_args_file(&args_path, &options)); let CreateRunnableDocTests { standalone_tests, @@ -179,7 +175,7 @@ pub(crate) fn run( .. } = interface::run_compiler(config, |compiler| { compiler.enter(|queries| { - let collector = queries.global_ctxt()?.enter(|tcx| { + let collector = queries.global_ctxt().enter(|tcx| { let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); let opts = scrape_test_config(crate_name, crate_attrs, args_path); @@ -196,13 +192,11 @@ pub(crate) fn run( collector }); - if compiler.sess.dcx().has_errors().is_some() { - FatalError.raise(); - } + compiler.sess.dcx().abort_if_errors(); - Ok(collector) + collector }) - })?; + }); run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests); @@ -246,8 +240,6 @@ pub(crate) fn run( eprintln!("{unused_extern_json}"); } } - - Ok(()) } pub(crate) fn run_tests( diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8bc543f7e72a..a384c286039d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -76,7 +76,7 @@ use std::process; use std::sync::Arc; use std::sync::atomic::AtomicBool; -use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; +use rustc_errors::DiagCtxtHandle; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; @@ -179,7 +179,8 @@ pub fn main() { let exit_code = rustc_driver::catch_with_exit_code(|| { let at_args = rustc_driver::args::raw_args(&early_dcx)?; - main_args(&mut early_dcx, &at_args, using_internal_features) + main_args(&mut early_dcx, &at_args, using_internal_features); + Ok(()) }); process::exit(exit_code); } @@ -699,13 +700,10 @@ fn usage(argv0: &str) { ); } -/// A result type used by several functions under `main()`. -type MainResult = Result<(), ErrorGuaranteed>; - -pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) -> MainResult { +pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) { match res { - Ok(()) => dcx.has_errors().map_or(Ok(()), Err), - Err(err) => Err(dcx.err(err)), + Ok(()) => dcx.abort_if_errors(), + Err(err) => dcx.fatal(err), } } @@ -714,17 +712,17 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( renderopts: config::RenderOptions, cache: formats::cache::Cache, tcx: TyCtxt<'tcx>, -) -> MainResult { +) { match formats::run_format::(krate, renderopts, cache, tcx) { - Ok(_) => tcx.dcx().has_errors().map_or(Ok(()), Err), + Ok(_) => tcx.dcx().abort_if_errors(), Err(e) => { let mut msg = - tcx.dcx().struct_err(format!("couldn't generate documentation: {}", e.error)); + tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error)); let file = e.file.display().to_string(); if !file.is_empty() { msg.note(format!("failed to create or modify \"{file}\"")); } - Err(msg.emit()) + msg.emit(); } } } @@ -759,7 +757,7 @@ fn main_args( early_dcx: &mut EarlyDiagCtxt, at_args: &[String], using_internal_features: Arc, -) -> MainResult { +) { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -770,7 +768,7 @@ fn main_args( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = rustc_driver::args::arg_expand_all(early_dcx, at_args)?; + let args = rustc_driver::args::arg_expand_all(early_dcx, at_args); let mut options = getopts::Options::new(); for option in opts() { @@ -788,7 +786,7 @@ fn main_args( let (input, options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) { Some(opts) => opts, - None => return Ok(()), + None => return, }; let dcx = @@ -853,11 +851,11 @@ fn main_args( if sess.opts.describe_lints { rustc_driver::describe_lints(sess); - return Ok(()); + return; } compiler.enter(|queries| { - let Ok(mut gcx) = queries.global_ctxt() else { FatalError.raise() }; + let mut gcx = queries.global_ctxt(); if sess.dcx().has_errors().is_some() { sess.dcx().fatal("Compilation failed, aborting rustdoc"); } @@ -865,7 +863,7 @@ fn main_args( gcx.enter(|tcx| { let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || { core::run_global_ctxt(tcx, show_coverage, render_options, output_format) - })?; + }); info!("finished with rustc"); if let Some(options) = scrape_examples_options { @@ -884,10 +882,10 @@ fn main_args( if show_coverage { // if we ran coverage, bail early, we don't need to also generate docs at this point // (also we didn't load in any of the useful passes) - return Ok(()); + return; } else if run_check { // Since we're in "check" mode, no need to generate anything beyond this point. - return Ok(()); + return; } info!("going to format"); diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 20d65d8cd9f0..d9c277c047f2 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -2,6 +2,7 @@ use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::emitter::Emitter; +use rustc_errors::registry::Registry; use rustc_errors::translation::{Translate, to_fluent_args}; use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle}; use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; @@ -155,7 +156,7 @@ impl Translate for BufferEmitter { } impl Emitter for BufferEmitter { - fn emit_diagnostic(&mut self, diag: DiagInner) { + fn emit_diagnostic(&mut self, diag: DiagInner, _registry: &Registry) { let mut buffer = self.buffer.borrow_mut(); let fluent_args = to_fluent_args(diag.args.iter()); diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 980a9f7a47cd..599671bd4d48 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::DiagCtxtHandle; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir}; -use rustc_interface::interface; use rustc_macros::{Decodable, Encodable}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; @@ -275,7 +274,7 @@ pub(crate) fn run( tcx: TyCtxt<'_>, options: ScrapeExamplesOptions, bin_crate: bool, -) -> interface::Result<()> { +) { let inner = move || -> Result<(), String> { // Generates source files for examples renderopts.no_emit_shared = true; @@ -329,8 +328,6 @@ pub(crate) fn run( if let Err(e) = inner() { tcx.dcx().fatal(e); } - - Ok(()) } // Note: the DiagCtxt must be passed in explicitly because sess isn't available while parsing diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 9d26bf930a1a..50a97579df77 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -234,7 +234,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // In the case of only two patterns, replacement adds net characters. | Ref(_, Mutability::Not) // Dealt with elsewhere. - | Or(_) | Paren(_) | Deref(_) => false, + | Or(_) | Paren(_) | Deref(_) | Guard(..) => false, // Transform `box x | ... | box y` into `box (x | y)`. // // The cases below until `Slice(...)` deal with *singleton* products. diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index c66837dc998f..32ee668cda1c 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -236,7 +236,8 @@ pub fn main() { let mut args: Vec = orig_args.clone(); pass_sysroot_env_if_given(&mut args, sys_root_env); - return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run(); + rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run(); + return Ok(()); } if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -296,12 +297,13 @@ pub fn main() { args.extend(clippy_args); rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }) .set_using_internal_features(using_internal_features) - .run() + .run(); } else { rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }) .set_using_internal_features(using_internal_features) - .run() + .run(); } + return Ok(()); })) } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index bf4a3124075e..a5a166af33b6 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -37,8 +37,8 @@ use walkdir::WalkDir; use self::header::{EarlyProps, make_test_description}; use crate::common::{ - Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, - output_relative_path, + CompareMode, Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, + output_base_dir, output_relative_path, }; use crate::header::HeadersCache; use crate::util::logv; @@ -273,6 +273,15 @@ pub fn parse_config(args: Vec) -> Config { } else { matches.free.clone() }; + let compare_mode = matches.opt_str("compare-mode").map(|s| { + s.parse().unwrap_or_else(|_| { + let variants: Vec<_> = CompareMode::STR_VARIANTS.iter().copied().collect(); + panic!( + "`{s}` is not a valid value for `--compare-mode`, it should be one of: {}", + variants.join(", ") + ); + }) + }); Config { bless: matches.opt_present("bless"), compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), @@ -342,9 +351,7 @@ pub fn parse_config(args: Vec) -> Config { only_modified: matches.opt_present("only-modified"), color, remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from), - compare_mode: matches - .opt_str("compare-mode") - .map(|s| s.parse().expect("invalid --compare-mode provided")), + compare_mode, rustfix_coverage: matches.opt_present("rustfix-coverage"), has_html_tidy, has_enzyme, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 84269fd44a1e..7b11bf3b1219 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -22,7 +22,7 @@ use crate::common::{ UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir, output_base_dir, output_base_name, output_testname_unique, }; -use crate::compute_diff::{write_diff, write_filtered_diff}; +use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; @@ -2295,17 +2295,31 @@ impl<'test> TestCx<'test> { match output_kind { TestOutput::Compile => { if !self.props.dont_check_compiler_stdout { - errors += - self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output( + stdout_kind, + &normalized_stdout, + &proc_res.stdout, + &expected_stdout, + ); } if !self.props.dont_check_compiler_stderr { - errors += - self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + errors += self.compare_output( + stderr_kind, + &normalized_stderr, + &stderr, + &expected_stderr, + ); } } TestOutput::Run => { - errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); - errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + errors += self.compare_output( + stdout_kind, + &normalized_stdout, + &proc_res.stdout, + &expected_stdout, + ); + errors += + self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr); } } errors @@ -2533,7 +2547,13 @@ impl<'test> TestCx<'test> { } } - fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize { + fn compare_output( + &self, + stream: &str, + actual: &str, + actual_unnormalized: &str, + expected: &str, + ) -> usize { let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) { // FIXME: We ignore the first line of SVG files // because the width parameter is non-deterministic. @@ -2590,28 +2610,14 @@ impl<'test> TestCx<'test> { if expected.is_empty() { println!("normalized {}:\n{}\n", stream, actual); } else { - println!("diff of {stream}:\n"); - if let Some(diff_command) = self.config.diff_command.as_deref() { - let mut args = diff_command.split_whitespace(); - let name = args.next().unwrap(); - match Command::new(name) - .args(args) - .args([&expected_path, &actual_path]) - .output() - { - Err(err) => { - self.fatal(&format!( - "failed to call custom diff command `{diff_command}`: {err}" - )); - } - Ok(output) => { - let output = String::from_utf8_lossy(&output.stdout); - print!("{output}"); - } - } - } else { - print!("{}", write_diff(expected, actual, 3)); - } + self.show_diff( + stream, + &expected_path, + &actual_path, + expected, + actual, + actual_unnormalized, + ); } } else { // Delete non-revision .stderr/.stdout file if revisions are used. @@ -2633,6 +2639,76 @@ impl<'test> TestCx<'test> { if self.config.bless { 0 } else { 1 } } + /// Returns whether to show the full stderr/stdout. + fn show_diff( + &self, + stream: &str, + expected_path: &Path, + actual_path: &Path, + expected: &str, + actual: &str, + actual_unnormalized: &str, + ) { + eprintln!("diff of {stream}:\n"); + if let Some(diff_command) = self.config.diff_command.as_deref() { + let mut args = diff_command.split_whitespace(); + let name = args.next().unwrap(); + match Command::new(name).args(args).args([expected_path, actual_path]).output() { + Err(err) => { + self.fatal(&format!( + "failed to call custom diff command `{diff_command}`: {err}" + )); + } + Ok(output) => { + let output = String::from_utf8_lossy(&output.stdout); + eprint!("{output}"); + } + } + } else { + eprint!("{}", write_diff(expected, actual, 3)); + } + + // NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below. + let diff_results = make_diff(actual, expected, 0); + + let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]); + for hunk in diff_results { + let mut line_no = hunk.line_number; + for line in hunk.lines { + // NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up + if let DiffLine::Expected(normalized) = line { + mismatches_normalized += &normalized; + mismatches_normalized += "\n"; + mismatch_line_nos.push(line_no); + line_no += 1; + } + } + } + let mut mismatches_unnormalized = String::new(); + let diff_normalized = make_diff(actual, actual_unnormalized, 0); + for hunk in diff_normalized { + if mismatch_line_nos.contains(&hunk.line_number) { + for line in hunk.lines { + if let DiffLine::Resulting(unnormalized) = line { + mismatches_unnormalized += &unnormalized; + mismatches_unnormalized += "\n"; + } + } + } + } + + let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0); + // HACK: instead of checking if each hunk is empty, this only checks if the whole input is empty. we should be smarter about this so we don't treat added or removed output as normalized. + if !normalized_diff.is_empty() + && !mismatches_unnormalized.is_empty() + && !mismatches_normalized.is_empty() + { + eprintln!("Note: some mismatched output was normalized before being compared"); + // FIXME: respect diff_command + eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0)); + } + } + fn check_and_prune_duplicate_outputs( &self, proc_res: &ProcRes, diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index 961a16029863..030ca5ebb247 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -39,8 +39,12 @@ impl<'test> TestCx<'test> { let expected_coverage_dump = self.load_expected_output(kind); let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]); - let coverage_dump_errors = - self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump); + let coverage_dump_errors = self.compare_output( + kind, + &actual_coverage_dump, + &proc_res.stdout, + &expected_coverage_dump, + ); if coverage_dump_errors > 0 { self.fatal_proc_rec( @@ -135,8 +139,12 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec(&err, &proc_res); }); - let coverage_errors = - self.compare_output(kind, &normalized_actual_coverage, &expected_coverage); + let coverage_errors = self.compare_output( + kind, + &normalized_actual_coverage, + &proc_res.stdout, + &expected_coverage, + ); if coverage_errors > 0 { self.fatal_proc_rec( diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index bb747c680292..172b1e32aad3 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -100,7 +100,7 @@ impl TestCx<'_> { ) }); - errors += self.compare_output("fixed", &fixed_code, &expected_fixed); + errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed); } else if !expected_fixed.is_empty() { panic!( "the `//@ run-rustfix` directive wasn't found but a `*.fixed` \ diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 57d0b27dfd3b..50710f55266e 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -728f2daab42ba8f1b3d5caab62495798d1eabfa1 +1b3fb316751227d30b1523ed0e3f00d83956d4d0 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 2c4b02e28737..5248c9d186b4 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -290,7 +290,8 @@ fn run_compiler( let exit_code = rustc_driver::catch_with_exit_code(move || { rustc_driver::RunCompiler::new(&args, callbacks) .set_using_internal_features(using_internal_features) - .run() + .run(); + Ok(()) }); std::process::exit(exit_code) } diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 54ad56ed3f35..63cc8794ceae 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; +use rustc_errors::registry::Registry; use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; @@ -38,10 +39,10 @@ struct SilentOnIgnoredFilesEmitter { } impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, diag: DiagInner) { + fn handle_non_ignoreable_error(&mut self, diag: DiagInner, registry: &Registry) { self.has_non_ignorable_parser_errors = true; self.can_reset.store(false, Ordering::Release); - self.emitter.emit_diagnostic(diag); + self.emitter.emit_diagnostic(diag, registry); } } @@ -60,9 +61,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter { None } - fn emit_diagnostic(&mut self, diag: DiagInner) { + fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry) { if diag.level() == DiagnosticLevel::Fatal { - return self.handle_non_ignoreable_error(diag); + return self.handle_non_ignoreable_error(diag, registry); } if let Some(primary_span) = &diag.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); @@ -80,7 +81,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } }; } - self.handle_non_ignoreable_error(diag); + self.handle_non_ignoreable_error(diag, registry); } } @@ -358,7 +359,7 @@ mod tests { None } - fn emit_diagnostic(&mut self, _diag: DiagInner) { + fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -412,6 +413,7 @@ mod tests { SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); + let registry = Registry::new(&[]); let mut emitter = build_emitter( Lrc::clone(&num_emitted_errors), Lrc::clone(&can_reset_errors), @@ -420,7 +422,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(fatal_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic, ®istry); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -437,6 +439,7 @@ mod tests { SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); + let registry = Registry::new(&[]); let mut emitter = build_emitter( Lrc::clone(&num_emitted_errors), Lrc::clone(&can_reset_errors), @@ -445,7 +448,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic, ®istry); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } @@ -461,6 +464,7 @@ mod tests { SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); + let registry = Registry::new(&[]); let mut emitter = build_emitter( Lrc::clone(&num_emitted_errors), Lrc::clone(&can_reset_errors), @@ -469,7 +473,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic, ®istry); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -497,6 +501,7 @@ mod tests { SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("fatal.rs"))), fatal_source, ); + let registry = Registry::new(&[]); let mut emitter = build_emitter( Lrc::clone(&num_emitted_errors), Lrc::clone(&can_reset_errors), @@ -508,9 +513,9 @@ mod tests { let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(bar_diagnostic); - emitter.emit_diagnostic(foo_diagnostic); - emitter.emit_diagnostic(fatal_diagnostic); + emitter.emit_diagnostic(bar_diagnostic, ®istry); + emitter.emit_diagnostic(foo_diagnostic, ®istry); + emitter.emit_diagnostic(fatal_diagnostic, ®istry); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 6fe2d4a8520e..7b4730eadc85 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -48,7 +48,8 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { | ast::PatKind::MacCall(..) | ast::PatKind::Slice(..) | ast::PatKind::Path(..) - | ast::PatKind::Range(..) => false, + | ast::PatKind::Range(..) + | ast::PatKind::Guard(..) => false, ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1, ast::PatKind::TupleStruct(_, ref path, ref subpats) => { path.segments.len() <= 1 && subpats.len() <= 1 @@ -338,8 +339,9 @@ impl Rewrite for Pat { .max_width_error(shape.width, self.span)?, ) .map(|inner_pat| format!("({})", inner_pat)), - PatKind::Err(_) => Err(RewriteError::Unknown), + PatKind::Guard(..) => Ok(context.snippet(self.span).to_string()), PatKind::Deref(_) => Err(RewriteError::Unknown), + PatKind::Err(_) => Err(RewriteError::Unknown), } } } diff --git a/src/tools/rustfmt/tests/target/guard_patterns.rs b/src/tools/rustfmt/tests/target/guard_patterns.rs new file mode 100644 index 000000000000..2e4667b916cd --- /dev/null +++ b/src/tools/rustfmt/tests/target/guard_patterns.rs @@ -0,0 +1,12 @@ +#![feature(guard_patterns)] + +fn main() { + match user.subscription_plan() { + (Plan::Regular if user.credit() >= 100) | (Plan::Premium if user.credit() >= 80) => { + // Complete the transaction. + } + _ => { + // The user doesn't have enough credit, return an error message. + } + } +} diff --git a/tests/crashes/121363.rs b/tests/crashes/121363.rs index 2a5b6274496f..387963422848 100644 --- a/tests/crashes/121363.rs +++ b/tests/crashes/121363.rs @@ -1,5 +1,5 @@ //@ known-bug: #121363 -//@ compile-flags: -Zmir-opt-level=5 --crate-type lib +//@ compile-flags: -Zmir-enable-passes=+GVN --crate-type lib #![feature(trivial_bounds)] diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs index 105a1c84a656..5f0ae108f8f6 100644 --- a/tests/crashes/128094.rs +++ b/tests/crashes/128094.rs @@ -1,5 +1,5 @@ //@ known-bug: rust-lang/rust#128094 -//@ compile-flags: -Zmir-opt-level=5 --edition=2018 +//@ compile-flags: -Zmir-enable-passes=+GVN --edition=2018 pub enum Request { TestSome(T), diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs index ea70c0565fc3..d82474e18e70 100644 --- a/tests/crashes/129095.rs +++ b/tests/crashes/129095.rs @@ -1,5 +1,5 @@ //@ known-bug: rust-lang/rust#129095 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir pub fn function_with_bytes() -> &'static [u8] { BYTES diff --git a/tests/crashes/129109.rs b/tests/crashes/129109.rs index 8b9ebdf03c77..0db53b98a711 100644 --- a/tests/crashes/129109.rs +++ b/tests/crashes/129109.rs @@ -1,5 +1,5 @@ //@ known-bug: rust-lang/rust#129109 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir extern "C" { pub static mut symbol: [i8]; diff --git a/tests/crashes/130970.rs b/tests/crashes/130970.rs index e1f59c155a56..698c2b478e15 100644 --- a/tests/crashes/130970.rs +++ b/tests/crashes/130970.rs @@ -1,5 +1,5 @@ //@ known-bug: #130970 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir fn main() { extern "C" { diff --git a/tests/crashes/131347.rs b/tests/crashes/131347.rs index 15f367d79e20..08f7d068e25a 100644 --- a/tests/crashes/131347.rs +++ b/tests/crashes/131347.rs @@ -1,5 +1,5 @@ //@ known-bug: #131347 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir struct S; static STUFF: [i8] = [0; S::N]; diff --git a/tests/crashes/131451.rs b/tests/crashes/131451.rs new file mode 100644 index 000000000000..cd5b44bad8a5 --- /dev/null +++ b/tests/crashes/131451.rs @@ -0,0 +1,9 @@ +//@ known-bug: #131451 +//@ needs-rustc-debug-assertions +//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+JumpThreading --crate-type=lib + +pub fn fun(terminate: bool) { + while true {} + + while !terminate {} +} diff --git a/tests/crashes/131507.rs b/tests/crashes/131507.rs index d402fb8afc32..05b5e76bed7d 100644 --- a/tests/crashes/131507.rs +++ b/tests/crashes/131507.rs @@ -1,5 +1,5 @@ //@ known-bug: #131507 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir #![feature(non_lifetime_binders)] fn brick() diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs index 320edad3fde9..c7b5b931fbbe 100644 --- a/tests/incremental/circular-dependencies.rs +++ b/tests/incremental/circular-dependencies.rs @@ -6,10 +6,12 @@ //@ [cfail2] compile-flags: --test --extern aux={{build-base}}/circular-dependencies/auxiliary/libcircular_dependencies_aux.rmeta -L dependency={{build-base}}/circular-dependencies pub struct Foo; -//[cfail2]~^ NOTE `Foo` is defined in the current crate -//[cfail2]~| NOTE `Foo` is defined in the current crate -//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` -//[cfail2]~| NOTE `circular_dependencies::Foo` is defined in crate `circular_dependencies` +//[cfail2]~^ NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +//[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations +//[cfail2]~| NOTE this is the expected type `Foo` +//[cfail2]~| NOTE this is the expected type `circular_dependencies::Foo` +//[cfail2]~| NOTE this is the found type `Foo` +//[cfail2]~| NOTE this is the found type `circular_dependencies::Foo` pub fn consume_foo(_: Foo) {} //[cfail2]~^ NOTE function defined here @@ -24,14 +26,12 @@ fn test() { //[cfail2]~^ ERROR mismatched types [E0308] //[cfail2]~| NOTE expected `circular_dependencies::Foo`, found `Foo` //[cfail2]~| NOTE arguments to this function are incorrect - //[cfail2]~| NOTE `Foo` and `circular_dependencies::Foo` have similar names, but are actually distinct types - //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations //[cfail2]~| NOTE function defined here + //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux` + //[cfail2]~| NOTE one version of crate `circular_dependencies` used here, as a dependency of crate `circular_dependencies_aux` consume_foo(aux::produce_foo()); //[cfail2]~^ ERROR mismatched types [E0308] //[cfail2]~| NOTE expected `Foo`, found `circular_dependencies::Foo` //[cfail2]~| NOTE arguments to this function are incorrect - //[cfail2]~| NOTE `circular_dependencies::Foo` and `Foo` have similar names, but are actually distinct types - //[cfail2]~| NOTE the crate `circular_dependencies` is compiled multiple times, possibly with different configurations } diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr index 36379429530b..7f131153540b 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr @@ -8,7 +8,7 @@ note: there are multiple different versions of crate `foo` in the dependency gra --> foo-current.rs:7:1 | 4 | extern crate foo; - | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate + | ----------------- one version of crate `foo` used here, as a direct dependency of the current crate 5 | 6 | pub struct Struct; | ----------------- this type implements the required trait diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/multiple-dep-versions-1.rs index d81462504dd5..bfeabccf5c14 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-1.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-1.rs @@ -5,8 +5,11 @@ pub trait Trait { fn foo(&self); fn bar(); } +pub trait Trait2 {} impl Trait for Type { fn foo(&self) {} fn bar() {} } pub fn do_something(_: X) {} +pub fn do_something_type(_: Type) {} +pub fn do_something_trait(_: Box) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/multiple-dep-versions-2.rs index 0a566fe2c605..682d1ff64b82 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-2.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-2.rs @@ -5,8 +5,12 @@ pub trait Trait { fn foo(&self); fn bar(); } +pub trait Trait2 {} +impl Trait2 for Type {} impl Trait for Type { fn foo(&self) {} fn bar() {} } pub fn do_something(_: X) {} +pub fn do_something_type(_: Type) {} +pub fn do_something_trait(_: Box) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/multiple-dep-versions-3.rs index f5c4d1baa811..07444511472f 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions-3.rs @@ -2,7 +2,7 @@ #![crate_type = "rlib"] extern crate dependency; -pub use dependency::Type; +pub use dependency::{Trait2, Type, do_something_trait, do_something_type}; pub struct OtherType; impl dependency::Trait for OtherType { fn foo(&self) {} diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs index c68a9e6489f5..3a4a20d38fc8 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.rs +++ b/tests/run-make/crate-loading/multiple-dep-versions.rs @@ -1,11 +1,13 @@ extern crate dep_2_reexport; extern crate dependency; -use dep_2_reexport::{OtherType, Type}; -use dependency::{Trait, do_something}; +use dep_2_reexport::{OtherType, Trait2, Type}; +use dependency::{Trait, do_something, do_something_trait, do_something_type}; fn main() { do_something(Type); Type.foo(); Type::bar(); do_something(OtherType); + do_something_type(Type); + do_something_trait(Box::new(Type) as Box); } diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr index 5888aad8f37b..6e1d6111b581 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions.stderr +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -17,9 +17,9 @@ LL | pub trait Trait { ::: replaced | LL | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` + | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` LL | extern crate dependency; - | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate | ::: replaced | @@ -51,7 +51,7 @@ LL | fn foo(&self); | ::: replaced | -LL | use dependency::{Trait, do_something}; +LL | use dependency::{Trait, do_something, do_something_trait, do_something_type}; | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` | ::: replaced @@ -76,7 +76,7 @@ LL | fn bar(); | ::: replaced | -LL | use dependency::{Trait, do_something}; +LL | use dependency::{Trait, do_something, do_something_trait, do_something_type}; | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` | ::: replaced @@ -101,9 +101,9 @@ LL | pub trait Trait { ::: replaced | LL | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` + | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` LL | extern crate dependency; - | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate | ::: replaced | @@ -121,7 +121,71 @@ note: required by a bound in `do_something` LL | pub fn do_something(_: X) {} | ^^^^^ required by this bound in `do_something` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> replaced + | +LL | do_something_type(Type); + | ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type` + | | + | arguments to this function are incorrect + | +note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same + --> replaced + | +LL | pub struct Type(pub i32); + | ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type` + | + ::: replaced + | +LL | pub struct Type; + | ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type` + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate + = help: you can use `cargo tree` to explore your dependency tree +note: function defined here + --> replaced + | +LL | pub fn do_something_type(_: Type) {} + | ^^^^^^^^^^^^^^^^^ -Some errors have detailed explanations: E0277, E0599. +error[E0308]: mismatched types + --> replaced + | +LL | do_something_trait(Box::new(Type) as Box); + | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2` + | | + | arguments to this function are incorrect + | +note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same + --> replaced + | +LL | pub trait Trait2 {} + | ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2` + | + ::: replaced + | +LL | pub trait Trait2 {} + | ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2` + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` used here, as a direct dependency of the current crate + = help: you can use `cargo tree` to explore your dependency tree +note: function defined here + --> replaced + | +LL | pub fn do_something_trait(_: Box) {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0308, E0599. For more information about an error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.rs b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs new file mode 100644 index 000000000000..65d0745f4944 --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs @@ -0,0 +1,4 @@ +pub fn baz(t: std::ops::Range) { + for _ in t {} +} +fn main() {} diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr new file mode 100644 index 000000000000..7196a1a6fed7 --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `T: Step` is not satisfied + --> missing-bound.rs:2:14 + | +2 | for _ in t {} + | ^ the trait `Step` is not implemented for `T` + | + = note: required for `std::ops::Range` to implement `Iterator` + = note: required for `std::ops::Range` to implement `IntoIterator` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs new file mode 100644 index 000000000000..20f77f7c9aa0 --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -0,0 +1,24 @@ +//@ only-linux +//@ ignore-wasm32 +//@ ignore-wasm64 +// ignore-tidy-linelength + +// Ensure that on stable we don't suggest restricting with an unsafe trait and we continue +// mentioning the rest of the obligation chain. + +use run_make_support::{diff, rust_lib_name, rustc}; + +fn main() { + let out = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .input("missing-bound.rs") + .run_fail() + .assert_stderr_not_contains("help: consider restricting type parameter `T`") + .assert_stderr_contains( + r#" + = note: required for `std::ops::Range` to implement `Iterator` + = note: required for `std::ops::Range` to implement `IntoIterator`"#, + ) + .stderr_utf8(); + diff().expected_file("missing-bound.stderr").actual_text("(stable rustc)", &out).run() +} diff --git a/tests/rustdoc-ui/issues/issue-96287.stderr b/tests/rustdoc-ui/issues/issue-96287.stderr index 9aba03321648..40dc1cc0e704 100644 --- a/tests/rustdoc-ui/issues/issue-96287.stderr +++ b/tests/rustdoc-ui/issues/issue-96287.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V` LL | pub type Foo = impl Trait; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | pub type Foo = impl Trait; | ++++++++++++++++ @@ -16,7 +16,7 @@ LL | pub type Foo = impl Trait; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | pub type Foo = impl Trait; | ++++++++++++++++ diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr index d87e769b5053..045516d7d2ff 100644 --- a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied LL | pub struct Structure { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C` | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `Bar` | LL | pub struct Structure> { | ++++++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied LL | _field: C::BarType, | ^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C` | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `Bar` | LL | pub struct Structure> { | ++++++++ diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index f273bbc99a8a..656cfca1ed1d 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -15,16 +15,16 @@ extern crate rustc_span; extern crate rustc_symbol_mangling; extern crate rustc_target; +use std::any::Any; + use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenResults, CrateInfo}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; -use rustc_session::config::OutputFilenames; use rustc_session::Session; -use std::any::Any; +use rustc_session::config::OutputFilenames; struct TheBackend; @@ -60,17 +60,12 @@ impl CodegenBackend for TheBackend { (*codegen_results, FxIndexMap::default()) } - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { - use rustc_session::{ - config::{CrateType, OutFileName}, - output::out_filename, - }; + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { use std::io::Write; + + use rustc_session::config::{CrateType, OutFileName}; + use rustc_session::output::out_filename; + let crate_name = codegen_results.crate_info.local_crate_name; for &crate_type in sess.opts.crate_types.iter() { if crate_type != CrateType::Rlib { @@ -88,7 +83,6 @@ impl CodegenBackend for TheBackend { } } } - Ok(()) } } diff --git a/tests/ui-fulldeps/compiler-calls.rs b/tests/ui-fulldeps/compiler-calls.rs index f6c10add2906..5fb47c87e501 100644 --- a/tests/ui-fulldeps/compiler-calls.rs +++ b/tests/ui-fulldeps/compiler-calls.rs @@ -12,7 +12,7 @@ extern crate rustc_interface; use rustc_interface::interface; struct TestCalls<'a> { - count: &'a mut u32 + count: &'a mut u32, } impl rustc_driver::Callbacks for TestCalls<'_> { @@ -24,8 +24,9 @@ impl rustc_driver::Callbacks for TestCalls<'_> { fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::catch_fatal_errors(|| { - rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run().ok(); + rustc_driver::catch_fatal_errors(|| -> interface::Result<()> { + rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run(); + Ok(()) }) .ok(); assert_eq!(count, 2); diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index af98f93297b6..8ea2ac619719 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -47,7 +47,8 @@ fn main() { rustc_args.push("-Zpolonius".to_owned()); let mut callbacks = CompilerCalls::default(); // Call the Rust compiler with our callbacks. - rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run() + rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run(); + Ok(()) }); std::process::exit(exit_code); } diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index cce4eac0d7c1..d4c9fd019b0f 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -17,8 +17,7 @@ extern crate rustc_span; use std::path::{Path, PathBuf}; -use rustc_interface::Linker; -use rustc_interface::interface; +use rustc_interface::{Linker, interface}; use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes}; use rustc_span::FileName; @@ -79,11 +78,11 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path interface::run_compiler(config, |compiler| { let linker = compiler.enter(|queries| { - queries.global_ctxt()?.enter(|tcx| { - tcx.analysis(())?; + queries.global_ctxt().enter(|tcx| { + let _ = tcx.analysis(()); Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend) }) }); - linker.unwrap().link(&compiler.sess, &*compiler.codegen_backend).unwrap(); + linker.link(&compiler.sess, &*compiler.codegen_backend); }); } diff --git a/tests/ui/assign-imm-local-twice.rs b/tests/ui/assign-imm-local-twice.rs deleted file mode 100644 index b2dfeb564d9f..000000000000 --- a/tests/ui/assign-imm-local-twice.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn test() { - let v: isize; - //~^ HELP consider making this binding mutable - //~| SUGGESTION mut - v = 1; //~ NOTE first assignment - println!("v={}", v); - v = 2; //~ ERROR cannot assign twice to immutable variable - //~| NOTE cannot assign twice to immutable - println!("v={}", v); -} - -fn main() { -} diff --git a/tests/ui/assoc-lang-items.rs b/tests/ui/assoc-lang-items.rs deleted file mode 100644 index 23453d201a72..000000000000 --- a/tests/ui/assoc-lang-items.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(lang_items)] - -trait Foo { - #[lang = "dummy_lang_item_1"] //~ ERROR definition - fn foo() {} - - #[lang = "dummy_lang_item_2"] //~ ERROR definition - fn bar(); - - #[lang = "dummy_lang_item_3"] //~ ERROR definition - type MyType; -} - -struct Bar; - -impl Bar { - #[lang = "dummy_lang_item_4"] //~ ERROR definition - fn test() {} -} - -fn main() {} diff --git a/tests/ui/assoc-oddities-3.rs b/tests/ui/assoc-oddities-3.rs deleted file mode 100644 index ffde2ccf7863..000000000000 --- a/tests/ui/assoc-oddities-3.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass - -fn that_odd_parse(c: bool, n: usize) -> u32 { - let x = 2; - let a = [1, 2, 3, 4]; - let b = [5, 6, 7, 7]; - x + if c { a } else { b }[n] -} - -fn main() { - assert_eq!(4, that_odd_parse(true, 1)); - assert_eq!(8, that_odd_parse(false, 1)); -} diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr index 9713051d9732..4f951ee4b4e6 100644 --- a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied LL | fn uhoh(foo: ::Value) {} | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Get` | LL | fn uhoh(foo: ::Value) {} | +++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied LL | fn uhoh(foo: ::Value) {} | ^^ the trait `Get` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Get` | LL | fn uhoh(foo: ::Value) {} | +++++ diff --git a/tests/ui/associated-types/defaults-suitability.current.stderr b/tests/ui/associated-types/defaults-suitability.current.stderr index 9c0ae59ae43b..61247cee1f34 100644 --- a/tests/ui/associated-types/defaults-suitability.current.stderr +++ b/tests/ui/associated-types/defaults-suitability.current.stderr @@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar` | LL | type Bar: Clone = Vec; | ^^^^^ required by this bound in `Foo::Bar` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | trait Foo { | +++++++++++++++++++ @@ -132,7 +132,7 @@ LL | Self::Baz: Clone, ... LL | type Baz = T; | --- required by a bound in this associated type -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Clone` | LL | Self::Baz: Clone, T: std::clone::Clone | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/defaults-suitability.next.stderr b/tests/ui/associated-types/defaults-suitability.next.stderr index 9c0ae59ae43b..61247cee1f34 100644 --- a/tests/ui/associated-types/defaults-suitability.next.stderr +++ b/tests/ui/associated-types/defaults-suitability.next.stderr @@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar` | LL | type Bar: Clone = Vec; | ^^^^^ required by this bound in `Foo::Bar` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | trait Foo { | +++++++++++++++++++ @@ -132,7 +132,7 @@ LL | Self::Baz: Clone, ... LL | type Baz = T; | --- required by a bound in this associated type -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Clone` | LL | Self::Baz: Clone, T: std::clone::Clone | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr index 5278bdb7a5cf..b2a86bb7f75e 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied LL | impl X<'_, T> for (S,) { | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `X` | LL | impl X<'b, T>> X<'_, T> for (S,) { | ++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr index 70bf90150b8f..0815bdce16fc 100644 --- a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr +++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -9,7 +9,7 @@ note: required by a bound in `copy` | LL | fn copy(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index 529fc1f119a9..ba4e683194f1 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -14,7 +14,7 @@ note: required by a bound in `Complete::Assoc` | LL | type Assoc: Partial; | ^^^^^^^^^^^^^ required by this bound in `Complete::Assoc` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Complete for T { | +++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index 6c77ee6044f1..ec2890cc8e7f 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -7,7 +7,7 @@ LL | | LL | | Service::OnlyFoo> | |______________________________________________^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService: | +++++ @@ -24,7 +24,7 @@ LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService: | +++++ @@ -38,7 +38,7 @@ LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService: | +++++ @@ -61,7 +61,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied LL | ) -> Self::AssocType; | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService: | +++++ diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 317c04d2c747..8de6a825042b 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -9,7 +9,7 @@ note: captured value is not `Send` | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Send` | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index f4cd7c42706c..6385a8c975e3 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -14,7 +14,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` = note: required for the cast from `Pin>` to `Pin + Send + 'async_trait)>>` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) | +++++++++++++++++++ diff --git a/tests/ui/atomic-from-mut-not-available.rs b/tests/ui/atomic-from-mut-not-available.rs deleted file mode 100644 index 8326187838a2..000000000000 --- a/tests/ui/atomic-from-mut-not-available.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86 -//@ only-linux - -fn main() { - core::sync::atomic::AtomicU64::from_mut(&mut 0u64); - //~^ ERROR: no function or associated item named `from_mut` found for struct `AtomicU64` -} diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 4c1de72798c4..27e38ce06a43 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -30,7 +30,7 @@ LL | fn copy(x: T) -> (T, T) { (x, x) } | ^ - you could clone this value | | | consider constraining this type parameter with `Clone` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn copy(x: T) -> (T, T) { (x, x) } | ++++++ diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr index 1b59216b3c76..d9d92a44766d 100644 --- a/tests/ui/binop/binop-consume-args.stderr +++ b/tests/ui/binop/binop-consume-args.stderr @@ -17,7 +17,7 @@ LL | lhs + rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn add + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -40,7 +40,7 @@ LL | fn add, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs + rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn add, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -64,7 +64,7 @@ LL | lhs - rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn sub + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -87,7 +87,7 @@ LL | fn sub, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs - rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn sub, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -111,7 +111,7 @@ LL | lhs * rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn mul + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -134,7 +134,7 @@ LL | fn mul, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs * rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn mul, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -158,7 +158,7 @@ LL | lhs / rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn div + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -181,7 +181,7 @@ LL | fn div, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs / rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn div, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -205,7 +205,7 @@ LL | lhs % rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn rem + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -228,7 +228,7 @@ LL | fn rem, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs % rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn rem, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -252,7 +252,7 @@ LL | lhs & rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitand + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -275,7 +275,7 @@ LL | fn bitand, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs & rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitand, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -299,7 +299,7 @@ LL | lhs | rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitor + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -322,7 +322,7 @@ LL | fn bitor, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs | rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitor, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -346,7 +346,7 @@ LL | lhs ^ rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitxor + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -369,7 +369,7 @@ LL | fn bitxor, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs ^ rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitxor, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -393,7 +393,7 @@ LL | lhs << rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn shl + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -416,7 +416,7 @@ LL | fn shl, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs << rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn shl, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -440,7 +440,7 @@ LL | lhs >> rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn shr + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -463,7 +463,7 @@ LL | fn shr, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs >> rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn shr, B: Copy>(lhs: A, rhs: B) { | ++++++ diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr index 45c7f1104061..2e661c44abd1 100644 --- a/tests/ui/binop/binop-move-semantics.stderr +++ b/tests/ui/binop/binop-move-semantics.stderr @@ -20,7 +20,7 @@ LL | x | - you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn double_move + Copy>(x: T) { | ++++++ @@ -40,7 +40,7 @@ help: consider cloning the value if the performance cost is acceptable | LL | x.clone() | ++++++++ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn move_then_borrow + Clone + Copy>(x: T) { | ++++++ diff --git a/tests/ui/binop/issue-93927.stderr b/tests/ui/binop/issue-93927.stderr index 9bcf2b17357e..ff5ecf66be63 100644 --- a/tests/ui/binop/issue-93927.stderr +++ b/tests/ui/binop/issue-93927.stderr @@ -6,7 +6,7 @@ LL | val == val | | | MyType | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Eq` | LL | fn cond(val: MyType) -> bool { | ++++++++++++++ diff --git a/tests/ui/borrowck/assign-imm-local-twice.fixed b/tests/ui/borrowck/assign-imm-local-twice.fixed new file mode 100644 index 000000000000..dca994141bb8 --- /dev/null +++ b/tests/ui/borrowck/assign-imm-local-twice.fixed @@ -0,0 +1,21 @@ +//! Check that we do not allow assigning twice to an immutable variable. This test also checks a +//! few pieces of borrowck diagnostics: +//! +//! - A multipart borrowck diagnostics that points out the first assignment to an immutable +//! variable, alongside violating assignments that follow subsequently. +//! - A suggestion diagnostics to make the immutable binding mutable. + +//@ run-rustfix + +fn main() { + let mut v: isize; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut + v = 1; + //~^ NOTE first assignment + println!("v={}", v); + v = 2; + //~^ ERROR cannot assign twice to immutable variable + //~| NOTE cannot assign twice to immutable + println!("v={}", v); +} diff --git a/tests/ui/borrowck/assign-imm-local-twice.rs b/tests/ui/borrowck/assign-imm-local-twice.rs new file mode 100644 index 000000000000..43437fa69fa8 --- /dev/null +++ b/tests/ui/borrowck/assign-imm-local-twice.rs @@ -0,0 +1,21 @@ +//! Check that we do not allow assigning twice to an immutable variable. This test also checks a +//! few pieces of borrowck diagnostics: +//! +//! - A multipart borrowck diagnostics that points out the first assignment to an immutable +//! variable, alongside violating assignments that follow subsequently. +//! - A suggestion diagnostics to make the immutable binding mutable. + +//@ run-rustfix + +fn main() { + let v: isize; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut + v = 1; + //~^ NOTE first assignment + println!("v={}", v); + v = 2; + //~^ ERROR cannot assign twice to immutable variable + //~| NOTE cannot assign twice to immutable + println!("v={}", v); +} diff --git a/tests/ui/assign-imm-local-twice.stderr b/tests/ui/borrowck/assign-imm-local-twice.stderr similarity index 84% rename from tests/ui/assign-imm-local-twice.stderr rename to tests/ui/borrowck/assign-imm-local-twice.stderr index fda3aa3de1b4..0a2138d0b962 100644 --- a/tests/ui/assign-imm-local-twice.stderr +++ b/tests/ui/borrowck/assign-imm-local-twice.stderr @@ -1,9 +1,9 @@ error[E0384]: cannot assign twice to immutable variable `v` - --> $DIR/assign-imm-local-twice.rs:7:5 + --> $DIR/assign-imm-local-twice.rs:17:5 | LL | v = 1; | ----- first assignment to `v` -LL | println!("v={}", v); +... LL | v = 2; | ^^^^^ cannot assign twice to immutable variable | diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index d5d21296a3f9..911c136086cf 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -12,7 +12,7 @@ LL | LL | drop(cloned_items); | ------------ immutable borrow later used here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn foo(list: &mut Vec) { | +++++++ @@ -39,7 +39,7 @@ LL | fn bar(x: T) { | ^ consider constraining this type parameter with `Clone` LL | let a = &x; | - you could clone this value -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn bar(x: T) { | +++++++ diff --git a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr index 6997710ec89f..e32a0c54dfee 100644 --- a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr +++ b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr @@ -15,7 +15,7 @@ LL | fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { ... LL | 6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g, | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { | ++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 592aa4369ce0..9915b772afaf 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send+Sync { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl Foo for (T,) { } | +++++++++++++++++++ @@ -27,7 +27,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send+Sync { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | impl Foo for (T,T) { } | +++++++++++++++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 251651df4f90..39a04186981f 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -14,7 +14,7 @@ note: required by a bound in `RequiresRequiresShareAndSend` | LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { } | ^^^^ required by this bound in `RequiresRequiresShareAndSend` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl RequiresRequiresShareAndSend for X { } | +++++++++++++++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index 4a25c42b5835..dd273b875aeb 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl Foo for T { } | +++++++++++++++++++ diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 8157590bd9e8..9ceee477856d 100644 --- a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -9,7 +9,7 @@ note: required by a bound in `X` | LL | struct X where F: FnOnce() + 'static + Send { | ^^^^ required by this bound in `X` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Send` | LL | fn foo(blk: F) -> X where F: FnOnce() + 'static + std::marker::Send { | +++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `X` | LL | struct X where F: FnOnce() + 'static + Send { | ^^^^ required by this bound in `X` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Send` | LL | fn foo(blk: F) -> X where F: FnOnce() + 'static + std::marker::Send { | +++++++++++++++++++ diff --git a/tests/ui/closures/closure-bounds-subtype.stderr b/tests/ui/closures/closure-bounds-subtype.stderr index 42588668e8a0..34c5e0299a75 100644 --- a/tests/ui/closures/closure-bounds-subtype.stderr +++ b/tests/ui/closures/closure-bounds-subtype.stderr @@ -15,7 +15,7 @@ help: use parentheses to call this type parameter | LL | take_const_owned(f()); | ++ -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Sync` | LL | fn give_owned(f: F) where F: FnOnce() + Send + std::marker::Sync { | +++++++++++++++++++ diff --git a/tests/ui/closures/issue-67123.stderr b/tests/ui/closures/issue-67123.stderr index bdafeaef15fd..7db82845ea5a 100644 --- a/tests/ui/closures/issue-67123.stderr +++ b/tests/ui/closures/issue-67123.stderr @@ -7,7 +7,7 @@ LL | || { t; t; }; | value moved here | = note: move occurs because `t` has type `T`, which does not implement the `Copy` trait -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn foo(t: T) { | ++++++ diff --git a/tests/ui/assign-assign.rs b/tests/ui/codegen/assign-expr-unit-type.rs similarity index 53% rename from tests/ui/assign-assign.rs rename to tests/ui/codegen/assign-expr-unit-type.rs index 002393f5bffb..b4268b5e09a3 100644 --- a/tests/ui/assign-assign.rs +++ b/tests/ui/codegen/assign-expr-unit-type.rs @@ -1,5 +1,11 @@ +//! Regression test for [Using the result of an assignment expression results in an LLVM assert +//! #483][issue-483]. This test checks that assignment expressions produce a unit type, and is +//! properly lowered to LLVM IR such that it does not trigger an LLVM assertion. This test was added +//! *really* early, back in 2011. +//! +//! [issue-483]: https://github.com/rust-lang/rust/issues/483 + //@ run-pass -// Issue 483 - Assignment expressions result in nil fn test_assign() { let mut x: isize; @@ -27,4 +33,7 @@ fn test_assign_op() { assert_eq!(z, ()); } -pub fn main() { test_assign(); test_assign_op(); } +pub fn main() { + test_assign(); + test_assign_op(); +} diff --git a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr index 88de8023f6d7..01b6eaf422ed 100644 --- a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr +++ b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr @@ -41,7 +41,7 @@ note: required by a bound in `W` | LL | struct W(*mut T); | ^^^^^ required by this bound in `W` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | impl Trait for W>> {} | +++++++ diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr index b0864689f740..92a704da8b45 100644 --- a/tests/ui/const-generics/issues/issue-61336-2.stderr +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -7,7 +7,7 @@ LL | [x; { N }] = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g(x: T) -> [T; N] { | +++++++++++++++++++ diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr index 111afbda343f..43e8f5c044a1 100644 --- a/tests/ui/const-generics/issues/issue-61336.stderr +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -7,7 +7,7 @@ LL | [x; N] = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g(x: T) -> [T; N] { | +++++++++++++++++++ diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr index 24572040b910..74ec052f6ecb 100644 --- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr @@ -12,7 +12,7 @@ LL | fn unsatisfied(self) LL | where LL | T: Bar, | ^^^^^^ required by this bound in `Foo::::unsatisfied` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Bar` | LL | impl, const N: usize> Foo { | ++++++++ diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 11e13c3efdd1..bb7ff76b1255 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -212,10 +212,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const Fn<()> + ~const Destruct + ~const Fn(), - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:23:5 @@ -224,10 +220,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const FnMut<()> + ~const Destruct + ~const FnMut(), - | ++++++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:30:5 @@ -236,10 +228,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const FnOnce<()> + ~const FnOnce(), - | +++++++++++++++++ error: aborting due to 25 previous errors diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 2bdec1bf41b7..f40c1871e90b 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -19,10 +19,6 @@ LL | Opt::None => f(), | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn unwrap_or_else T + ~const FnOnce()>(self, f: F) -> T { - | +++++++++++++++++ error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:60 diff --git a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr index 3ef11e2c0bbd..2caa779ffaba 100644 --- a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr +++ b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr @@ -9,7 +9,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe(T); | ^^^^ required by this bound in `DropMe` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy` | ~~~~~~~~~~~~~~~~~~~~~~ @@ -25,7 +25,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe(T); | ^^^^ required by this bound in `DropMe` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy` | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr index 8138b86ddea4..5851731e8346 100644 --- a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr +++ b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr @@ -9,7 +9,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe(T); | ^^^^ required by this bound in `DropMe` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Drop for DropMe | +++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe(T); | ^^^^ required by this bound in `DropMe` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Drop for DropMe | +++++++++++++++++++ diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr index 038f44e8b14f..ab2536cc0c9d 100644 --- a/tests/ui/error-codes/E0229.stderr +++ b/tests/ui/error-codes/E0229.stderr @@ -42,7 +42,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied LL | fn baz(x: &>::A) {} | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I` | -help: consider restricting type parameter `I` +help: consider restricting type parameter `I` with trait `Foo` | LL | fn baz(x: &>::A) {} | +++++ @@ -53,7 +53,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied LL | fn baz(x: &>::A) {} | ^^ the trait `Foo` is not implemented for `I` | -help: consider restricting type parameter `I` +help: consider restricting type parameter `I` with trait `Foo` | LL | fn baz(x: &>::A) {} | +++++ diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 9228a047e878..b221195a7bd5 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -25,7 +25,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -73,7 +73,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `Iterator` | LL | fn example(q: Q) { | +++++++++++++++++++++ @@ -100,7 +100,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `Iterator` | LL | fn example(q: Q) { | +++++++++++++++++++++ @@ -125,7 +125,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -150,7 +150,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -175,7 +175,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -200,7 +200,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -225,7 +225,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -248,7 +248,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -273,7 +273,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -296,7 +296,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -319,7 +319,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -342,7 +342,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -367,7 +367,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -392,7 +392,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index b6a24e12bcc7..90380091c509 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -23,7 +23,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -53,7 +53,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -85,7 +85,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -117,7 +117,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -147,7 +147,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -172,7 +172,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T2` | LL | fn example(q: Q) { | ++++ @@ -204,7 +204,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -236,7 +236,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -261,7 +261,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example(q: Q) { | ++++ @@ -286,7 +286,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example(q: Q) { | ++++ @@ -318,7 +318,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ @@ -343,7 +343,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example(q: Q) { | ++++ @@ -370,7 +370,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example(q: Q) { | ++++ @@ -402,7 +402,7 @@ note: required by a bound in `want` | LL | fn want(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example(q: Q) { | ++++ diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr index 044c1ae2dd42..b5c718ec3814 100644 --- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr @@ -4,6 +4,7 @@ warning: `extern` fn uses type `CStr`, which is not FFI-safe LL | type Foo = extern "C" fn(::std::ffi::CStr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(CStr)` is FFI-unsafe due to `CStr` = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes_definitions)]` on by default @@ -14,6 +15,7 @@ warning: `extern` block uses type `CStr`, which is not FFI-safe LL | fn meh(blah: Foo); | ^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(CStr)` is FFI-unsafe due to `CStr` = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes)]` on by default diff --git a/tests/ui/extern/extern-C-str-arg-ice-80125.stderr b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr index ebd6cec6ecd3..f2ee21c31665 100644 --- a/tests/ui/extern/extern-C-str-arg-ice-80125.stderr +++ b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr @@ -4,6 +4,7 @@ warning: `extern` fn uses type `str`, which is not FFI-safe LL | type ExternCallback = extern "C" fn(*const u8, u32, str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(*const u8, u32, str)` is FFI-unsafe due to `str` = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent = note: `#[warn(improper_ctypes_definitions)]` on by default @@ -14,6 +15,7 @@ warning: `extern` fn uses type `str`, which is not FFI-safe LL | pub extern "C" fn register_something(bind: ExternCallback) -> Struct { | ^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(*const u8, u32, str)` is FFI-unsafe due to `str` = help: consider using `*const u8` and a length instead = note: string slices have no C equivalent diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.rs b/tests/ui/feature-gates/feature-gate-guard-patterns.rs new file mode 100644 index 000000000000..929e8ef3181f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-guard-patterns.rs @@ -0,0 +1,46 @@ +fn match_guards_still_work() { + match 0 { + 0 if guard(0) => {}, + _ => {}, + } +} + +fn other_guards_dont() { + match 0 { + (0 if guard(0)) => {}, + //~^ ERROR unexpected parentheses surrounding `match` arm pattern + _ => {}, + } + + match 0 { + (0 if guard(0)) | 1 => {}, + //~^ ERROR: guard patterns are experimental + _ => {}, + } + + let ((x if guard(x)) | x) = 0; + //~^ ERROR: guard patterns are experimental + //~| ERROR: cannot find value `x` + + if let (x if guard(x)) = 0 {} + //~^ ERROR: guard patterns are experimental + //~| WARN: irrefutable + + while let (x if guard(x)) = 0 {} + //~^ ERROR: guard patterns are experimental + //~| WARN: irrefutable + + #[cfg(FALSE)] + while let (x if guard(x)) = 0 {} + //~^ ERROR: guard patterns are experimental +} + +fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {} +//~^ ERROR: guard patterns are experimental +//~| ERROR: cannot find value `x` + +fn guard(x: T) -> bool { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.stderr b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr new file mode 100644 index 000000000000..0613b5c95a41 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr @@ -0,0 +1,119 @@ +error: unexpected parentheses surrounding `match` arm pattern + --> $DIR/feature-gate-guard-patterns.rs:10:9 + | +LL | (0 if guard(0)) => {}, + | ^ ^ + | +help: remove parentheses surrounding the pattern + | +LL - (0 if guard(0)) => {}, +LL + 0 if guard(0) => {}, + | + +error[E0425]: cannot find value `x` in this scope + --> $DIR/feature-gate-guard-patterns.rs:21:22 + | +LL | let ((x if guard(x)) | x) = 0; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/feature-gate-guard-patterns.rs:38:45 + | +LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {} + | ^ + | +help: the binding `x` is available in a different scope in the same function + --> $DIR/feature-gate-guard-patterns.rs:21:11 + | +LL | let ((x if guard(x)) | x) = 0; + | ^ + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:16:15 + | +LL | (0 if guard(0)) | 1 => {}, + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:21:16 + | +LL | let ((x if guard(x)) | x) = 0; + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:25:18 + | +LL | if let (x if guard(x)) = 0 {} + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:29:21 + | +LL | while let (x if guard(x)) = 0 {} + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:34:21 + | +LL | while let (x if guard(x)) = 0 {} + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +error[E0658]: guard patterns are experimental + --> $DIR/feature-gate-guard-patterns.rs:38:39 + | +LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {} + | ^^^^^^^^ + | + = note: see issue #129967 for more information + = help: add `#![feature(guard_patterns)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider using match arm guards + +warning: irrefutable `if let` pattern + --> $DIR/feature-gate-guard-patterns.rs:25:8 + | +LL | if let (x if guard(x)) = 0 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `while let` pattern + --> $DIR/feature-gate-guard-patterns.rs:29:11 + | +LL | while let (x if guard(x)) = 0 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +error: aborting due to 9 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr index 9a745c099c0e..7dce34650d78 100644 --- a/tests/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr @@ -5,7 +5,7 @@ LL | type Assoc2 = Vec; | ^^^^^^ `T` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Display` | LL | type Assoc2 = Vec; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 261070d1db4b..aa56505dd300 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -41,7 +41,7 @@ LL | trait Foo { LL | type C where Self: Clone; | ^ this trait's associated type doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Foo for Fooy { | +++++++++++++++++++ @@ -66,7 +66,7 @@ LL | trait Foo { LL | fn d() where Self: Clone; | ^ this trait's method doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Foo for Fooy { | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index 55901cf450b6..ac91bdcf3e93 100644 --- a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -9,7 +9,7 @@ note: required by a bound in `UnsafeCopy::Item` | LL | type Item<'a>: Copy; | ^^^^ required by this bound in `UnsafeCopy::Item` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl UnsafeCopy for T { | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 3929e66a25a3..d98071efe831 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr index 662726b89935..cd4c06a8660a 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 34278249e35d..12f9949a0d30 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index dafe1c1d3950..8b23f6095306 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-74824.current.stderr b/tests/ui/generic-associated-types/issue-74824.current.stderr index 231136612a05..3a72db27097f 100644 --- a/tests/ui/generic-associated-types/issue-74824.current.stderr +++ b/tests/ui/generic-associated-types/issue-74824.current.stderr @@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy` | LL | type Copy: Copy = Box; | ^^^^ required by this bound in `UnsafeCopy::Copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | type Copy: Copy = Box; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-74824.next.stderr b/tests/ui/generic-associated-types/issue-74824.next.stderr index 231136612a05..3a72db27097f 100644 --- a/tests/ui/generic-associated-types/issue-74824.next.stderr +++ b/tests/ui/generic-associated-types/issue-74824.next.stderr @@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy` | LL | type Copy: Copy = Box; | ^^^^ required by this bound in `UnsafeCopy::Copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | type Copy: Copy = Box; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 1d7d80d1b076..6e0700639e9c 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -71,7 +71,7 @@ LL | Self(self.0 + rhs.0) | | | B | -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Add` | LL | impl> Add for D { | +++++++++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index cf3e4cc85b91..025fcc5e1702 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -5,7 +5,7 @@ error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `ToUnit` | LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} | ++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr index e10da26665eb..da6013a4af33 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -13,7 +13,7 @@ LL | fn want_bar_for_any_ccx(b: &B) | -------------------- required by a bound in this function LL | where B : for<'ccx> Bar<'ccx> | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Bar` | LL | where B : Qux + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr index e60531a876be..5080d35bdde2 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied LL | callee:: >::Associated>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `SomeTrait` | LL | fn give_me_ice SomeTrait<'a>>() { | +++++++++++++++++++++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied LL | callee:: >::Associated>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `SomeTrait` | LL | fn give_me_ice SomeTrait<'a>>() { | +++++++++++++++++++++++ diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index 38c7a9ea16e6..1ddbd75142f9 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -17,7 +17,7 @@ LL | impl> Callback for F { | ------- ^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ @@ -43,7 +43,7 @@ LL | fn autobatch(self) -> impl Trait ... LL | F: Callback, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `::autobatch` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ @@ -68,7 +68,7 @@ LL | impl> Callback for F { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ @@ -121,7 +121,7 @@ LL | impl> Callback for F { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ @@ -137,7 +137,7 @@ note: required by a bound in `Callback` | LL | trait Callback: MyFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback + MyFn, | +++++++++++ diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 2ccca0b562c0..81759760bf13 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -17,7 +17,7 @@ LL | (S::default(), T::default()) | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Copy` | LL | impl Bar for S { | +++++++++++++++++++ @@ -32,7 +32,7 @@ LL | (S::default(), T::default()) | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn foo() -> Self::E { | +++++++++++++++++++ diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 203fbfc1d2c5..1dd84f10ad86 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -33,10 +33,6 @@ LL | fun(filter_positive()); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) { - | ++++++++++++++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/issues/issue-6738.stderr index 9c25c0fd9a14..f22d6a2e4686 100644 --- a/tests/ui/issues/issue-6738.stderr +++ b/tests/ui/issues/issue-6738.stderr @@ -6,7 +6,7 @@ LL | self.x += v.x; | | | cannot use `+=` on type `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `AddAssign` | LL | impl Foo { | +++++++++++++++++++++ diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index da9a8e5532c3..a0a4ef09216f 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -12,7 +12,7 @@ LL | impl Gettable for S {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S` to `&dyn Gettable` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn f(val: T) { | +++++++++++++++++++ @@ -31,7 +31,7 @@ LL | impl Gettable for S {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S` to `&dyn Gettable` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn f(val: T) { | +++++++++++++++++++ @@ -50,7 +50,7 @@ LL | impl Gettable for S {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S` to `&dyn Gettable` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn g(val: T) { | +++++++++++++++++++ @@ -69,7 +69,7 @@ LL | impl Gettable for S {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S` to `&dyn Gettable` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g(val: T) { | +++++++++++++++++++ diff --git a/tests/ui/lang-items/assoc-lang-items.rs b/tests/ui/lang-items/assoc-lang-items.rs new file mode 100644 index 000000000000..460d3ed23266 --- /dev/null +++ b/tests/ui/lang-items/assoc-lang-items.rs @@ -0,0 +1,35 @@ +//! Check that associated items can be marked as lang items, so that they don't have to be looked up +//! by name or by definition order indirectly. +//! +//! This test is not *quite* high-fidelity: it checks that you can use lang items on associated +//! items by looking at the error message *as a proxy*. That is, the error message is about +//! undefined lang items and not invalid attribute target, indicating that it has reached lang item +//! machinery (which is relying on knowing the implementation detail). However, it's annoying to +//! write a full-fidelity test for this, so I think this is acceptable even though it's not *great*. +//! +//! This was implemented in to help with +//! , which is itself relevant for e.g. `Fn::Output` +//! or `Future::Output` or specific use cases like [Use `T`'s discriminant type in +//! `mem::Discriminant` instead of `u64`](https://github.com/rust-lang/rust/pull/70705). + +#![feature(lang_items)] + +trait Foo { + #[lang = "dummy_lang_item_1"] //~ ERROR definition + fn foo() {} + + #[lang = "dummy_lang_item_2"] //~ ERROR definition + fn bar(); + + #[lang = "dummy_lang_item_3"] //~ ERROR definition + type MyType; +} + +struct Bar; + +impl Bar { + #[lang = "dummy_lang_item_4"] //~ ERROR definition + fn test() {} +} + +fn main() {} diff --git a/tests/ui/assoc-lang-items.stderr b/tests/ui/lang-items/assoc-lang-items.stderr similarity index 86% rename from tests/ui/assoc-lang-items.stderr rename to tests/ui/lang-items/assoc-lang-items.stderr index 59aec8e3fdc6..7e61fea449be 100644 --- a/tests/ui/assoc-lang-items.stderr +++ b/tests/ui/lang-items/assoc-lang-items.stderr @@ -1,23 +1,23 @@ error[E0522]: definition of an unknown lang item: `dummy_lang_item_1` - --> $DIR/assoc-lang-items.rs:4:5 + --> $DIR/assoc-lang-items.rs:18:5 | LL | #[lang = "dummy_lang_item_1"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_1` error[E0522]: definition of an unknown lang item: `dummy_lang_item_2` - --> $DIR/assoc-lang-items.rs:7:5 + --> $DIR/assoc-lang-items.rs:21:5 | LL | #[lang = "dummy_lang_item_2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_2` error[E0522]: definition of an unknown lang item: `dummy_lang_item_3` - --> $DIR/assoc-lang-items.rs:10:5 + --> $DIR/assoc-lang-items.rs:24:5 | LL | #[lang = "dummy_lang_item_3"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_3` error[E0522]: definition of an unknown lang item: `dummy_lang_item_4` - --> $DIR/assoc-lang-items.rs:17:5 + --> $DIR/assoc-lang-items.rs:31:5 | LL | #[lang = "dummy_lang_item_4"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown lang item `dummy_lang_item_4` diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr index 206a6801065d..3b051ef9a882 100644 --- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr @@ -6,7 +6,7 @@ LL | impl FnOnce for CachedFun | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -19,7 +19,7 @@ LL | impl FnMut for CachedFun | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` | -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -41,7 +41,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` | -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -56,7 +56,7 @@ LL | self.call_mut(a) | note: required by a bound in `call_mut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr index bd8095224a72..d0d4d04e28a3 100644 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr +++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr @@ -4,7 +4,7 @@ error[E0277]: cannot multiply `T` by `T` LL | type Alias = ::Output; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Mul` | LL | type Alias = ::Output; | +++++++++++++++ diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.rs b/tests/ui/lint/extern-C-fnptr-lints-slices.rs index 0c35eb37a489..4e3832ab1b67 100644 --- a/tests/ui/lint/extern-C-fnptr-lints-slices.rs +++ b/tests/ui/lint/extern-C-fnptr-lints-slices.rs @@ -3,7 +3,7 @@ // It's an improper ctype (a slice) arg in an extern "C" fnptr. pub type F = extern "C" fn(&[u8]); -//~^ ERROR: `extern` fn uses type `[u8]`, which is not FFI-safe +//~^ ERROR: `extern` fn uses type `&[u8]`, which is not FFI-safe fn main() {} diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.stderr b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr index d13f93ca96f2..c0923dd96c8c 100644 --- a/tests/ui/lint/extern-C-fnptr-lints-slices.stderr +++ b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr @@ -1,11 +1,12 @@ -error: `extern` fn uses type `[u8]`, which is not FFI-safe +error: `extern` fn uses type `&[u8]`, which is not FFI-safe --> $DIR/extern-C-fnptr-lints-slices.rs:5:14 | LL | pub type F = extern "C" fn(&[u8]); | ^^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = note: the function pointer to `for<'a> extern "C" fn(&'a [u8])` is FFI-unsafe due to `&[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer note: the lint level is defined here --> $DIR/extern-C-fnptr-lints-slices.rs:1:8 | diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr index ef30a406969d..f035cdb213ef 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.stderr +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -4,6 +4,7 @@ error: `extern` block uses type `Qux`, which is not FFI-safe LL | fn lint_me() -> A<()>; | ^^^^^ not FFI-safe | + = note: this reference (`&Qux`) is ABI-compatible with a C pointer, but `Qux` itself does not have a C layout = note: opaque types have no C equivalent note: the lint level is defined here --> $DIR/lint-ctypes-73249-2.rs:2:9 diff --git a/tests/ui/lint/lint-ctypes-94223.stderr b/tests/ui/lint/lint-ctypes-94223.stderr index bd127cf60044..4bebca69b7f3 100644 --- a/tests/ui/lint/lint-ctypes-94223.stderr +++ b/tests/ui/lint/lint-ctypes-94223.stderr @@ -4,7 +4,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | pub fn bad(f: extern "C" fn([u8])) {} | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent note: the lint level is defined here --> $DIR/lint-ctypes-94223.rs:2:9 @@ -18,7 +19,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | pub fn bad_twice(f: Result) {} | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `[u8]`, which is not FFI-safe @@ -27,7 +29,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | pub fn bad_twice(f: Result) {} | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `[u8]`, which is not FFI-safe @@ -36,7 +39,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | struct BadStruct(extern "C" fn([u8])); | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `[u8]`, which is not FFI-safe @@ -45,7 +49,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | A(extern "C" fn([u8])), | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `[u8]`, which is not FFI-safe @@ -54,7 +59,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | A(extern "C" fn([u8])), | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `[u8]`, which is not FFI-safe @@ -63,7 +69,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe LL | type Foo = extern "C" fn([u8]); | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead + = note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]` + = help: consider using a raw pointer to the slice's first element (and a length) instead = note: slices have no C equivalent error: `extern` fn uses type `Option<&::FooType>`, which is not FFI-safe @@ -72,6 +79,7 @@ error: `extern` fn uses type `Option<&::FooType>`, which is not F LL | pub type Foo2 = extern "C" fn(Option<&::FooType>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `for<'a> extern "C" fn(Option<&'a ::FooType>)` is FFI-unsafe due to `Option<&::FooType>` = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint @@ -81,6 +89,7 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe LL | pub static BAD: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe` = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here @@ -95,6 +104,7 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe` = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here @@ -109,6 +119,7 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe` = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here @@ -123,6 +134,7 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | + = note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe` = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here diff --git a/tests/ui/lint/lint-ctypes-cstr.rs b/tests/ui/lint/lint-ctypes-cstr.rs index b04decd0bcac..c4de5a44a962 100644 --- a/tests/ui/lint/lint-ctypes-cstr.rs +++ b/tests/ui/lint/lint-ctypes-cstr.rs @@ -8,7 +8,7 @@ extern "C" { //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` fn take_cstr_ref(s: &CStr); - //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~^ ERROR `extern` block uses type `&CStr`, which is not FFI-safe //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` fn take_cstring(s: CString); //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe @@ -27,7 +27,7 @@ extern "C" { } extern "C" fn rust_take_cstr_ref(s: &CStr) {} -//~^ ERROR `extern` fn uses type `CStr`, which is not FFI-safe +//~^ ERROR `extern` fn uses type `&CStr`, which is not FFI-safe //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` extern "C" fn rust_take_cstring(s: CString) {} //~^ ERROR `extern` fn uses type `CString`, which is not FFI-safe diff --git a/tests/ui/lint/lint-ctypes-cstr.stderr b/tests/ui/lint/lint-ctypes-cstr.stderr index 8957758d5773..da15b748f211 100644 --- a/tests/ui/lint/lint-ctypes-cstr.stderr +++ b/tests/ui/lint/lint-ctypes-cstr.stderr @@ -12,14 +12,14 @@ note: the lint level is defined here LL | #![deny(improper_ctypes, improper_ctypes_definitions)] | ^^^^^^^^^^^^^^^ -error: `extern` block uses type `CStr`, which is not FFI-safe +error: `extern` block uses type `&CStr`, which is not FFI-safe --> $DIR/lint-ctypes-cstr.rs:10:25 | LL | fn take_cstr_ref(s: &CStr); | ^^^^^ not FFI-safe | = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` - = note: `CStr`/`CString` do not have a guaranteed layout + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` block uses type `CString`, which is not FFI-safe --> $DIR/lint-ctypes-cstr.rs:13:24 @@ -36,6 +36,7 @@ error: `extern` block uses type `CString`, which is not FFI-safe LL | fn take_cstring_ref(s: &CString); | ^^^^^^^^ not FFI-safe | + = note: this reference (`&CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` = note: `CStr`/`CString` do not have a guaranteed layout @@ -45,6 +46,7 @@ error: `extern` block uses type `CString`, which is not FFI-safe LL | fn no_special_help_for_mut_cstring(s: *mut CString); | ^^^^^^^^^^^^ not FFI-safe | + = note: this reference (`*mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout @@ -54,17 +56,18 @@ error: `extern` block uses type `CString`, which is not FFI-safe LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString); | ^^^^^^^^^^^^ not FFI-safe | + = note: this reference (`&mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout -error: `extern` fn uses type `CStr`, which is not FFI-safe +error: `extern` fn uses type `&CStr`, which is not FFI-safe --> $DIR/lint-ctypes-cstr.rs:29:37 | LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {} | ^^^^^ not FFI-safe | = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` - = note: `CStr`/`CString` do not have a guaranteed layout + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer note: the lint level is defined here --> $DIR/lint-ctypes-cstr.rs:2:26 | diff --git a/tests/ui/lint/lint-ctypes-fn.rs b/tests/ui/lint/lint-ctypes-fn.rs index 73820c86d1a0..e16ff9573fd1 100644 --- a/tests/ui/lint/lint-ctypes-fn.rs +++ b/tests/ui/lint/lint-ctypes-fn.rs @@ -68,10 +68,10 @@ pub extern "C" fn ptr_unit(p: *const ()) { } pub extern "C" fn ptr_tuple(p: *const ((),)) { } pub extern "C" fn slice_type(p: &[u32]) { } -//~^ ERROR: uses type `[u32]` +//~^ ERROR: uses type `&[u32]` pub extern "C" fn str_type(p: &str) { } -//~^ ERROR: uses type `str` +//~^ ERROR: uses type `&str` pub extern "C" fn box_type(p: Box) { } @@ -124,7 +124,7 @@ pub extern "C" fn transparent_i128(p: TransparentI128) { } //~^ ERROR: uses type `i128` pub extern "C" fn transparent_str(p: TransparentStr) { } -//~^ ERROR: uses type `str` +//~^ ERROR: uses type `&str` pub extern "C" fn transparent_fn(p: TransparentBadFn) { } diff --git a/tests/ui/lint/lint-ctypes-fn.stderr b/tests/ui/lint/lint-ctypes-fn.stderr index a62533a4be17..c86c02c80064 100644 --- a/tests/ui/lint/lint-ctypes-fn.stderr +++ b/tests/ui/lint/lint-ctypes-fn.stderr @@ -1,25 +1,25 @@ -error: `extern` fn uses type `[u32]`, which is not FFI-safe +error: `extern` fn uses type `&[u32]`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:70:33 | LL | pub extern "C" fn slice_type(p: &[u32]) { } | ^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider using a raw pointer to the slice's first element (and a length) instead + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer note: the lint level is defined here --> $DIR/lint-ctypes-fn.rs:2:9 | LL | #![deny(improper_ctypes_definitions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `extern` fn uses type `str`, which is not FFI-safe +error: `extern` fn uses type `&str`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:73:31 | LL | pub extern "C" fn str_type(p: &str) { } | ^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead - = note: string slices have no C equivalent + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:80:34 @@ -27,7 +27,8 @@ error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } | ^^^^^^^^^ not FFI-safe | - = note: box cannot be represented as a single pointer + = help: consider using a raw pointer to the slice's first element (and a length) instead + = note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` fn uses type `Box`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:83:35 @@ -35,7 +36,8 @@ error: `extern` fn uses type `Box`, which is not FFI-safe LL | pub extern "C" fn boxed_string(p: Box) { } | ^^^^^^^^ not FFI-safe | - = note: box cannot be represented as a single pointer + = help: consider using `*const u8` and a length instead + = note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` fn uses type `Box`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:86:34 @@ -43,7 +45,7 @@ error: `extern` fn uses type `Box`, which is not FFI-safe LL | pub extern "C" fn boxed_trait(p: Box) { } | ^^^^^^^^^^^^^^ not FFI-safe | - = note: box cannot be represented as a single pointer + = note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` fn uses type `char`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:89:32 @@ -149,14 +151,14 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` fn uses type `str`, which is not FFI-safe +error: `extern` fn uses type `&str`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:126:38 | LL | pub extern "C" fn transparent_str(p: TransparentStr) { } | ^^^^^^^^^^^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead - = note: string slices have no C equivalent + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` fn uses type `PhantomData`, which is not FFI-safe --> $DIR/lint-ctypes-fn.rs:172:43 diff --git a/tests/ui/lint/lint-ctypes.rs b/tests/ui/lint/lint-ctypes.rs index dae07930aba6..8c516ab8428b 100644 --- a/tests/ui/lint/lint-ctypes.rs +++ b/tests/ui/lint/lint-ctypes.rs @@ -1,4 +1,5 @@ #![feature(rustc_private)] +#![feature(extern_types)] #![allow(private_interfaces)] #![deny(improper_ctypes)] @@ -6,7 +7,9 @@ use std::cell::UnsafeCell; use std::marker::PhantomData; use std::ffi::{c_int, c_uint}; +use std::fmt::Debug; +unsafe extern "C" {type UnsizedOpaque;} trait Bar { } trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } @@ -20,7 +23,7 @@ pub type I32Pair = (i32, i32); #[repr(C)] pub struct ZeroSize; pub type RustFn = fn(); -pub type RustBadRet = extern "C" fn() -> Box; +pub type RustBoxRet = extern "C" fn() -> Box; pub type CVoidRet = (); pub struct Foo; #[repr(transparent)] @@ -28,7 +31,7 @@ pub struct TransparentI128(i128); #[repr(transparent)] pub struct TransparentStr(&'static str); #[repr(transparent)] -pub struct TransparentBadFn(RustBadRet); +pub struct TransparentBoxFn(RustBoxRet); #[repr(transparent)] pub struct TransparentInt(u32); #[repr(transparent)] @@ -39,6 +42,16 @@ pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); pub struct TransparentUnit(f32, PhantomData); #[repr(transparent)] pub struct TransparentCustomZst(i32, ZeroSize); +#[repr(C)] +pub struct UnsizedStructBecauseForeign { + sized: u32, + unszd: UnsizedOpaque, +} +#[repr(C)] +pub struct UnsizedStructBecauseDyn { + sized: u32, + unszd: dyn Debug, +} #[repr(C)] pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); @@ -48,15 +61,14 @@ extern "C" { pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo` pub fn ptr_unit(p: *const ()); pub fn ptr_tuple(p: *const ((),)); //~ ERROR: uses type `((),)` - pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]` - pub fn str_type(p: &str); //~ ERROR: uses type `str` - pub fn box_type(p: Box); //~ ERROR uses type `Box` + pub fn slice_type(p: &[u32]); //~ ERROR: uses type `&[u32]` + pub fn str_type(p: &str); //~ ERROR: uses type `&str` + pub fn box_type(p: Box); pub fn opt_box_type(p: Option>); - //~^ ERROR uses type `Option>` pub fn char_type(p: char); //~ ERROR uses type `char` pub fn i128_type(p: i128); //~ ERROR uses type `i128` pub fn u128_type(p: u128); //~ ERROR uses type `u128` - pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar` + pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `&dyn Bar` pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` @@ -66,12 +78,15 @@ extern "C" { -> ::std::marker::PhantomData; //~ ERROR uses type `PhantomData` pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()` pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()` - pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `Box` + pub fn fn_contained(p: RustBoxRet); pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128` - pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str` - pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box` + pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `&str` + pub fn transparent_fn(p: TransparentBoxFn); pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]` + pub fn struct_unsized_ptr_no_metadata(p: &UnsizedStructBecauseForeign); + pub fn struct_unsized_ptr_has_metadata(p: &UnsizedStructBecauseDyn); //~ ERROR uses type `&UnsizedStructBecauseDyn` + pub fn no_niche_a(a: Option>); //~^ ERROR: uses type `Option>` pub fn no_niche_b(b: Option>); diff --git a/tests/ui/lint/lint-ctypes.stderr b/tests/ui/lint/lint-ctypes.stderr index 2c81c7b8e4b6..8580a10b2153 100644 --- a/tests/ui/lint/lint-ctypes.stderr +++ b/tests/ui/lint/lint-ctypes.stderr @@ -1,83 +1,68 @@ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:47:28 + --> $DIR/lint-ctypes.rs:60:28 | LL | pub fn ptr_type1(size: *const Foo); | ^^^^^^^^^^ not FFI-safe | + = note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:25:1 + --> $DIR/lint-ctypes.rs:28:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/lint-ctypes.rs:4:9 + --> $DIR/lint-ctypes.rs:5:9 | LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:48:28 + --> $DIR/lint-ctypes.rs:61:28 | LL | pub fn ptr_type2(size: *const Foo); | ^^^^^^^^^^ not FFI-safe | + = note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:25:1 + --> $DIR/lint-ctypes.rs:28:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^ error: `extern` block uses type `((),)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:50:25 + --> $DIR/lint-ctypes.rs:63:25 | LL | pub fn ptr_tuple(p: *const ((),)); | ^^^^^^^^^^^^ not FFI-safe | + = note: this reference (`*const ((),)`) is ABI-compatible with a C pointer, but `((),)` itself does not have a C layout = help: consider using a struct instead = note: tuples have unspecified layout -error: `extern` block uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:51:26 +error: `extern` block uses type `&[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:64:26 | LL | pub fn slice_type(p: &[u32]); | ^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider using a raw pointer to the slice's first element (and a length) instead + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer -error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:52:24 +error: `extern` block uses type `&str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:65:24 | LL | pub fn str_type(p: &str); | ^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead - = note: string slices have no C equivalent - -error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:53:24 - | -LL | pub fn box_type(p: Box); - | ^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - = note: this struct has unspecified layout - -error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:54:28 - | -LL | pub fn opt_box_type(p: Option>); - | ^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - = note: enum has no representation hint + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` block uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:56:25 + --> $DIR/lint-ctypes.rs:68:25 | LL | pub fn char_type(p: char); | ^^^^ not FFI-safe @@ -86,7 +71,7 @@ LL | pub fn char_type(p: char); = note: the `char` type has no C equivalent error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:57:25 + --> $DIR/lint-ctypes.rs:69:25 | LL | pub fn i128_type(p: i128); | ^^^^ not FFI-safe @@ -94,23 +79,23 @@ LL | pub fn i128_type(p: i128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:58:25 + --> $DIR/lint-ctypes.rs:70:25 | LL | pub fn u128_type(p: u128); | ^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `dyn Bar`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:59:26 +error: `extern` block uses type `&dyn Bar`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:71:26 | LL | pub fn trait_type(p: &dyn Bar); | ^^^^^^^^ not FFI-safe | - = note: trait objects have no C equivalent + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:60:26 + --> $DIR/lint-ctypes.rs:72:26 | LL | pub fn tuple_type(p: (i32, i32)); | ^^^^^^^^^^ not FFI-safe @@ -119,7 +104,7 @@ LL | pub fn tuple_type(p: (i32, i32)); = note: tuples have unspecified layout error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:61:27 + --> $DIR/lint-ctypes.rs:73:27 | LL | pub fn tuple_type2(p: I32Pair); | ^^^^^^^ not FFI-safe @@ -128,7 +113,7 @@ LL | pub fn tuple_type2(p: I32Pair); = note: tuples have unspecified layout error: `extern` block uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:62:25 + --> $DIR/lint-ctypes.rs:74:25 | LL | pub fn zero_size(p: ZeroSize); | ^^^^^^^^ not FFI-safe @@ -136,26 +121,26 @@ LL | pub fn zero_size(p: ZeroSize); = help: consider adding a member to this struct = note: this struct has no fields note: the type is defined here - --> $DIR/lint-ctypes.rs:21:1 + --> $DIR/lint-ctypes.rs:24:1 | LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:63:33 + --> $DIR/lint-ctypes.rs:75:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: composed only of `PhantomData` note: the type is defined here - --> $DIR/lint-ctypes.rs:44:1 + --> $DIR/lint-ctypes.rs:57:1 | LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:66:12 + --> $DIR/lint-ctypes.rs:78:12 | LL | -> ::std::marker::PhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -163,7 +148,7 @@ LL | -> ::std::marker::PhantomData; = note: composed only of `PhantomData` error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:67:23 + --> $DIR/lint-ctypes.rs:79:23 | LL | pub fn fn_type(p: RustFn); | ^^^^^^ not FFI-safe @@ -172,7 +157,7 @@ LL | pub fn fn_type(p: RustFn); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:68:24 + --> $DIR/lint-ctypes.rs:80:24 | LL | pub fn fn_type2(p: fn()); | ^^^^ not FFI-safe @@ -180,43 +165,25 @@ LL | pub fn fn_type2(p: fn()); = help: consider using an `extern fn(...) -> ...` function pointer instead = note: this function pointer has Rust-specific calling convention -error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:69:28 - | -LL | pub fn fn_contained(p: RustBadRet); - | ^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - = note: this struct has unspecified layout - error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:70:32 + --> $DIR/lint-ctypes.rs:82:32 | LL | pub fn transparent_i128(p: TransparentI128); | ^^^^^^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:71:31 +error: `extern` block uses type `&str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:83:31 | LL | pub fn transparent_str(p: TransparentStr); | ^^^^^^^^^^^^^^ not FFI-safe | = help: consider using `*const u8` and a length instead - = note: string slices have no C equivalent - -error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:72:30 - | -LL | pub fn transparent_fn(p: TransparentBadFn); - | ^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - = note: this struct has unspecified layout + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer error: `extern` block uses type `[u8; 8]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:73:27 + --> $DIR/lint-ctypes.rs:85:27 | LL | pub fn raw_array(arr: [u8; 8]); | ^^^^^^^ not FFI-safe @@ -224,8 +191,16 @@ LL | pub fn raw_array(arr: [u8; 8]); = help: consider passing a pointer to the array = note: passing raw arrays by value is not FFI-safe +error: `extern` block uses type `&UnsizedStructBecauseDyn`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:88:47 + | +LL | pub fn struct_unsized_ptr_has_metadata(p: &UnsizedStructBecauseDyn); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer + error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:75:26 + --> $DIR/lint-ctypes.rs:90:26 | LL | pub fn no_niche_a(a: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -234,7 +209,7 @@ LL | pub fn no_niche_a(a: Option>); = note: enum has no representation hint error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:77:26 + --> $DIR/lint-ctypes.rs:92:26 | LL | pub fn no_niche_b(b: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -243,7 +218,7 @@ LL | pub fn no_niche_b(b: Option>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:80:34 + --> $DIR/lint-ctypes.rs:95:34 | LL | pub static static_u128_type: u128; | ^^^^ not FFI-safe @@ -251,12 +226,12 @@ LL | pub static static_u128_type: u128; = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:81:40 + --> $DIR/lint-ctypes.rs:96:40 | LL | pub static static_u128_array_type: [u128; 16]; | ^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: aborting due to 27 previous errors +error: aborting due to 24 previous errors diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr index b737c0ab11fd..0e00adf6ea64 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.stderr +++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr @@ -8,7 +8,7 @@ LL | | where LL | | F: for<'a> FnOnce(>::Type), | |___________________________________________________^ the trait `for<'a> Output<'a>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(>::Type) + for<'a> Output<'a>, | ++++++++++++++++++++ @@ -19,7 +19,7 @@ error[E0277]: the trait bound `for<'a> F: Output<'a>` is not satisfied LL | fn do_something_wrapper(self, _: F) | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Output<'a>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(>::Type) + for<'a> Output<'a>, | ++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied LL | F: for<'a> FnOnce(>::Type), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(>::Type) + Output<'_>, | ++++++++++++ @@ -41,7 +41,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied LL | F: for<'a> FnOnce(>::Type), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(>::Type) + Output<'_>, | ++++++++++++ diff --git a/tests/ui/mir/validate/validate-unsize-cast.stderr b/tests/ui/mir/validate/validate-unsize-cast.stderr index cfb47b34e980..8449c6a24bd3 100644 --- a/tests/ui/mir/validate/validate-unsize-cast.stderr +++ b/tests/ui/mir/validate/validate-unsize-cast.stderr @@ -10,7 +10,7 @@ note: required by a bound in `CastTo` | LL | pub trait CastTo: Unsize {} | ^^^^^^^^^ required by this bound in `CastTo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with unstable trait `Unsize` | LL | impl, U: ?Sized> CastTo for T {} | ++++++++++++++++++++++++ diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index 98890a15d98b..a58fe68b8638 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -1,14 +1,22 @@ #![allow(non_camel_case_types)] -struct bool; -struct str; +struct bool; //~ NOTE the other `bool` is defined in the current crate +struct str; //~ NOTE the other `str` is defined in the current crate -fn foo(_: bool) {} -fn bar(_: &str) {} +fn foo(_: bool) {} //~ NOTE function defined here +fn bar(_: &str) {} //~ NOTE function defined here fn main() { foo(true); //~^ ERROR mismatched types [E0308] + //~| NOTE expected `bool`, found a different `bool` + //~| NOTE arguments to this function are incorrect + //~| NOTE `bool` and `bool` have similar names, but are actually distinct types + //~| NOTE one `bool` is a primitive defined by the language bar("hello"); //~^ ERROR mismatched types [E0308] + //~| NOTE expected `str`, found a different `str` + //~| NOTE arguments to this function are incorrect + //~| NOTE `str` and `str` have similar names, but are actually distinct types + //~| NOTE one `str` is a primitive defined by the language } diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index 0530bf5863e6..cf26234dba85 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -6,9 +6,9 @@ LL | foo(true); | | | arguments to this function are incorrect | - = note: bool and `bool` have similar names, but are actually distinct types - = note: bool is a primitive defined by the language -note: `bool` is defined in the current crate + = note: `bool` and `bool` have similar names, but are actually distinct types + = note: one `bool` is a primitive defined by the language +note: the other `bool` is defined in the current crate --> $DIR/similar_paths_primitive.rs:3:1 | LL | struct bool; @@ -20,16 +20,16 @@ LL | fn foo(_: bool) {} | ^^^ ------- error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:12:9 + --> $DIR/similar_paths_primitive.rs:16:9 | LL | bar("hello"); | --- ^^^^^^^ expected `str`, found a different `str` | | | arguments to this function are incorrect | - = note: str and `str` have similar names, but are actually distinct types - = note: str is a primitive defined by the language -note: `str` is defined in the current crate + = note: `str` and `str` have similar names, but are actually distinct types + = note: one `str` is a primitive defined by the language +note: the other `str` is defined in the current crate --> $DIR/similar_paths_primitive.rs:4:1 | LL | struct str; diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr index b3089cecfbb2..80b003bbcc56 100644 --- a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr @@ -6,7 +6,7 @@ LL | let _ = s == t; | | | &[T] | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `PartialEq` | LL | pub fn foo(s: &[T], t: &[T]) { | +++++++++++++++++++++ diff --git a/tests/ui/moves/issue-34721.stderr b/tests/ui/moves/issue-34721.stderr index 94780a04c1f2..9834d009d222 100644 --- a/tests/ui/moves/issue-34721.stderr +++ b/tests/ui/moves/issue-34721.stderr @@ -18,7 +18,7 @@ note: `Foo::zero` takes ownership of the receiver `self`, which moves `x` | LL | fn zero(self) -> Self; | ^^^^ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | pub fn baz(x: T) -> T { | ++++++ diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed index bfb855c7fb1f..a5e0dd819b46 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -48,7 +48,7 @@ fn duplicate_custom_1(t: S) -> (S, S) where { fn duplicate_custom_2(t: S) -> (S, S) where T: A + Copy + Trait, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting { (t, t) //~ use of moved value: `t` } @@ -56,14 +56,14 @@ where fn duplicate_custom_3(t: S) -> (S, S) where T: A + Copy + Trait, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting T: B, { (t, t) //~ use of moved value: `t` } fn duplicate_custom_4(t: S) -> (S, S) -//~^ HELP consider further restricting this bound +//~^ HELP consider further restricting where T: B, { diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs index fbe5a1d74c37..60ca03ed6984 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -48,7 +48,7 @@ fn duplicate_custom_1(t: S) -> (S, S) where { fn duplicate_custom_2(t: S) -> (S, S) where T: A, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting { (t, t) //~ use of moved value: `t` } @@ -56,14 +56,14 @@ where fn duplicate_custom_3(t: S) -> (S, S) where T: A, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting T: B, { (t, t) //~ use of moved value: `t` } fn duplicate_custom_4(t: S) -> (S, S) -//~^ HELP consider further restricting this bound +//~^ HELP consider further restricting where T: B, { diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr index c03204c7b9f1..784945dbbaea 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -17,7 +17,7 @@ LL | fn duplicate_t(t: T) -> (T, T) { ... LL | (t, t) | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_t(t: T) -> (T, T) { | ++++++ @@ -33,7 +33,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_opt(t: Option) -> (Option, Option) { | ++++++ @@ -49,7 +49,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { | ++++++ @@ -81,7 +81,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom(t: S) -> (S, S) { | ++++++++++++++ @@ -97,7 +97,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom_1(t: S) -> (S, S) where { | ++++++++++++++ @@ -113,7 +113,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | T: A + Copy + Trait, | ++++++++++++++ @@ -129,7 +129,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | T: A + Copy + Trait, | ++++++++++++++ @@ -145,7 +145,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom_4(t: S) -> (S, S) | ++++++++++++++ @@ -169,7 +169,7 @@ LL | fn existing_colon(t: T) { ... LL | [t, t]; | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn existing_colon(t: T) { | ++++ @@ -193,7 +193,7 @@ LL | fn existing_colon_in_where(t: T) ... LL | [t, t]; | - you could clone this value -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | T:, T: Copy | ~~~~~~~~~ diff --git a/tests/ui/parser/assoc/assoc-oddities-3.rs b/tests/ui/parser/assoc/assoc-oddities-3.rs new file mode 100644 index 000000000000..1a41c4be0237 --- /dev/null +++ b/tests/ui/parser/assoc/assoc-oddities-3.rs @@ -0,0 +1,41 @@ +//! Check that braces has the expected precedence in relation to index op and some arithmetic +//! bin-ops involving nested braces. +//! +//! This is a regression test for [Wrapping expr in curly braces changes the operator precedence +//! #28777](https://github.com/rust-lang/rust/issues/28777), which was fixed by +//! . + +//@ run-pass + +fn that_odd_parse(c: bool, n: usize) -> u32 { + let x = 2; + let a = [1, 2, 3, 4]; + let b = [5, 6, 7, 7]; + x + if c { a } else { b }[n] +} + +/// See [Wrapping expr in curly braces changes the operator precedence +/// #28777](https://github.com/rust-lang/rust/issues/28777). This was fixed by +/// . #30375 added the `that_odd_parse` example above, +/// but that is not *quite* the same original example as reported in #28777, so we also include the +/// original example here. +fn check_issue_28777() { + // Before #30375 fixed the precedence... + + // ... `v1` evaluated to 9, indicating a parse of `(1 + 2) * 3`, while + let v1 = { 1 + { 2 } * { 3 } }; + + // `v2` evaluated to 7, indicating a parse of `1 + (2 * 3)`. + let v2 = 1 + { 2 } * { 3 }; + + // Check that both now evaluate to 7, as was fixed by #30375. + assert_eq!(v1, 7); + assert_eq!(v2, 7); +} + +fn main() { + assert_eq!(4, that_odd_parse(true, 1)); + assert_eq!(8, that_odd_parse(false, 1)); + + check_issue_28777(); +} diff --git a/tests/ui/parser/issues/issue-72373.rs b/tests/ui/parser/issues/issue-72373.rs index 4da6061c27fe..ed88d53539bd 100644 --- a/tests/ui/parser/issues/issue-72373.rs +++ b/tests/ui/parser/issues/issue-72373.rs @@ -3,7 +3,7 @@ fn foo(c: &[u32], n: u32) -> u32 { [h, ..] if h > n => 0, [h, ..] if h == n => 1, [h, ref ts..] => foo(c, n - h) + foo(ts, n), - //~^ ERROR expected one of `,`, `@`, `]`, or `|`, found `..` + //~^ ERROR expected one of `,`, `@`, `]`, `if`, or `|`, found `..` [] => 0, } } diff --git a/tests/ui/parser/issues/issue-72373.stderr b/tests/ui/parser/issues/issue-72373.stderr index c596c6abda55..d566d6f5fd13 100644 --- a/tests/ui/parser/issues/issue-72373.stderr +++ b/tests/ui/parser/issues/issue-72373.stderr @@ -1,8 +1,8 @@ -error: expected one of `,`, `@`, `]`, or `|`, found `..` +error: expected one of `,`, `@`, `]`, `if`, or `|`, found `..` --> $DIR/issue-72373.rs:5:19 | LL | [h, ref ts..] => foo(c, n - h) + foo(ts, n), - | ^^ expected one of `,`, `@`, `]`, or `|` + | ^^ expected one of `,`, `@`, `]`, `if`, or `|` | help: if you meant to bind the contents of the rest of the array pattern into `ts`, use `@` | diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr index b8b52702314c..398d9d6bb99b 100644 --- a/tests/ui/parser/misspelled-keywords/ref.stderr +++ b/tests/ui/parser/misspelled-keywords/ref.stderr @@ -1,8 +1,8 @@ -error: expected one of `)`, `,`, `@`, or `|`, found `list` +error: expected one of `)`, `,`, `@`, `if`, or `|`, found `list` --> $DIR/ref.rs:4:19 | LL | Some(refe list) => println!("{list:?}"), - | ^^^^ expected one of `)`, `,`, `@`, or `|` + | ^^^^ expected one of `)`, `,`, `@`, `if`, or `|` | help: there is a keyword `ref` with a similar name | diff --git a/tests/ui/parser/pat-lt-bracket-7.rs b/tests/ui/parser/pat-lt-bracket-7.rs index 327aef5ad157..abaeb4c83c05 100644 --- a/tests/ui/parser/pat-lt-bracket-7.rs +++ b/tests/ui/parser/pat-lt-bracket-7.rs @@ -3,7 +3,7 @@ fn main() { let foo = core::iter::empty(); for Thing(x[]) in foo {} - //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` + //~^ ERROR: expected one of `)`, `,`, `@`, `if`, or `|`, found `[` } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/tests/ui/parser/pat-lt-bracket-7.stderr b/tests/ui/parser/pat-lt-bracket-7.stderr index 004dcfb2a7b2..cc457a4e64e2 100644 --- a/tests/ui/parser/pat-lt-bracket-7.stderr +++ b/tests/ui/parser/pat-lt-bracket-7.stderr @@ -1,10 +1,10 @@ -error: expected one of `)`, `,`, `@`, or `|`, found `[` +error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[` --> $DIR/pat-lt-bracket-7.rs:5:16 | LL | for Thing(x[]) in foo {} | ^ | | - | expected one of `)`, `,`, `@`, or `|` + | expected one of `)`, `,`, `@`, `if`, or `|` | help: missing `,` error[E0308]: mismatched types diff --git a/tests/ui/parser/recover/recover-pat-exprs.rs b/tests/ui/parser/recover/recover-pat-exprs.rs index e5e25df0c01c..a78bb82828d3 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.rs +++ b/tests/ui/parser/recover/recover-pat-exprs.rs @@ -27,7 +27,7 @@ fn array_indexing() { { let x[0, 1, 2]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` { let x[0; 20]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` { let x[]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` - { let (x[]); } //~ error: expected one of `)`, `,`, `@`, or `|`, found `[` + { let (x[]); } //~ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[` //~^ missing `,` } @@ -95,12 +95,12 @@ fn main() { f?() => (), //~^ error: expected a pattern, found an expression (_ + 1) => (), - //~^ error: expected one of `)`, `,`, or `|`, found `+` + //~^ error: expected one of `)`, `,`, `if`, or `|`, found `+` } let 1 + 1 = 2; //~^ error: expected a pattern, found an expression let b = matches!(x, (x * x | x.f()) | x[0]); - //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*` + //~^ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*` } diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index 041dfd647ad0..281eeced4024 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -213,13 +213,13 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` LL | { let x[]; } | ^ expected one of `:`, `;`, `=`, `@`, or `|` -error: expected one of `)`, `,`, `@`, or `|`, found `[` +error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[` --> $DIR/recover-pat-exprs.rs:30:13 | LL | { let (x[]); } | ^ | | - | expected one of `)`, `,`, `@`, or `|` + | expected one of `)`, `,`, `@`, `if`, or `|` | help: missing `,` error: expected a pattern, found an expression @@ -611,11 +611,11 @@ LL | x.sqrt() @ .. => (), | = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` -error: expected one of `)`, `,`, or `|`, found `+` +error: expected one of `)`, `,`, `if`, or `|`, found `+` --> $DIR/recover-pat-exprs.rs:97:12 | LL | (_ + 1) => (), - | ^ expected one of `)`, `,`, or `|` + | ^ expected one of `)`, `,`, `if`, or `|` error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:81:9 @@ -772,11 +772,11 @@ LL | let 1 + 1 = 2; | = note: arbitrary expressions are not allowed in patterns: -error: expected one of `)`, `,`, `@`, or `|`, found `*` +error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*` --> $DIR/recover-pat-exprs.rs:104:28 | LL | let b = matches!(x, (x * x | x.f()) | x[0]); - | ^ expected one of `)`, `,`, `@`, or `|` + | ^ expected one of `)`, `,`, `@`, `if`, or `|` --> $SRC_DIR/core/src/macros/mod.rs:LL:COL | = note: while parsing argument for this `pat` macro fragment diff --git a/tests/ui/parser/recover/recover-pat-wildcards.rs b/tests/ui/parser/recover/recover-pat-wildcards.rs index f506e2223d60..d4d28ce63587 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.rs +++ b/tests/ui/parser/recover/recover-pat-wildcards.rs @@ -8,7 +8,7 @@ fn a() { fn b() { match 2 { - (_ % 4) => () //~ error: expected one of `)`, `,`, or `|`, found `%` + (_ % 4) => () //~ error: expected one of `)`, `,`, `if`, or `|`, found `%` } } @@ -40,7 +40,7 @@ fn f() { fn g() { match 7 { - (_ * 0)..5 => () //~ error: expected one of `)`, `,`, or `|`, found `*` + (_ * 0)..5 => () //~ error: expected one of `)`, `,`, `if`, or `|`, found `*` } } diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr index 81a9920f6a24..f939e5133700 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -4,11 +4,11 @@ error: expected one of `=>`, `if`, or `|`, found `+` LL | _ + 1 => () | ^ expected one of `=>`, `if`, or `|` -error: expected one of `)`, `,`, or `|`, found `%` +error: expected one of `)`, `,`, `if`, or `|`, found `%` --> $DIR/recover-pat-wildcards.rs:11:12 | LL | (_ % 4) => () - | ^ expected one of `)`, `,`, or `|` + | ^ expected one of `)`, `,`, `if`, or `|` error: expected one of `=>`, `if`, or `|`, found `.` --> $DIR/recover-pat-wildcards.rs:17:10 @@ -47,11 +47,11 @@ error: expected one of `=>`, `if`, or `|`, found reserved identifier `_` LL | 0..._ => () | ^ expected one of `=>`, `if`, or `|` -error: expected one of `)`, `,`, or `|`, found `*` +error: expected one of `)`, `,`, `if`, or `|`, found `*` --> $DIR/recover-pat-wildcards.rs:43:12 | LL | (_ * 0)..5 => () - | ^ expected one of `)`, `,`, or `|` + | ^ expected one of `)`, `,`, `if`, or `|` error: expected one of `=>`, `if`, or `|`, found `(` --> $DIR/recover-pat-wildcards.rs:49:11 diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr index da8f4ca5f0cd..6ce8f6d31a03 100644 --- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr @@ -6,11 +6,11 @@ LL | let a: u8 @ b = 0; | | | while parsing the type for `a` -error: expected one of `)`, `,`, `@`, or `|`, found `:` +error: expected one of `)`, `,`, `@`, `if`, or `|`, found `:` --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15 | LL | let a @ (b: u8); - | ^ expected one of `)`, `,`, `@`, or `|` + | ^ expected one of `)`, `,`, `@`, `if`, or `|` | = note: type ascription syntax has been removed, see issue #101728 diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/macro-rules.rs b/tests/ui/pattern/rfc-3637-guard-patterns/macro-rules.rs new file mode 100644 index 000000000000..76681f45bb33 --- /dev/null +++ b/tests/ui/pattern/rfc-3637-guard-patterns/macro-rules.rs @@ -0,0 +1,20 @@ +//@ run-pass +//! Tests that the addition of guard patterns does not change the behavior of the `pat` macro +//! fragment. +#![feature(guard_patterns)] +#![allow(incomplete_features)] + +macro_rules! has_guard { + ($p:pat) => { + false + }; + ($p:pat if $e:expr) => { + true + }; +} + +fn main() { + assert_eq!(has_guard!(Some(_)), false); + assert_eq!(has_guard!(Some(_) if true), true); + assert_eq!(has_guard!((Some(_) if true)), false); +} diff --git a/tests/ui/phantom-auto-trait.stderr b/tests/ui/phantom-auto-trait.stderr index 5af648f6a0cf..ffd4c3a0e1ad 100644 --- a/tests/ui/phantom-auto-trait.stderr +++ b/tests/ui/phantom-auto-trait.stderr @@ -23,7 +23,7 @@ note: required by a bound in `is_zen` | LL | fn is_zen(_: T) {} | ^^^ required by this bound in `is_zen` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Sync` | LL | fn not_sync(x: Guard) { | +++++++++++++++++++ @@ -58,7 +58,7 @@ note: required by a bound in `is_zen` | LL | fn is_zen(_: T) {} | ^^^ required by this bound in `is_zen` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Sync` | LL | fn nested_not_sync(x: Nested>) { | +++++++++++++++++++ diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs index f91698d06372..e919a2d93096 100644 --- a/tests/ui/recursion/issue-83150.rs +++ b/tests/ui/recursion/issue-83150.rs @@ -1,8 +1,7 @@ -//~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:14:24: 14:27}>: Iterator` +//~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator` //@ build-fail //@ compile-flags: -Copt-level=0 //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" -//@ ignore-compare-mode-next-solver (hangs) fn main() { let mut iter = 0u8..1; diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr index fb66436dbbdd..92a39a44e4fa 100644 --- a/tests/ui/recursion/issue-83150.stderr +++ b/tests/ui/recursion/issue-83150.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/issue-83150.rs:12:1 + --> $DIR/issue-83150.rs:11:1 | LL | fn func>(iter: &mut T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -10,12 +10,12 @@ LL | func(&mut iter.map(|x| x + 1)) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:14:24: 14:27}>: Iterator` +error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:14:24: 14:27}>` to implement `Iterator` + = note: required for `&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` = note: 65 redundant requirements hidden - = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>, {closure@$DIR/issue-83150.rs:14:24: 14:27}>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index b17d1e0ab113..87f0f47f2401 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait2` | LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ @@ -17,7 +17,7 @@ LL | | LL | | } | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait2` | LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ diff --git a/tests/ui/resolve/issue-55673.stderr b/tests/ui/resolve/issue-55673.stderr index 4069b35a9984..7d420126199b 100644 --- a/tests/ui/resolve/issue-55673.stderr +++ b/tests/ui/resolve/issue-55673.stderr @@ -15,7 +15,7 @@ error[E0220]: associated type `Baa` not found for `T` LL | T::Baa: std::fmt::Debug, | ^^^ there is a similarly named associated type `Bar` in the trait `Foo` | -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Foo` | LL | T::Baa: std::fmt::Debug, T: Foo | ~~~~~~~~ diff --git a/tests/ui/rust-2024/gen-kw.e2015.stderr b/tests/ui/rust-2024/gen-kw.e2015.stderr index ff552f663c74..5c42d65abf03 100644 --- a/tests/ui/rust-2024/gen-kw.e2015.stderr +++ b/tests/ui/rust-2024/gen-kw.e2015.stderr @@ -34,11 +34,47 @@ LL | () => { mod test { fn gen() {} } } error: `gen` is a keyword in the 2024 edition --> $DIR/gen-kw.rs:25:9 | -LL | fn test<'gen>() {} +LL | fn test<'gen>(_: &'gen i32) {} | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see issue #49716 -error: aborting due to 4 previous errors +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:25:19 + | +LL | fn test<'gen>(_: &'gen i32) {} + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:13 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:28 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:37 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: aborting due to 8 previous errors diff --git a/tests/ui/rust-2024/gen-kw.e2018.stderr b/tests/ui/rust-2024/gen-kw.e2018.stderr index efa812069c38..050e58c119bf 100644 --- a/tests/ui/rust-2024/gen-kw.e2018.stderr +++ b/tests/ui/rust-2024/gen-kw.e2018.stderr @@ -34,11 +34,47 @@ LL | () => { mod test { fn gen() {} } } error: `gen` is a keyword in the 2024 edition --> $DIR/gen-kw.rs:25:9 | -LL | fn test<'gen>() {} +LL | fn test<'gen>(_: &'gen i32) {} | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! = note: for more information, see issue #49716 -error: aborting due to 4 previous errors +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:25:19 + | +LL | fn test<'gen>(_: &'gen i32) {} + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:13 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:28 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: `gen` is a keyword in the 2024 edition + --> $DIR/gen-kw.rs:33:37 + | +LL | struct Test<'gen>(Box>, &'gen ()); + | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! + = note: for more information, see issue #49716 + +error: aborting due to 8 previous errors diff --git a/tests/ui/rust-2024/gen-kw.rs b/tests/ui/rust-2024/gen-kw.rs index 5a658470c0a8..3c075a4c022a 100644 --- a/tests/ui/rust-2024/gen-kw.rs +++ b/tests/ui/rust-2024/gen-kw.rs @@ -22,9 +22,23 @@ macro_rules! t { //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! } -fn test<'gen>() {} +fn test<'gen>(_: &'gen i32) {} //~^ ERROR `gen` is a keyword in the 2024 edition +//~| ERROR `gen` is a keyword in the 2024 edition //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! +//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! +//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! +//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! + +struct Test<'gen>(Box>, &'gen ()); +//~^ ERROR `gen` is a keyword in the 2024 edition +//~| ERROR `gen` is a keyword in the 2024 edition +//~| ERROR `gen` is a keyword in the 2024 edition +//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! +//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! +//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! +//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! +//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024! t!(); diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr index afdbe2eb2267..57d67ac526ac 100644 --- a/tests/ui/specialization/default-generic-associated-type-bound.stderr +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -20,7 +20,7 @@ note: required by a bound in `X::U` | LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; | ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `PartialEq` | LL | impl X for T { | +++++++++++++++++++++ diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 01188e293bd9..4a51a7dfa47f 100644 --- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -19,7 +19,7 @@ note: required by a bound in `Foo` | LL | trait Foo<'a, T: Eq + 'a> { } | ^^ required by this bound in `Foo` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Eq` | LL | default impl Foo<'static, U> for () {} | ++++++++++++++ diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr index 2c20077078fd..29a82a4d8751 100644 --- a/tests/ui/specialization/issue-33017.stderr +++ b/tests/ui/specialization/issue-33017.stderr @@ -9,7 +9,7 @@ note: required by a bound in `UncheckedCopy::Output` | LL | type Output: From + Copy + Into; | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl UncheckedCopy for T { | +++++++++++++++++++ diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index 268fc3a95916..84e526f45978 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -5,7 +5,7 @@ LL | impl Display for Cow<'_, B> { | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ @@ -17,7 +17,7 @@ LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ @@ -29,7 +29,7 @@ LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ @@ -47,7 +47,7 @@ LL | | } | |_____^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ diff --git a/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_matches.stderr b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_matches.stderr new file mode 100644 index 000000000000..109985c00528 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_matches.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature `atomic_from_mut` + --> $DIR/atomic-from-mut-not-available.rs:24:5 + | +LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76314 for more information + = help: add `#![feature(atomic_from_mut)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr similarity index 94% rename from tests/ui/atomic-from-mut-not-available.stderr rename to tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr index a4514524f48f..47b17f9fcd7a 100644 --- a/tests/ui/atomic-from-mut-not-available.stderr +++ b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `from_mut` found for struct `AtomicU64` in the current scope - --> $DIR/atomic-from-mut-not-available.rs:5:36 + --> $DIR/atomic-from-mut-not-available.rs:24:36 | LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); | ^^^^^^^^ function or associated item not found in `AtomicU64` diff --git a/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.rs b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.rs new file mode 100644 index 000000000000..7e9de3570eb9 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.rs @@ -0,0 +1,27 @@ +//! This test exercises the combined effect of the `cfg(target_has_atomic_equal_alignment = "...")` +//! implementation in the compiler plus usage of said `cfg(target_has_atomic_equal_alignment)` in +//! `core` for the `Atomic64::from_mut` API. +//! +//! This test is a basic smoke test: that `AtomicU64::from_mut` is gated by +//! `#[cfg(target_has_atomic_equal_alignment = "8")]`, which is only available on platforms where +//! `AtomicU64` has the same alignment as `u64`. This is notably *not* satisfied by `x86_32`, where +//! they have differing alignments. Thus, `AtomicU64::from_mut` should *not* be available on +//! `x86_32` linux and should report assoc item not found, if the `cfg` is working correctly. +//! Conversely, `AtomicU64::from_mut` *should* be available on `x86_64` linux where the alignment +//! matches. + +//@ revisions: alignment_mismatch alignment_matches + +// This should fail on 32-bit x86 linux... +//@[alignment_mismatch] only-x86 +//@[alignment_mismatch] only-linux + +// ... but pass on 64-bit x86_64 linux. +//@[alignment_matches] only-x86_64 +//@[alignment_matches] only-linux + +fn main() { + core::sync::atomic::AtomicU64::from_mut(&mut 0u64); + //[alignment_mismatch]~^ ERROR no function or associated item named `from_mut` found for struct `AtomicU64` + //[alignment_matches]~^^ ERROR use of unstable library feature `atomic_from_mut` +} diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr index 69e9af726479..6732033e774f 100644 --- a/tests/ui/suggestions/assoc-const-as-fn.stderr +++ b/tests/ui/suggestions/assoc-const-as-fn.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied LL | ::FACTORY(1, value); | ^ the trait `GlUniformScalar` is not implemented for `T` | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `GlUniformScalar` | LL | pub fn foo(value: T) { | +++++++++++++++++ diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index 4965e7439f84..e30deb11398e 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -5,7 +5,7 @@ LL | println!("{:?}", t); | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider restricting opaque type `impl Sized` with trait `Debug` | LL | fn test_impl(t: impl Sized + std::fmt::Debug) { | +++++++++++++++++ @@ -17,7 +17,7 @@ LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Debug` | LL | fn test_no_bounds(t: T) { | +++++++++++++++++ @@ -29,7 +29,7 @@ LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Debug` | LL | fn test_one_bound(t: T) { | +++++++++++++++++ @@ -41,7 +41,7 @@ LL | println!("{:?} {:?}", x, y); | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting type parameter `Y` +help: consider further restricting type parameter `Y` with trait `Debug` | LL | fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { | ~~~~~~~~~~~~~~~~~~~~ @@ -53,7 +53,7 @@ LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `X` with trait `Debug` | LL | fn test_one_bound_where(x: X) where X: Sized + std::fmt::Debug { | +++++++++++++++++ @@ -65,7 +65,7 @@ LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `X` with trait `Debug` | LL | fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Sized { | +++++++++++++++++ diff --git a/tests/ui/suggestions/clone-bounds-121524.rs b/tests/ui/suggestions/clone-bounds-121524.rs index 8cd60b452de0..b7760584ebbc 100644 --- a/tests/ui/suggestions/clone-bounds-121524.rs +++ b/tests/ui/suggestions/clone-bounds-121524.rs @@ -6,7 +6,7 @@ trait DoesAThing {} impl DoesAThing for ThingThatDoesAThing {} fn clones_impl_ref_inline(thing: &impl DoesAThing) { - //~^ HELP consider further restricting this bound + //~^ HELP consider restricting opaque type `impl DoesAThing` with trait `Clone` drops_impl_owned(thing.clone()); //~ ERROR E0277 //~^ NOTE copies the reference //~| NOTE the trait `DoesAThing` is not implemented for `&impl DoesAThing` diff --git a/tests/ui/suggestions/clone-bounds-121524.stderr b/tests/ui/suggestions/clone-bounds-121524.stderr index 6d60508a4a14..bdba8d7e4722 100644 --- a/tests/ui/suggestions/clone-bounds-121524.stderr +++ b/tests/ui/suggestions/clone-bounds-121524.stderr @@ -9,7 +9,7 @@ note: this `clone()` copies the reference, which does not do anything, because ` | LL | drops_impl_owned(thing.clone()); | ^^^^^ -help: consider further restricting this bound +help: consider restricting opaque type `impl DoesAThing` with trait `Clone` | LL | fn clones_impl_ref_inline(thing: &impl DoesAThing + Clone) { | +++++++ diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr index afbb9c32d516..03a14b03781e 100644 --- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -15,7 +15,7 @@ note: `T` does not implement `Clone`, so `&T` was cloned instead | LL | t.clone() | ^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | fn wat(t: &T) -> T { | +++++++ diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 680890e880ca..eae0b0ae8175 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -14,7 +14,7 @@ LL | impl PartialEq for Struct note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct(T); | +++++++++++++++++++ diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index bffcb1af487e..37a5f4932ff2 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -38,7 +38,7 @@ LL | impl Debug for Inner { = note: required for `&c::Inner` to implement `Debug` = note: required for the cast from `&&c::Inner` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer(Inner); | ++++++++++ @@ -60,7 +60,7 @@ LL | impl Debug for Inner where T: Debug, T: Trait { = note: required for `&d::Inner` to implement `Debug` = note: required for the cast from `&&d::Inner` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer(Inner); | ++++++++++ @@ -82,7 +82,7 @@ LL | impl Debug for Inner where T: Debug + Trait { = note: required for `&e::Inner` to implement `Debug` = note: required for the cast from `&&e::Inner` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer(Inner); | ++++++++++ @@ -104,7 +104,7 @@ LL | impl Debug for Inner where T: Trait { = note: required for `&f::Inner` to implement `Debug` = note: required for the cast from `&&f::Inner` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer(Inner); | ++++++++++ diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr index 8607917ede6b..8b1c0b9a77ad 100644 --- a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&T: X` is not satisfied LL | foo(s); | ^ the trait `X` is not implemented for `&T` | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn bar(s: &T) { | +++++++ diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr index 0e95167d8515..7fe091ef71c7 100644 --- a/tests/ui/suggestions/issue-97677.stderr +++ b/tests/ui/suggestions/issue-97677.stderr @@ -6,7 +6,7 @@ LL | n + 10 | | | N | -help: consider restricting type parameter `N` +help: consider restricting type parameter `N` with trait `Add` | LL | fn add_ten>(n: N) -> N { | ++++++++++++++++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index d65ad109241a..4408fe0a0a4b 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2 { | ^^^^ required by this bound in `Vector2` -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -32,7 +32,7 @@ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -52,7 +52,7 @@ note: required by a bound in `Vector2` LL | pub struct Vector2 { | ^^^^ required by this bound in `Vector2` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -74,7 +74,7 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 2ade0e974e49..1bbf6f66ab23 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2` requires that `K: Debug` LL | pub loc: Vector2, | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB{ | +++++++ @@ -29,7 +29,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2{ | ^^^^^ required by this bound in `Vector2` -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB{ | +++++++++++++++++ @@ -44,7 +44,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB{ | +++++++++++++++++ @@ -59,7 +59,7 @@ LL | pub size: Vector2 | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB{ | +++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 316c2fa0fc96..8b5cced4c4aa 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2` requires that `K: Debug` LL | pub loc: Vector2, | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB { | +++++++ @@ -29,7 +29,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2 { | ^^^^^ required by this bound in `Vector2` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB { | +++++++++++++++++ @@ -45,7 +45,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2 { | ^^^^ required by this bound in `Vector2` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -68,7 +68,7 @@ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -83,7 +83,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB { | +++++++++++++++++ @@ -103,7 +103,7 @@ note: required by a bound in `Vector2` LL | pub struct Vector2 { | ^^^^ required by this bound in `Vector2` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ @@ -118,7 +118,7 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB { | +++++++++++++++++ @@ -140,7 +140,7 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 23a75154f200..600e5ae63d3d 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -12,7 +12,7 @@ note: the `Copy` impl for `OnlyCopyIfDisplay` requires that `S: std::fmt::Dis | LL | struct Wrapper(T); | ^ -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Display` | LL | impl Copy for Wrapper> {} | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index c9f277fb3501..b22aa35ef6d4 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -7,7 +7,7 @@ LL | LL | impl Copy for Wrapper {} | ^^^^^^^^^^ | -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Copy` | LL | impl Copy for Wrapper {} | ++++++ diff --git a/tests/ui/suggestions/restrict-type-argument.stderr b/tests/ui/suggestions/restrict-type-argument.stderr index 01c2de798641..4b6da8a9cd92 100644 --- a/tests/ui/suggestions/restrict-type-argument.stderr +++ b/tests/ui/suggestions/restrict-type-argument.stderr @@ -11,7 +11,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider restricting opaque type `impl Sync` with trait `Send` | LL | fn use_impl_sync(val: impl Sync + std::marker::Send) { | +++++++++++++++++++ @@ -29,7 +29,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_where(val: S) where S: Sync + std::marker::Send { | +++++++++++++++++++ @@ -47,7 +47,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_bound(val: S) { | +++++++++++++++++++ @@ -65,7 +65,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | Sync + std::marker::Send | +++++++++++++++++++ @@ -83,7 +83,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_bound_and_where(val: S) where S: std::fmt::Debug { | +++++++++++++++++++ @@ -101,7 +101,7 @@ note: required by a bound in `is_send` | LL | fn is_send(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Send` | LL | fn use_unbound(val: S) { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr index 6a75cbdf6397..346d19f1b772 100644 --- a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr +++ b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGeneric where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGenericWithEmptyWhere where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -41,7 +41,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGeneric where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -57,7 +57,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGenericWithEmptyWhere where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.rs b/tests/ui/trait-bounds/unstable-trait-suggestion.rs new file mode 100644 index 000000000000..ba96b4f3f97f --- /dev/null +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.rs @@ -0,0 +1,19 @@ +#![feature(staged_api)] +#![allow(internal_features)] +#![stable(feature = "unit_test", since = "1.0.0")] + +#[unstable(feature = "step_trait", issue = "42168")] +pub trait Unstable {} + +#[stable(feature = "unit_test", since = "1.0.0")] +fn foo(_: T) {} + +#[stable(feature = "unit_test", since = "1.0.0")] +pub fn bar(t: T) { //~ HELP consider restricting type parameter `T` with unstable trait `Unstable` + foo(t) //~ ERROR E0277 +} +#[stable(feature = "unit_test", since = "1.0.0")] +pub fn baz(t: std::ops::Range) { //~ HELP consider restricting type parameter `T` with unstable trait + for _ in t {} //~ ERROR E0277 +} +fn main() {} diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr new file mode 100644 index 000000000000..dfa47f2ab468 --- /dev/null +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -0,0 +1,34 @@ +error[E0277]: the trait bound `T: Unstable` is not satisfied + --> $DIR/unstable-trait-suggestion.rs:13:9 + | +LL | foo(t) + | --- ^ the trait `Unstable` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/unstable-trait-suggestion.rs:9:11 + | +LL | fn foo(_: T) {} + | ^^^^^^^^ required by this bound in `foo` +help: consider restricting type parameter `T` with unstable trait `Unstable` + | +LL | pub fn bar(t: T) { + | ++++++++++ + +error[E0277]: the trait bound `T: Step` is not satisfied + --> $DIR/unstable-trait-suggestion.rs:17:14 + | +LL | for _ in t {} + | ^ the trait `Step` is not implemented for `T` + | + = note: required for `std::ops::Range` to implement `Iterator` + = note: required for `std::ops::Range` to implement `IntoIterator` +help: consider restricting type parameter `T` with unstable trait `Step` + | +LL | pub fn baz(t: std::ops::Range) { + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr index 3be6e8a49d69..42b0104e8651 100644 --- a/tests/ui/traits/alias/wf.stderr +++ b/tests/ui/traits/alias/wf.stderr @@ -9,7 +9,7 @@ note: required by a bound in `A` | LL | trait A {} | ^^^ required by this bound in `A` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Foo` | LL | trait B = A; | +++++ diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr index 376a83e58a7d..3b3d6e5f832b 100644 --- a/tests/ui/traits/bad-method-typaram-kind.stderr +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -11,7 +11,7 @@ note: required by a bound in `Bar::bar` | LL | fn bar(&self); | ^^^^ required by this bound in `Bar::bar` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | fn foo() { | +++++++++++++++++++ diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr index 606f764852fe..7d6420c64827 100644 --- a/tests/ui/traits/bound/on-structs-and-enums.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | struct Foo { | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | impl Foo { | +++++++ @@ -59,7 +59,7 @@ note: required by a bound in `Foo` | LL | struct Foo { | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Trait` | LL | struct Badness { | +++++++ @@ -75,7 +75,7 @@ note: required by a bound in `Bar` | LL | enum Bar { | ^^^^^ required by this bound in `Bar` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Trait` | LL | enum MoreBadness { | +++++++ diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr index 9a53c61d0191..21fb19daad4a 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr @@ -42,10 +42,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `::eq` in constant functions --> $DIR/call-generic-method-chain.rs:16:15 diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr index a168171cfe84..845949a38bf5 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr @@ -42,10 +42,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `::eq` in constant functions --> $DIR/call-generic-method-dup-bound.rs:14:15 @@ -62,10 +58,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self2(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error: aborting due to 8 previous errors diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr index 07e50a7f7daa..6bacb986fef0 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -5,10 +5,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | pub const fn equals_self(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr index af6e6d25dc9b..0c0037e36b86 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr @@ -28,10 +28,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `::eq` in constant functions --> $DIR/call-generic-method-pass.rs:16:15 diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr index cb4c994bc2f2..a76dc3e82af7 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -19,10 +19,6 @@ LL | x(()) | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure i32 + ~const FnOnce(())>(x: T) -> i32 { - | +++++++++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr index 43af435ae64d..d37ff3d727ce 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr @@ -19,10 +19,6 @@ LL | x(()) | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure i32 + ~const FnOnce(())>(x: T) -> i32 { - | +++++++++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr index 2e9e37ba3216..8ceaae16d8e7 100644 --- a/tests/ui/traits/const-traits/const-closures.stderr +++ b/tests/ui/traits/const-traits/const-closures.stderr @@ -61,10 +61,6 @@ LL | f() + f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn answer u8 + ~const Fn()>(f: &F) -> u8 { - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:24:11 @@ -73,10 +69,6 @@ LL | f() + f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn answer u8 + ~const Fn()>(f: &F) -> u8 { - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:12:5 @@ -85,10 +77,6 @@ LL | f() * 7 | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | F: ~const FnOnce() -> u8 + ~const Fn(), - | +++++++++++++ error: aborting due to 11 previous errors diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr index abe24b662a27..3a15cc63f322 100644 --- a/tests/ui/traits/const-traits/trait-where-clause.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause.stderr @@ -33,7 +33,7 @@ note: required by a bound in `Foo::b` | LL | fn b() where Self: ~const Bar; | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Bar` | LL | fn test1() { | +++++ @@ -49,7 +49,7 @@ note: required by a bound in `Foo::c` | LL | fn c(); | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Bar` | LL | fn test1() { | +++++ diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index 3bdb8b70172c..45c26ac9ef46 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -14,7 +14,7 @@ LL | T: TraitFoo, | -------- unsatisfied trait bound introduced here note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `TraitFoo` | LL | impl Copy for Foo {} | ++++++++++ diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr index 56544dd4def0..02170a127dbd 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -12,7 +12,7 @@ note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static` | LL | struct Bar<'lt>(Foo<'lt>); | ^^^^^^^^ -help: consider restricting type parameter `'any` +help: consider restricting type parameter `'any` with `'static` | LL | impl<'any: 'static> Copy for Bar<'any> {} | +++++++++ diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr index 6092c194a875..1816e029f184 100644 --- a/tests/ui/traits/inductive-overflow/two-traits.stderr +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Magic::X` | LL | type X: Trait; | ^^^^^ required by this bound in `Magic::X` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | impl Magic for T { | +++++++++++++++++++ diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 6f7c9fa11d4b..fdf0b1722bea 100644 --- a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -18,7 +18,7 @@ LL | c.same_as(22) | | | required by a bound introduced by this call | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `CompareTo` | LL | fn with_trait>(c: &C) -> bool { | ++++++++++++++++ @@ -41,7 +41,7 @@ LL | CompareTo::same_as(c, 22) | | | required by a bound introduced by this call | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `CompareTo` | LL | fn with_ufcs2>(c: &C) -> bool { | ++++++++++++++++ diff --git a/tests/ui/traits/issue-21837.stderr b/tests/ui/traits/issue-21837.stderr index f19893926880..06e79d40c7d6 100644 --- a/tests/ui/traits/issue-21837.stderr +++ b/tests/ui/traits/issue-21837.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | pub struct Foo(T); | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Bound` | LL | impl Trait2 for Foo {} | +++++++ diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 2bf365745a6b..1a6da70d76da 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -14,7 +14,7 @@ note: required by a bound in `Complete` | LL | pub trait Complete: Partial { | ^^^^^^^ required by this bound in `Complete` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Complete for T {} | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr index cd8d8b3ffcd3..463e50a2553e 100644 --- a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | let x: ::Assoc = (); | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn test_poly() { | +++++++ diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr index a720797efc4b..6398fbddca5e 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -10,7 +10,7 @@ note: required by a bound in `copy` | LL | fn copy(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ @@ -38,7 +38,7 @@ LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T` | = note: required because it appears within the type `dyn Setup` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 1f319cc6743b..da269bbeae4c 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -14,7 +14,7 @@ LL | impl PartialEq for Struct note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct(T); | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 09162970d33d..d2a58e95629a 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -32,7 +32,7 @@ error[E0277]: the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not sati LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^ the trait `Overlap fn(Assoc<'a, T>)>` is not implemented for `T` | -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Overlap` | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap, T: Overlap fn(Assoc<'a, T>)> {} | ++++++++++++++++++++++++++++++++++++++ diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr index e3e29a73fdc0..ccbc5ae2b751 100644 --- a/tests/ui/tuple/builtin-fail.stderr +++ b/tests/ui/tuple/builtin-fail.stderr @@ -9,7 +9,7 @@ note: required by a bound in `assert_is_tuple` | LL | fn assert_is_tuple() {} | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with unstable trait `Tuple` | LL | fn from_param_env() { | ++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index 8f887a6ac68f..bbb32b2d604d 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn f(t: T) -> X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub type X = impl Clone; | +++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr index bca88b5fae10..c0f6d6780976 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Struct` | LL | struct Struct(Option); | ^^^^^^^ required by this bound in `Struct` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Display` | LL | type Foo = (impl Debug, Struct); | +++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr index b20073fcdfcd..047ad164239c 100644 --- a/tests/ui/type-alias-impl-trait/future.stderr +++ b/tests/ui/type-alias-impl-trait/future.stderr @@ -9,7 +9,7 @@ note: required by a bound in `foo` | LL | fn foo(bar: B) -> FooFuture { | ^^^ required by this bound in `foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFuture = impl Future; | +++++ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index af6e6e1e66e8..cd6e85764bda 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn two(t: T, _: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Debug` | LL | type Two = impl Debug; | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index a847bed93da7..bf3c4a0e04fe 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn three(_: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | type Two = impl Debug; | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr index 88529b370f13..98f99cdbfbd6 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained = impl Send; | ^^^^^ required by this bound -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn underconstrain(_: T) -> Underconstrained { | +++++++ @@ -30,7 +30,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained = impl Send; | ^^^^^ required by this bound -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn underconstrain(_: T) -> Underconstrained { | +++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index b3b9cbca9685..5506977a3e70 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | fn underconstrained(_: U) -> Underconstrained { | +++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound on the type alias `Underconstrained2` | LL | type Underconstrained2 = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Debug` | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { | +++++++++++++++++ @@ -46,7 +46,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | fn underconstrained(_: U) -> Underconstrained { | +++++++++++++++++ @@ -67,7 +67,7 @@ note: required by a bound on the type alias `Underconstrained2` | LL | type Underconstrained2 = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Debug` | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr index a6bdddbc98c6..6673b03525d0 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn foo(t: T) -> Foo { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Default` | LL | type Foo = impl Default; | +++++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr index f04750866c76..579902aa3ab2 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -9,7 +9,7 @@ note: required by a bound in `make_bug` | LL | fn make_bug>() -> Bug { | ^^^^^^^ required by this bound in `make_bug` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `From` | LL | pub type Bug> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr index 91d71339a084..6fa7e197c40c 100644 --- a/tests/ui/type-alias-impl-trait/issue-89686.stderr +++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | async move { self.f().await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type G<'a, T: Trait> = impl Future; | +++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr index bc233a532143..afdccd56a50f 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -9,7 +9,7 @@ note: required by a bound in `::foo` | LL | fn foo(&self, bar: B) -> Self::FooFn { | ^^^ required by this bound in `::foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn = impl FnOnce(); | +++++ diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 4a6a62bdf96d..d4faa6e93925 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn foo(&self, bar: B) -> Self::FooFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn = impl Baz; | +++++ diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr index a2944a1acb97..e2fa9442323a 100644 --- a/tests/ui/type-alias-impl-trait/not_well_formed.stderr +++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V` LL | type Foo = impl Trait; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | type Foo = impl Trait; | ++++++++++++++++ @@ -16,7 +16,7 @@ LL | type Foo = impl Trait; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | type Foo = impl Trait; | ++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs index b33051da2d77..18f09b548675 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -1,5 +1,3 @@ -//@ ignore-compare-mode-next-solver (hangs) - #![feature(type_alias_impl_trait)] type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr index 32eac622e518..15ebcdafca6f 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -1,5 +1,5 @@ error[E0277]: can't compare `&i32` with `Bar<'a, 'b>` - --> $DIR/self-referential-3.rs:7:31 + --> $DIR/self-referential-3.rs:5:31 | LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>` diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.rs b/tests/ui/type-alias-impl-trait/self-referential-4.rs index 29b5a042b7df..36742c8ad57f 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-4.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-4.rs @@ -1,5 +1,3 @@ -//@ ignore-compare-mode-next-solver (hangs) - #![feature(type_alias_impl_trait)] type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.stderr b/tests/ui/type-alias-impl-trait/self-referential-4.stderr index e7f9e232a274..98c762e3d382 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-4.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-4.stderr @@ -1,5 +1,5 @@ error[E0277]: can't compare `&i32` with `Bar<'b, 'static>` - --> $DIR/self-referential-4.rs:7:31 + --> $DIR/self-referential-4.rs:5:31 | LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'static>` @@ -10,7 +10,7 @@ LL | i = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` - --> $DIR/self-referential-4.rs:13:31 + --> $DIR/self-referential-4.rs:11:31 | LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == Foo<'static, 'b>` @@ -21,7 +21,7 @@ LL | i = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` - --> $DIR/self-referential-4.rs:19:31 + --> $DIR/self-referential-4.rs:17:31 | LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == Moo<'static, 'a>` diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs index 2bd450e6c860..b899b12cc4a1 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.rs +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -1,5 +1,3 @@ -//@ ignore-compare-mode-next-solver (hangs) - #![feature(type_alias_impl_trait)] type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr index 396237c78980..57d67f693761 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -1,5 +1,5 @@ error[E0277]: can't compare `&i32` with `Bar<'b, 'a>` - --> $DIR/self-referential.rs:7:31 + --> $DIR/self-referential.rs:5:31 | LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'a>` @@ -11,7 +11,7 @@ LL | i = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)` - --> $DIR/self-referential.rs:14:31 + --> $DIR/self-referential.rs:12:31 | LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)` @@ -23,7 +23,7 @@ LL | (42, i) = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)` - --> $DIR/self-referential.rs:21:31 + --> $DIR/self-referential.rs:19:31 | LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)` diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index 48cef847fbbf..e50949ed8f36 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn _defining_use() -> Converter { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type Converter = impl ProofForConversion; | +++++++ diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr index 47bea7bbe608..9046a8a76b82 100644 --- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr @@ -9,7 +9,7 @@ note: required by a bound in `mop` | LL | fn mop(bar: B) { bar.bar() } | ^^^ required by this bound in `mop` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn = impl FnOnce(B); | +++++ diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr index 09a42f73490a..4156f0ca96ae 100644 --- a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr @@ -9,7 +9,7 @@ note: required by a bound in `foo` | LL | fn foo(bar: B) -> FooFn { | ^^^ required by this bound in `foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn = impl FnOnce(); | +++++ diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr index 96179a7b4846..885c6ec9d8e8 100644 --- a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr +++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `T` LL | type AssocOf = T::Assoc; | ^^^^^ there is an associated type `Assoc` in the trait `Trait` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type AssocOf = T::Assoc; | +++++++ @@ -15,7 +15,7 @@ error[E0220]: associated type `Assok` not found for `T` LL | type AssokOf = T::Assok; | ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type AssokOf = T::Assok; | +++++++ @@ -30,7 +30,7 @@ error[E0220]: associated type `Proj` not found for `T` LL | type ProjOf = T::Proj; | ^^^^ there is an associated type `Proj` in the trait `Parametrized` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Parametrized` | LL | type ProjOf> = T::Proj; | ++++++++++++++++++++++++++++++ diff --git a/tests/ui/type/auxiliary/crate_a1.rs b/tests/ui/type/auxiliary/crate_a1.rs index e2e18500541e..616493193fd6 100644 --- a/tests/ui/type/auxiliary/crate_a1.rs +++ b/tests/ui/type/auxiliary/crate_a1.rs @@ -1,6 +1,6 @@ pub struct Foo; -pub trait Bar{} +pub trait Bar {} pub fn bar() -> Box { unimplemented!() diff --git a/tests/ui/type/auxiliary/crate_a2.rs b/tests/ui/type/auxiliary/crate_a2.rs index d16a4ac10e0c..57a7685b77c4 100644 --- a/tests/ui/type/auxiliary/crate_a2.rs +++ b/tests/ui/type/auxiliary/crate_a2.rs @@ -1,6 +1,6 @@ pub struct Foo; -pub trait Bar{} +pub trait Bar {} pub fn bar() -> Box { unimplemented!() diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr index 9c4825061297..ab3378eaa4ab 100644 --- a/tests/ui/type/type-check-defaults.stderr +++ b/tests/ui/type/type-check-defaults.stderr @@ -53,7 +53,7 @@ note: required by a bound in `Super` | LL | trait Super { } | ^^^^ required by this bound in `Super` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | trait Base: Super where T: std::marker::Copy { } | ++++++++++++++++++++++++++ diff --git a/tests/ui/type/type-check/missing_trait_impl.stderr b/tests/ui/type/type-check/missing_trait_impl.stderr index 2b58cd4180bd..033b42e6736d 100644 --- a/tests/ui/type/type-check/missing_trait_impl.stderr +++ b/tests/ui/type/type-check/missing_trait_impl.stderr @@ -6,7 +6,7 @@ LL | let z = x + y; | | | T | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Add` | LL | fn foo(x: T, y: T) { | +++++++++++++++ @@ -19,7 +19,7 @@ LL | x += x; | | | cannot use `+=` on type `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `AddAssign` | LL | fn bar(x: T) { | +++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0600]: cannot apply unary operator `-` to type `T` LL | let y = -x; | ^^ cannot apply unary operator `-` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Neg` | LL | fn baz(x: T) { | +++++++++++++++ @@ -41,7 +41,7 @@ error[E0600]: cannot apply unary operator `!` to type `T` LL | let y = !x; | ^^ cannot apply unary operator `!` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Not` | LL | fn baz(x: T) { | +++++++++++++++ diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs index da7661652382..e88960364a25 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.rs +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -3,25 +3,32 @@ // This tests the extra note reported when a type error deals with // seemingly identical types. -// The main use case of this error is when there are two crates -// (generally different versions of the same crate) with the same name -// causing a type mismatch. Here, we simulate that error using block-scoped -// aliased `extern crate` declarations. +// The main use case of this error is when there are two crates imported +// with the same name, causing a type mismatch. Here, we simulate that error +// using block-scoped aliased `extern crate` declarations. +// This is *not* the same case as two different crate versions in the +// dependency tree. That is tested in `tests/run-make/crate-loading/`. fn main() { let foo2 = {extern crate crate_a2 as a; a::Foo}; + //~^ NOTE one type comes from crate `crate_a2` used here, which is renamed locally to `a` + //~| NOTE one trait comes from crate `crate_a2` used here, which is renamed locally to `a` let bar2 = {extern crate crate_a2 as a; a::bar()}; { extern crate crate_a1 as a; + //~^ NOTE one type comes from crate `crate_a1` used here, which is renamed locally to `a` + //~| NOTE one trait comes from crate `crate_a1` used here, which is renamed locally to `a` a::try_foo(foo2); //~^ ERROR mismatched types - //~| perhaps two different versions of crate `crate_a1` - //~| expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE arguments to this function are incorrect + //~| NOTE two types coming from two different crates are different types even if they look the same + //~| NOTE function defined here a::try_bar(bar2); //~^ ERROR mismatched types - //~| perhaps two different versions of crate `crate_a1` - //~| expected trait `main::a::Bar` - //~| expected struct `Box<(dyn main::a::Bar + 'static)>` - //~| found struct `Box` + //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar` + //~| NOTE arguments to this function are incorrect + //~| NOTE two types coming from two different crates are different types even if they look the same + //~| NOTE function defined here } } diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr index 504812f5867a..7b791549f563 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.stderr +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -1,23 +1,29 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:16:20 + --> $DIR/type-mismatch-same-crate-name.rs:21:20 | LL | a::try_foo(foo2); | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo` | | | arguments to this function are incorrect | - = note: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types -note: `main::a::Foo` is defined in crate `crate_a2` +note: two types coming from two different crates are different types even if they look the same --> $DIR/auxiliary/crate_a2.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ -note: `main::a::Foo` is defined in crate `crate_a1` - --> $DIR/auxiliary/crate_a1.rs:1:1 + | ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo` + | + ::: $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ - = note: perhaps two different versions of crate `crate_a1` are being used? + | ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo` + | + ::: $DIR/type-mismatch-same-crate-name.rs:13:17 + | +LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; + | --------------------------- one type comes from crate `crate_a2` used here, which is renamed locally to `a` +... +LL | extern crate crate_a1 as a; + | --------------------------- one type comes from crate `crate_a1` used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | @@ -25,16 +31,31 @@ LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:20:20 + --> $DIR/type-mismatch-same-crate-name.rs:27:20 | LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` | | | arguments to this function are incorrect | - = note: expected struct `Box<(dyn main::a::Bar + 'static)>` - found struct `Box` - = note: perhaps two different versions of crate `crate_a1` are being used? +note: two types coming from two different crates are different types even if they look the same + --> $DIR/auxiliary/crate_a2.rs:3:1 + | +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar` + | + ::: $DIR/auxiliary/crate_a1.rs:3:1 + | +LL | pub trait Bar {} + | ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar` + | + ::: $DIR/type-mismatch-same-crate-name.rs:13:17 + | +LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; + | --------------------------- one trait comes from crate `crate_a2` used here, which is renamed locally to `a` +... +LL | extern crate crate_a1 as a; + | --------------------------- one trait comes from crate `crate_a1` used here, which is renamed locally to `a` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index bd7fd0392c37..dd2ce092368a 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -12,7 +12,7 @@ LL | impl Index<&K> for HashMap LL | where LL | K: Hash, | ---- unsatisfied trait bound introduced here -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Hash` | LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap, k: K) -> &'a V { | +++++++++++++++++ @@ -31,7 +31,7 @@ LL | impl Index<&K> for HashMap ... LL | V: Copy, | ---- unsatisfied trait bound introduced here -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Copy` | LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap, k: K) -> &'a V { | +++++++++++++++++++ diff --git a/tests/ui/typeck/issue-90164.stderr b/tests/ui/typeck/issue-90164.stderr index 43e96e1adc6b..1be9c1a0b6e1 100644 --- a/tests/ui/typeck/issue-90164.stderr +++ b/tests/ui/typeck/issue-90164.stderr @@ -13,7 +13,7 @@ note: required by a bound in `copy` | LL | fn copy(_: R, _: W) {} | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Unpin` | LL | fn f(r: T) { | ++++++++++++++++++++ diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr index 537ae6b2b5f6..d72c56ac7127 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -9,7 +9,7 @@ note: required by a bound in `is_send` | LL | fn is_send() { | ^^^^ required by this bound in `is_send` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn foo() { | +++++++++++++++++++ diff --git a/tests/ui/union/issue-81199.stderr b/tests/ui/union/issue-81199.stderr index 0dd894beb2a4..8b78ddcf4a52 100644 --- a/tests/ui/union/issue-81199.stderr +++ b/tests/ui/union/issue-81199.stderr @@ -9,7 +9,7 @@ note: required by a bound in `PtrComponents` | LL | struct PtrComponents { | ^^^^^^^ required by this bound in `PtrComponents` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Pointee` | LL | union PtrRepr { | +++++++++ diff --git a/tests/ui/unop/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr index 0ae918d434a0..5b81feaa578a 100644 --- a/tests/ui/unop/unop-move-semantics.stderr +++ b/tests/ui/unop/unop-move-semantics.stderr @@ -15,7 +15,7 @@ help: consider cloning the value if the performance cost is acceptable | LL | !x.clone(); | ++++++++ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn move_then_borrow + Clone + Copy>(x: T) { | ++++++ diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr index 622d72f791e2..3f87d3e0786f 100644 --- a/tests/ui/wf/issue-96810.stderr +++ b/tests/ui/wf/issue-96810.stderr @@ -9,7 +9,7 @@ note: required by a bound in `S` | LL | struct S(T::Assoc); | ^^ required by this bound in `S` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Tr` | LL | struct Hoge { | ++++ diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr index 78b5c6ec20eb..1f37dc409fc7 100644 --- a/tests/ui/wf/wf-enum-bound.stderr +++ b/tests/ui/wf/wf-enum-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr index 2f2c1c2d2665..f15a31887a20 100644 --- a/tests/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | enum AnotherEnum { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr index a5feaadfc758..3b4de77efdc2 100644 --- a/tests/ui/wf/wf-enum-fields.stderr +++ b/tests/ui/wf/wf-enum-fields.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | enum SomeEnum { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index fbfe42ac6247..76671dedabf4 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | fn foo() where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr index 09e255bead02..47962c75d69d 100644 --- a/tests/ui/wf/wf-impl-associated-type-trait.stderr +++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MySet` | LL | pub struct MySet { | ^^^^^^ required by this bound in `MySet` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `MyHash` | LL | impl Foo for T { | ++++++++ diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr index 8f22edd17a10..a65f621526b1 100644 --- a/tests/ui/wf/wf-in-fn-arg.stderr +++ b/tests/ui/wf/wf-in-fn-arg.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn bar(_: &MustBeCopy) | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr index 1ae49a348cc6..3f2b46f8478d 100644 --- a/tests/ui/wf/wf-in-fn-ret.stderr +++ b/tests/ui/wf/wf-in-fn-ret.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn bar() -> MustBeCopy | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr index 17594c813daa..4626b90500a3 100644 --- a/tests/ui/wf/wf-in-fn-type-arg.stderr +++ b/tests/ui/wf/wf-in-fn-type-arg.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Bar { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr index fac535a11265..2ad405b44516 100644 --- a/tests/ui/wf/wf-in-fn-type-ret.stderr +++ b/tests/ui/wf/wf-in-fn-type-ret.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Foo { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr index 4c556d3d77de..6a56d1c032f7 100644 --- a/tests/ui/wf/wf-in-fn-where-clause.stderr +++ b/tests/ui/wf/wf-in-fn-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | trait MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: MustBeCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr index b96f56a12a54..5cd5bf5e24ee 100644 --- a/tests/ui/wf/wf-in-obj-type-trait.stderr +++ b/tests/ui/wf/wf-in-obj-type-trait.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Bar { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr index 4cfbec12b6e4..8b41bb17d2fa 100644 --- a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Copy` | LL | impl Foo { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr index bdc1ee3e0e21..216b7a98b13f 100644 --- a/tests/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | impl Foo where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr index 4ac7f4634e46..24b4282538da 100644 --- a/tests/ui/wf/wf-struct-bound.stderr +++ b/tests/ui/wf/wf-struct-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr index 241ced3c2dbd..4449b71bd880 100644 --- a/tests/ui/wf/wf-struct-field.stderr +++ b/tests/ui/wf/wf-struct-field.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | struct SomeStruct { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr index 4ea895a9b039..fe6a848f8667 100644 --- a/tests/ui/wf/wf-trait-associated-type-bound.stderr +++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | trait SomeTrait { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr index 5845d05b38e6..0a8d9aa7be82 100644 --- a/tests/ui/wf/wf-trait-bound.stderr +++ b/tests/ui/wf/wf-trait-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr index 3c05065e57f9..9b0205bfe395 100644 --- a/tests/ui/wf/wf-trait-superbound.stderr +++ b/tests/ui/wf/wf-trait-superbound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | trait SomeTrait: ExtraCopy { | +++++++++++++++++++ diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 2612cefef28c..955ec18f4651 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -11,7 +11,7 @@ note: required by a bound in `require_copy` | LL | fn require_copy(x: T) {} | ^^^^ required by this bound in `require_copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Foo { | +++++++++++++++++++ diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index 090df26a39e1..793851a28717 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -11,7 +11,7 @@ note: required by a bound in `require_copy` | LL | fn require_copy(x: T) {} | ^^^^ required by this bound in `require_copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl Foo for Bar { | +++++++++++++++++++ diff --git a/triagebot.toml b/triagebot.toml index 4d6806711fbc..c5dbd538f6c2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -644,7 +644,7 @@ cc = ["@rust-lang/wg-const-eval"] message = "Some changes occurred to the CTFE / Miri interpreter" cc = ["@rust-lang/miri"] -[mentions."compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs"] +[mentions."compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"] message = "Some changes occurred in need_type_info.rs" cc = ["@lcnr"] @@ -656,7 +656,7 @@ cc = ["@compiler-errors", "@lcnr"] message = "changes to the core type system" cc = ["@compiler-errors", "@lcnr"] -[mentions."compiler/rustc_hir_analysis/src/fn_ctxt/inspect_obligations.rs"] +[mentions."compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs"] message = "changes to `inspect_obligations.rs`" cc = ["@compiler-errors", "@lcnr"] @@ -761,10 +761,6 @@ cc = [ "@jsha", ] -[mentions."src/librustdoc/html/static/css/themes"] -message = "Some changes occurred in HTML/CSS themes." -cc = ["@GuillaumeGomez"] - [mentions."tests/rustdoc-gui/"] message = "Some changes occurred in GUI tests." cc = ["@GuillaumeGomez"] @@ -779,10 +775,6 @@ directly, or you can comment on the tracking issue and link this PR. """ cc = ["@jieyouxu"] -[mentions."src/librustdoc/html/static/css/themes/ayu.css"] -message = "A change occurred in the Ayu theme." -cc = ["@Cldfire"] - [mentions."src/rustdoc-json-types"] message = """ rustdoc-json-types is a **public** (although nightly-only) API. \