diff options
| author | bors <bors@rust-lang.org> | 2024-03-08 07:09:40 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-08 07:09:40 +0000 |
| commit | 4db028f44995266895ae9e75b0a0726cc690ef7c (patch) | |
| tree | 9da59f255a8a2d5451877c60b9b4d48ab5328542 | |
| parent | 305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd (diff) | |
| parent | fcd2efeb1180162091ce8f79087b2cbd56ea0b76 (diff) | |
| download | rust-4db028f44995266895ae9e75b0a0726cc690ef7c.tar.gz rust-4db028f44995266895ae9e75b0a0726cc690ef7c.zip | |
Auto merge of #3365 - rust-lang:rustup-2024-03-08, r=RalfJung
Automatic Rustup
517 files changed, 7061 insertions, 4174 deletions
diff --git a/Cargo.lock b/Cargo.lock index 635146492b0..853acd1abd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,9 +469,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 37ee9a5140a..03ad75ca8b4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -427,7 +427,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.ensure_with_value().early_lint_checks(()); tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); tcx.ensure_with_value().get_lang_items(()); - let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); + let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); let mut owners = IndexVec::from_fn_n( diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 5321ba8a7cb..2bef4c91224 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -929,35 +929,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> { only_trait: only_trait.then_some(()), }; - self.visibility_not_permitted( - &item.vis, - errors::VisibilityNotPermittedNote::IndividualImplItems, - ); - if let &Unsafe::Yes(span) = unsafety { - self.dcx().emit_err(errors::InherentImplCannotUnsafe { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - }); - } - if let &ImplPolarity::Negative(span) = polarity { - self.dcx().emit_err(error(span, "negative", false)); - } - if let &Defaultness::Default(def_span) = defaultness { - self.dcx().emit_err(error(def_span, "`default`", true)); - } - if let &Const::Yes(span) = constness { - self.dcx().emit_err(error(span, "`const`", true)); - } + self.with_in_trait_impl(None, |this| { + this.visibility_not_permitted( + &item.vis, + errors::VisibilityNotPermittedNote::IndividualImplItems, + ); + if let &Unsafe::Yes(span) = unsafety { + this.dcx().emit_err(errors::InherentImplCannotUnsafe { + span: self_ty.span, + annotation_span: span, + annotation: "unsafe", + self_ty: self_ty.span, + }); + } + if let &ImplPolarity::Negative(span) = polarity { + this.dcx().emit_err(error(span, "negative", false)); + } + if let &Defaultness::Default(def_span) = defaultness { + this.dcx().emit_err(error(def_span, "`default`", true)); + } + if let &Const::Yes(span) = constness { + this.dcx().emit_err(error(span, "`const`", true)); + } - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| { - this.visit_generics(generics) + this.visit_vis(&item.vis); + this.visit_ident(item.ident); + this.with_tilde_const( + Some(DisallowTildeConstContext::Impl(item.span)), + |this| this.visit_generics(generics), + ); + this.visit_ty(self_ty); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); }); - self.visit_ty(self_ty); - walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d9e3f028697..2e14238f950 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -206,14 +206,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } } - if !attr.is_doc_comment() - && let [seg, _] = attr.get_normal_item().path.segments.as_slice() - && seg.ident.name == sym::diagnostic - && !self.features.diagnostic_namespace - { - let msg = "`#[diagnostic]` attribute name space is experimental"; - gate!(self, diagnostic_namespace, seg.ident.span, msg); - } // Emit errors for non-staged-api crates. if !self.features.staged_api { diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index ca43ac4b0e7..0619000364b 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -55,6 +55,7 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { "x86_64" => LLVMMachineType::AMD64, "x86" => LLVMMachineType::I386, "aarch64" => LLVMMachineType::ARM64, + "arm64ec" => LLVMMachineType::ARM64EC, "arm" => LLVMMachineType::ARM, _ => panic!("unsupported cpu type {cpu}"), } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 952f41fbd90..3a34ef0874e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -56,6 +56,7 @@ pub enum LLVMMachineType { AMD64 = 0x8664, I386 = 0x14c, ARM64 = 0xaa64, + ARM64EC = 0xa641, ARM = 0x01c0, } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 75a189aa87c..78d47f36f91 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -201,7 +201,13 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { - let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; + let arch = if sess.target.arch == "x86_64" { + "x86" + } else if sess.target.arch == "arm64ec" { + "aarch64" + } else { + &*sess.target.arch + }; match (arch, s) { ("x86", "sse4.2") => { LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index b406a04af74..220bb77d3fd 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -288,7 +288,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // Generic x86 "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true), // Windows AArch64 - "aarch64" if target.is_like_windows => { + "aarch64" | "arm64ec" if target.is_like_windows => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 9359df5de6a..81ca42e1ad8 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" # tidy-alphabetical-start ar_archive_writer = "0.1.5" bitflags = "2.4.1" -cc = "1.0.69" +cc = "1.0.90" itertools = "0.11" jobserver = "0.1.28" pathdiff = "0.2.0" diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 158b8fb8727..ab1bc0b6cd2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -8,7 +8,7 @@ use std::path::Path; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, - ObjectSymbol, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, + ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, }; use rustc_data_structures::memmap::Mmap; @@ -182,37 +182,40 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static Endian::Little => Endianness::Little, Endian::Big => Endianness::Big, }; - let architecture = match &sess.target.arch[..] { - "arm" => Architecture::Arm, - "aarch64" => { + let (architecture, sub_architecture) = match &sess.target.arch[..] { + "arm" => (Architecture::Arm, None), + "aarch64" => ( if sess.target.pointer_width == 32 { Architecture::Aarch64_Ilp32 } else { Architecture::Aarch64 - } - } - "x86" => Architecture::I386, - "s390x" => Architecture::S390x, - "mips" | "mips32r6" => Architecture::Mips, - "mips64" | "mips64r6" => Architecture::Mips64, - "x86_64" => { + }, + None, + ), + "x86" => (Architecture::I386, None), + "s390x" => (Architecture::S390x, None), + "mips" | "mips32r6" => (Architecture::Mips, None), + "mips64" | "mips64r6" => (Architecture::Mips64, None), + "x86_64" => ( if sess.target.pointer_width == 32 { Architecture::X86_64_X32 } else { Architecture::X86_64 - } - } - "powerpc" => Architecture::PowerPc, - "powerpc64" => Architecture::PowerPc64, - "riscv32" => Architecture::Riscv32, - "riscv64" => Architecture::Riscv64, - "sparc64" => Architecture::Sparc64, - "avr" => Architecture::Avr, - "msp430" => Architecture::Msp430, - "hexagon" => Architecture::Hexagon, - "bpf" => Architecture::Bpf, - "loongarch64" => Architecture::LoongArch64, - "csky" => Architecture::Csky, + }, + None, + ), + "powerpc" => (Architecture::PowerPc, None), + "powerpc64" => (Architecture::PowerPc64, None), + "riscv32" => (Architecture::Riscv32, None), + "riscv64" => (Architecture::Riscv64, None), + "sparc64" => (Architecture::Sparc64, None), + "avr" => (Architecture::Avr, None), + "msp430" => (Architecture::Msp430, None), + "hexagon" => (Architecture::Hexagon, None), + "bpf" => (Architecture::Bpf, None), + "loongarch64" => (Architecture::LoongArch64, None), + "csky" => (Architecture::Csky, None), + "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), // Unsupported architecture. _ => return None, }; @@ -227,6 +230,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static }; let mut file = write::Object::new(binary_format, architecture, endianness); + file.set_sub_architecture(sub_architecture); if sess.target.is_like_osx { if macho_is_arm64e(&sess.target) { file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E); @@ -335,7 +339,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT, "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT, "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT, - _ => bug!("unknown RISC-V ABI name"), + _ => bug!("unknown LoongArch ABI name"), } e_flags diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index bff7e43b8e4..72648e5ade4 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -567,9 +567,10 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( return undecorated; } - let x86 = match &target.arch[..] { - "x86" => true, - "x86_64" => false, + let prefix = match &target.arch[..] { + "x86" => Some('_'), + "x86_64" => None, + "arm64ec" => Some('#'), // Only x86/64 use symbol decorations. _ => return undecorated, }; @@ -606,8 +607,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( Conv::X86Stdcall => ("_", "@"), Conv::X86VectorCall => ("", "@@"), _ => { - if x86 { - undecorated.insert(0, '_'); + if let Some(prefix) = prefix { + undecorated.insert(0, prefix); } return undecorated; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f7afd22a48c..2161bf61daa 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -907,7 +907,11 @@ impl CrateInfo { lang_items::required(tcx, l).then_some(name) }) .collect(); - let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" }; + let prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => "_", + (true, "arm64ec") => "#", + _ => "", + }; // This loop only adds new items to values of the hash map, so the order in which we // iterate over the values is not important. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 725d3bf4431..1ec6c351e25 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -104,10 +104,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let mut simple = || { let llval = if offset.bytes() == 0 { self.llval - } else if field.is_zst() { - // FIXME(erikdesjardins): it should be fine to use inbounds for ZSTs too; - // keeping this logic for now to preserve previous behavior. - bx.ptradd(self.llval, bx.const_usize(offset.bytes())) } else { bx.inbounds_ptradd(self.llval, bx.const_usize(offset.bytes())) }; @@ -168,8 +164,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { debug!("struct_field_ptr: DST field offset: {:?}", offset); // Adjust pointer. - // FIXME(erikdesjardins): should be able to use inbounds here too. - let ptr = bx.ptradd(self.llval, offset); + let ptr = bx.inbounds_ptradd(self.llval, offset); PlaceRef { llval: ptr, llextra: self.llextra, layout: field, align: effective_field_align } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 946ffc05cc1..864241fbd4a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -24,7 +24,7 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, - Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, PointerArithmetic, Scalar, + Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar, }; use super::error::*; @@ -219,7 +219,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { let def_id = instance.def_id(); @@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, ControlFlow<()>> { assert_eq!(args.len(), 2); @@ -410,7 +410,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, orig_instance: ty::Instance<'tcx>, _abi: CallAbi, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -455,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx, Self::Provenance>, + dest: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cb308ab53ec..a484fbd892c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -108,7 +108,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { /// The location where the result of the current stack frame should be written to, /// and its layout in the caller. - pub return_place: PlaceTy<'tcx, Prov>, + pub return_place: MPlaceTy<'tcx, Prov>, /// The list of locals for this stack frame, stored in order as /// `[return_ptr, arguments..., variables..., temporaries...]`. @@ -771,7 +771,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, body: &'mir mir::Body<'tcx>, - return_place: &PlaceTy<'tcx, M::Provenance>, + return_place: &MPlaceTy<'tcx, M::Provenance>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); @@ -912,7 +912,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.copy_op_allow_transmute(&op, &dest) }; - trace!("return value: {:?}", self.dump_place(&dest)); + trace!("return value: {:?}", self.dump_place(&dest.into())); // We delay actually short-circuiting on this error until *after* the stack frame is // popped, since we want this error to be attributed to the caller, whose type defines // this transmute. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1cb991b38f7..b68bfb4211d 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::Size; use super::{ - util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, + util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, MPlaceTy, Machine, OpTy, Pointer, }; @@ -104,7 +104,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; @@ -377,7 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; let (input, input_len) = self.operand_to_simd(&args[0])?; - let (dest, dest_len) = self.place_to_simd(dest)?; + let (dest, dest_len) = self.mplace_to_simd(dest)?; assert_eq!(input_len, dest_len, "Return vector length must match input length"); // Bounds are not checked by typeck so we have to do it ourselves. if index >= input_len { @@ -430,7 +430,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => return Ok(false), } - trace!("{:?}", self.dump_place(dest)); + trace!("{:?}", self.dump_place(&dest.clone().into())); self.go_to_block(ret); Ok(true) } @@ -488,7 +488,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, a: &ImmTy<'tcx, M::Provenance>, b: &ImmTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { assert_eq!(a.layout.ty, b.layout.ty); assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); @@ -506,7 +506,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } // `Rem` says this is all right, so we can let `Div` do its job. - self.binop_ignore_overflow(BinOp::Div, a, b, dest) + self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into()) } pub fn saturating_arith( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0106ec425bc..ee5de44a651 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -196,7 +196,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { instance: ty::Instance<'tcx>, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; @@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { fn_val: Self::ExtraFnVal, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -219,7 +219,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -584,7 +584,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn_val: !, _abi: CallAbi, _args: &[FnArg<$tcx>], - _destination: &PlaceTy<$tcx, Self::Provenance>, + _destination: &MPlaceTy<$tcx, Self::Provenance>, _target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, ) -> InterpResult<$tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 672008edfd3..60f7710c11d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -194,6 +194,12 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> { Local { frame: usize, local: mir::Local, offset: Option<Size> }, } +/// An evaluated place, together with its type. +/// +/// This may reference a stack frame by its index, so `PlaceTy` should generally not be kept around +/// for longer than a single operation. Popping and then pushing a stack frame can make `PlaceTy` +/// point to the wrong destination. If the interpreter has multiple stacks, stack switching will +/// also invalidate a `PlaceTy`. #[derive(Clone)] pub struct PlaceTy<'tcx, Prov: Provenance = CtfeProvenance> { place: Place<Prov>, // Keep this private; it helps enforce invariants. @@ -495,16 +501,6 @@ where Ok((mplace, len)) } - /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. - /// Also returns the number of elements. - pub fn place_to_simd( - &mut self, - place: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - let mplace = self.force_allocation(place)?; - self.mplace_to_simd(&mplace) - } - pub fn local_to_place( &self, frame: usize, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d29e69d753e..55f85573f38 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -153,7 +153,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - let destination = self.eval_place(destination)?; + let destination = self.force_allocation(&self.eval_place(destination)?)?; self.eval_fn_call( fn_val, (fn_sig.abi, fn_abi), @@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, - destination: &PlaceTy<'tcx, M::Provenance>, + destination: &MPlaceTy<'tcx, M::Provenance>, target: Option<mir::BasicBlock>, mut unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -726,7 +726,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }); } // Protect return place for in-place return value passing. - M::protect_in_place_function_argument(self, destination)?; + M::protect_in_place_function_argument(self, &destination.clone().into())?; // Don't forget to mark "initially live" locals as live. self.storage_live_for_always_live_locals()?; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index cd296c9662a..e06d1d245b2 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -418,7 +418,7 @@ 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 callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 768d98ce01e..c9bbe45b212 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -229,7 +229,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering(()).borrow().1), + PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().borrow().1), } } @@ -281,7 +281,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } AstTreeExpanded => { debug!("pretty-printing expanded AST"); - format!("{:#?}", ex.tcx().resolver_for_lowering(()).borrow().1) + format!("{:#?}", ex.tcx().resolver_for_lowering().borrow().1) } Hir(s) => { debug!("pretty printing HIR {:?}", s); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1b2993dabdb..7e5197f16f9 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -146,6 +146,8 @@ declare_features! ( (accepted, derive_default_enum, "1.62.0", Some(86985)), /// Allows the use of destructuring assignments. (accepted, destructuring_assignment, "1.59.0", Some(71126)), + /// Allows using the `#[diagnostic]` attribute tool namespace + (accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146)), /// Allows `..` in tuple (struct) patterns. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 17c4d81474e..9f4bead21dc 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -436,8 +436,6 @@ declare_features! ( (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), - /// Allows using the `#[diagnostic]` attribute tool namespace - (unstable, diagnostic_namespace, "1.73.0", Some(111996)), /// Controls errors in trait implementations. (unstable, do_not_recommend, "1.67.0", Some(51992)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b8cf72c2c73..325342d653d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .any(|impl_def_id| { let impl_header = tcx.impl_trait_header(impl_def_id); impl_header.is_some_and(|header| { - let header = header.instantiate( + let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { @@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infcx .can_eq( ty::ParamEnv::empty(), - header.trait_ref.self_ty(), + trait_ref.self_ty(), value, ) && header.polarity != ty::ImplPolarity::Negative }) @@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) - && header.skip_binder().polarity != ty::ImplPolarity::Negative + && header.polarity != ty::ImplPolarity::Negative }) - .map(|header| header.instantiate_identity().trait_ref.self_ty()) + .map(|header| header.trait_ref.instantiate_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 7705445ffaa..b9543c7a29b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, - // FIXME: This should be `true`, but we don't really handle - // associated type bounds or type aliases in objects in a way - // that makes this meaningful, I think. - OnlySelfBounds(false), + // True so we don't populate `bounds` with associated type bounds, even + // though they're disallowed from object types. + OnlySelfBounds(true), ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expanded_traits = traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; let additional_trait = ®ular_traits[1]; @@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { + for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); let bound_predicate = pred.kind(); @@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); + let existential_projections = projection_bounds.iter().map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.dcx().span_delayed_bug( - span, - "trait object projection bounds reference `Self`", - ); - let args: Vec<_> = b - .projection_ty - .args - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return Ty::new_error(tcx, guar).into(); - } - arg - }) - .collect(); - b.projection_ty.args = tcx.mk_args(&args); + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; } + false + }); + if references_self { + let guar = tcx + .dcx() + .span_delayed_bug(span, "trait object projection bounds reference `Self`"); + let args: Vec<_> = b + .projection_ty + .args + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return Ty::new_error(tcx, guar).into(); + } + arg + }) + .collect(); + b.projection_ty.args = tcx.mk_args(&args); + } - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 845bbdca96a..748571c12b3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -530,11 +530,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { - check_impl_items_against_trait( - tcx, - def_id, - impl_trait_header.instantiate_identity(), - ); + check_impl_items_against_trait(tcx, def_id, impl_trait_header); check_on_unimplemented(tcx, def_id); } } @@ -725,10 +721,11 @@ fn check_impl_items_against_trait<'tcx>( impl_id: LocalDefId, impl_trait_header: ty::ImplTraitHeader<'tcx>, ) { + let trait_ref = impl_trait_header.trait_ref.instantiate_identity(); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. - if impl_trait_header.references_error() { + if trait_ref.references_error() { return; } @@ -752,7 +749,7 @@ fn check_impl_items_against_trait<'tcx>( } } - let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id); + let trait_def = tcx.trait_def(trait_ref.def_id); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); @@ -771,10 +768,10 @@ fn check_impl_items_against_trait<'tcx>( )); } ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); } ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); } } @@ -794,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( let mut must_implement_one_of: Option<&[Ident]> = trait_def.must_implement_one_of.as_deref(); - for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) { + for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) { let leaf_def = ancestors.leaf_def(tcx, trait_item_id); let is_implemented = leaf_def @@ -872,7 +869,7 @@ fn check_impl_items_against_trait<'tcx>( if let Some(missing_items) = must_implement_one_of { let attr_span = tcx - .get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of) + .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); missing_items_must_implement_one_of_err( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index bec7b7bd974..ae7ea271c56 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -247,7 +247,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Impl(impl_) => { let header = tcx.impl_trait_header(def_id); let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id)); + .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); + + crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); @@ -259,7 +261,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() .emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match header.map(|h| h.skip_binder().polarity) { + match header.map(|h| h.polarity) { // `None` means this is an inherent impl Some(ty::ImplPolarity::Positive) | None => { res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); @@ -296,31 +298,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, hir_generics) => { let res = check_type_defn(tcx, item, false); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } hir::ItemKind::Trait(..) => check_trait(tcx, item), hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, ast_generics) => { + hir::ItemKind::TyAlias(hir_ty, hir_generics) => { if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } else { Ok(()) @@ -1275,16 +1277,16 @@ fn check_item_type( }) } -#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] +#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - ast_self_ty: &hir::Ty<'_>, - ast_trait_ref: &Option<hir::TraitRef<'_>>, + hir_self_ty: &hir::Ty<'_>, + hir_trait_ref: &Option<hir::TraitRef<'_>>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - match ast_trait_ref { - Some(ast_trait_ref) => { + match hir_trait_ref { + Some(hir_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). @@ -1292,8 +1294,9 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; + let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( - ast_trait_ref.path.span, + trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); @@ -1304,14 +1307,23 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_def_id, trait_pred, - ast_trait_ref.path.span, + trait_span, item, ); for obligation in &mut obligations { + if obligation.cause.span != trait_span { + // We already have a better span. + continue; + } if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() - && pred.self_ty().skip_binder() == trait_ref.self_ty() + && pred.skip_binder().self_ty() == trait_ref.self_ty() + { + obligation.cause.span = hir_self_ty.span; + } + if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; } } debug!(?obligations); @@ -1325,7 +1337,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - ast_self_ty.span, + hir_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 6c3a9b747ef..8d8b13d6cb3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait<'tcx>( +pub(super) fn check_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, @@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> { fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; // Destructors only work on local ADT types. - match header.trait_ref.self_ty().kind() { + match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Error(_) => return Ok(()), _ => {} @@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let impl_did = checker.impl_def_id; debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let self_type = impl_header.trait_ref.self_ty(); + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); let param_env = tcx.param_env(impl_did); @@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E let tcx = checker.tcx; let header = checker.impl_header; let impl_did = checker.impl_def_id; - let self_type = header.trait_ref.self_ty(); + let self_type = header.trait_ref.instantiate_identity().self_ty(); assert!(!self_type.has_escaping_bound_vars()); let param_env = tcx.param_env(impl_did); @@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; - let trait_ref = header.trait_ref; + let trait_ref = checker.impl_header.trait_ref.instantiate_identity(); debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index d6281fa08f7..fc7a73e12be 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + let trait_def = tcx.trait_def(trait_ref.def_id); - res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 53a5ada4105..13ce4f07593 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,9 +13,10 @@ pub(super) fn check_item( trait_header: ImplTraitHeader<'_>, trait_def: &TraitDef, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = trait_header.trait_ref; let unsafe_attr = tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { let span = tcx.def_span(def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2cc37651ef5..e1704ffc8bf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1519,10 +1519,7 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header( - tcx: TyCtxt<'_>, - def_id: LocalDefId, -) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id); let impl_ = item.expect_impl(); @@ -1558,11 +1555,11 @@ fn impl_trait_header( } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) }; - ty::EarlyBinder::bind(ty::ImplTraitHeader { - trait_ref, + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) - }) + } }) } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9cc6c16c126..c86788db988 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -14,6 +14,43 @@ use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; + // For an RPITIT, synthesize generics which are equal to the opaque's generics + // and parent fn's generics compressed into one list. + if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = + tcx.opt_rpitit_info(def_id.to_def_id()) + { + let trait_def_id = tcx.parent(fn_def_id); + let opaque_ty_generics = tcx.generics_of(opaque_def_id); + let opaque_ty_parent_count = opaque_ty_generics.parent_count; + let mut params = opaque_ty_generics.params.clone(); + + let parent_generics = tcx.generics_of(trait_def_id); + let parent_count = parent_generics.parent_count + parent_generics.params.len(); + + let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone(); + + for param in &mut params { + param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32 + - opaque_ty_parent_count as u32; + } + + trait_fn_params.extend(params); + params = trait_fn_params; + + let param_def_id_to_index = + params.iter().map(|param| (param.def_id, param.index)).collect(); + + return ty::Generics { + parent: Some(trait_def_id), + parent_count, + params, + param_def_id_to_index, + has_self: opaque_ty_generics.has_self, + has_late_bound_regions: opaque_ty_generics.has_late_bound_regions, + host_effect_index: parent_generics.host_effect_index, + }; + } + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 417f0fceaa8..2217e5280a7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,7 +5,7 @@ use rustc_hir::HirId; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -350,22 +350,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the // associated type in the impl. - if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = - tcx.opt_rpitit_info(def_id.to_def_id()) - { - match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { - Ok(map) => { - let assoc_item = tcx.associated_item(def_id); - return map[&assoc_item.trait_item_def_id.unwrap()]; - } - Err(_) => { - return ty::EarlyBinder::bind(Ty::new_error_with_message( - tcx, - DUMMY_SP, - "Could not collect return position impl trait in trait tys", - )); + match tcx.opt_rpitit_info(def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => { + match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { + Ok(map) => { + let assoc_item = tcx.associated_item(def_id); + return map[&assoc_item.trait_item_def_id.unwrap()]; + } + Err(_) => { + return ty::EarlyBinder::bind(Ty::new_error_with_message( + tcx, + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + )); + } } } + // For an RPITIT in a trait, just return the corresponding opaque. + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return ty::EarlyBinder::bind(Ty::new_opaque( + tcx, + opaque_def_id, + ty::GenericArgs::identity_for_item(tcx, opaque_def_id), + )); + } + None => {} } let hir_id = tcx.local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 9d7866fe3e0..caa85092415 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -14,8 +14,7 @@ use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; -use rustc_middle::query::Providers; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; @@ -51,23 +50,16 @@ mod min_specialization; /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> { +pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; - let module = tcx.hir_module_items(module_def_id); let mut res = Ok(()); - for id in module.items() { - if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) { - res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id)); - if min_specialization { - res = res.and(check_min_specialization(tcx, id.owner_id.def_id)); - } - } + debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. })); + res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id)); + if min_specialization { + res = res.and(check_min_specialization(tcx, impl_def_id)); } - res -} -pub fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_impl_wf, ..*providers }; + res } fn enforce_impl_params_are_constrained( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7cb103626da..77c4ff382b9 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -153,7 +153,6 @@ pub fn provide(providers: &mut Providers) { check_unused::provide(providers); variance::provide(providers); outlives::provide(providers); - impl_wf_check::provide(providers); hir_wf_check::provide(providers); } @@ -171,9 +170,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { } tcx.sess.time("coherence_checking", || { - // Check impls constrain their parameters - let res = - tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); + tcx.hir().par_for_each_module(|module| { + let _ = tcx.ensure().check_mod_type_wf(module); + }); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { let _ = tcx.ensure().coherent_trait(trait_def_id); @@ -181,19 +180,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // these queries are executed for side-effects (error reporting): let _ = tcx.ensure().crate_inherent_impls(()); let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); - res - })?; + }); if tcx.features().rustc_attrs { tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; } - tcx.sess.time("wf_checking", || { - tcx.hir().par_for_each_module(|module| { - let _ = tcx.ensure().check_mod_type_wf(module); - }) - }); - if tcx.features().rustc_attrs { collect::test_opaque_hidden_types(tcx)?; } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 893b3f9534d..7012f40e349 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3368,11 +3368,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "inherent impls can't be candidates, only trait impls can be", ) }) - .filter(|header| { - header.skip_binder().polarity == ty::ImplPolarity::Negative - }) + .filter(|header| header.polarity == ty::ImplPolarity::Negative) .any(|header| { - let imp = header.instantiate_identity().trait_ref; + let imp = header.trait_ref.instantiate_identity(); let imp_simp = simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); imp_simp.is_some_and(|s| s == simp_rcvr_ty) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index d876174e620..88298150a79 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -12,7 +12,24 @@ use std::vec; use crate::{Idx, IndexSlice}; /// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`. -/// Its purpose is to avoid mixing indexes. +/// +/// ## Why use this instead of a `Vec`? +/// +/// An `IndexVec` allows element access only via a specific associated index type, meaning that +/// trying to use the wrong index type (possibly accessing an invalid element) will fail at +/// compile time. +/// +/// It also documents what the index is indexing: in a `HashMap<usize, Something>` it's not +/// immediately clear what the `usize` means, while a `HashMap<FieldIdx, Something>` makes it obvious. +/// +/// ```compile_fail +/// use rustc_index::{Idx, IndexVec}; +/// +/// fn f<I1: Idx, I2: Idx>(vec1: IndexVec<I1, u8>, idx1: I1, idx2: I2) { +/// &vec1[idx1]; // Ok +/// &vec1[idx2]; // Compile error! +/// } +/// ``` /// /// While it's possible to use `u32` or `usize` directly for `I`, /// you almost certainly want to use a [`newtype_index!`]-generated type instead. diff --git a/compiler/rustc_infer/src/infer/higher_ranked/README.md b/compiler/rustc_infer/src/infer/higher_ranked/README.md deleted file mode 100644 index 533d0ef7e6c..00000000000 --- a/compiler/rustc_infer/src/infer/higher_ranked/README.md +++ /dev/null @@ -1,8 +0,0 @@ -To learn more about how Higher-ranked trait bounds work in the _old_ trait -solver, see [this chapter][oldhrtb] of the rustc-dev-guide. - -To learn more about how they work in the _new_ trait solver, see [this -chapter][newhrtb]. - -[oldhrtb]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html -[newhrtb]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 73a25637e1a..15cdd6a910e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,23 +1,25 @@ -pub use self::at::DefineOpaqueTypes; -pub use self::freshen::TypeFreshener; -pub use self::lexical_region_resolve::RegionResolutionError; -pub use self::BoundRegionConversionTime::*; -pub use self::RegionVariableOrigin::*; -pub use self::SubregionOrigin::*; -pub use self::ValuePairs::*; +pub use at::DefineOpaqueTypes; +pub use freshen::TypeFreshener; +pub use lexical_region_resolve::RegionResolutionError; +pub use relate::combine::CombineFields; pub use relate::combine::ObligationEmittingRelation; -use rustc_data_structures::captures::Captures; -use rustc_data_structures::undo_log::UndoLogs; -use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; - -use self::opaque_types::OpaqueTypeStorage; -pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; +pub use relate::StructurallyRelateAliases; +pub use rustc_middle::ty::IntVarValue; +pub use BoundRegionConversionTime::*; +pub use RegionVariableOrigin::*; +pub use SubregionOrigin::*; +pub use ValuePairs::*; use crate::traits::{ self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, }; - +use error_reporting::TypeErrCtxt; +use free_regions::RegionRelations; +use lexical_region_resolve::LexicalRegionResolutions; +use opaque_types::OpaqueTypeStorage; +use region_constraints::{GenericKind, VarInfos, VerifyBound}; +use region_constraints::{RegionConstraintCollector, RegionConstraintStorage}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -27,7 +29,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::ConstVariableValue; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -36,33 +40,21 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::visit::TypeVisitableExt; -pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_span::symbol::Symbol; use rustc_span::Span; - +use snapshot::undo_log::InferCtxtUndoLogs; use std::cell::{Cell, RefCell}; use std::fmt; - -use self::error_reporting::TypeErrCtxt; -use self::free_regions::RegionRelations; -use self::lexical_region_resolve::LexicalRegionResolutions; -use self::region_constraints::{GenericKind, VarInfos, VerifyBound}; -use self::region_constraints::{ - RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, -}; -pub use self::relate::combine::CombineFields; -pub use self::relate::StructurallyRelateAliases; -use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; pub mod at; pub mod canonical; pub mod error_reporting; pub mod free_regions; mod freshen; -mod fudge; mod lexical_region_resolve; pub mod opaque_types; pub mod outlives; @@ -70,8 +62,8 @@ mod projection; pub mod region_constraints; mod relate; pub mod resolve; +pub(crate) mod snapshot; pub mod type_variable; -mod undo_log; #[must_use] #[derive(Debug)] @@ -738,13 +730,6 @@ impl<'tcx> InferOk<'tcx, ()> { } } -#[must_use = "once you start a snapshot, you should always consume it"] -pub struct CombinedSnapshot<'tcx> { - undo_snapshot: Snapshot<'tcx>, - region_constraints_snapshot: RegionSnapshot, - universe: ty::UniverseIndex, -} - impl<'tcx> InferCtxt<'tcx> { pub fn dcx(&self) -> &'tcx DiagCtxt { self.tcx.dcx() @@ -842,90 +827,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn in_snapshot(&self) -> bool { - UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log) - } - - pub fn num_open_snapshots(&self) -> usize { - UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log) - } - - fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { - debug!("start_snapshot()"); - - let mut inner = self.inner.borrow_mut(); - - CombinedSnapshot { - undo_snapshot: inner.undo_log.start_snapshot(), - region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), - universe: self.universe(), - } - } - - #[instrument(skip(self, snapshot), level = "debug")] - fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; - - self.universe.set(universe); - - let mut inner = self.inner.borrow_mut(); - inner.rollback_to(undo_snapshot); - inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); - } - - #[instrument(skip(self, snapshot), level = "debug")] - fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } = - snapshot; - - self.inner.borrow_mut().commit(undo_snapshot); - } - - /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. - #[instrument(skip(self, f), level = "debug")] - pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> - where - F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>, - { - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); - match r { - Ok(_) => { - self.commit_from(snapshot); - } - Err(_) => { - self.rollback_to(snapshot); - } - } - r - } - - /// Execute `f` then unroll any bindings it creates. - #[instrument(skip(self, f), level = "debug")] - pub fn probe<R, F>(&self, f: F) -> R - where - F: FnOnce(&CombinedSnapshot<'tcx>) -> R, - { - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - self.rollback_to(snapshot); - r - } - - /// Scan the constraints produced since `snapshot` and check whether - /// we added any region constraints. - pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { - self.inner - .borrow_mut() - .unwrap_region_constraints() - .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) - } - - pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { - self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) - } - pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index b6f3c38cb3f..b6f3c38cb3f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 9f49ed00219..a7ddf475436 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,7 +1,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty}; -use crate::infer::{InferCtxtUndoLogs, UndoLog}; +use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog}; use super::{OpaqueTypeDecl, OpaqueTypeMap}; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 8dd3a1f40cc..fe323982ec0 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -63,9 +63,8 @@ use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::resolve::OpportunisticRegionResolver; -use crate::infer::{ - self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, -}; +use crate::infer::snapshot::undo_log::UndoLog; +use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 9e2f3a10b6a..06f8dd4a4c6 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -1,9 +1,7 @@ use super::*; -use crate::infer::CombinedSnapshot; -use rustc_data_structures::{ - fx::FxIndexMap, - graph::{scc::Sccs, vec_graph::VecGraph}, -}; +use crate::infer::snapshot::CombinedSnapshot; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph}; use rustc_index::Idx; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index ee97dd36807..0f3f2bc5fa6 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -3,9 +3,8 @@ use self::CombineMapType::*; use self::UndoLog::*; -use super::{ - InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, -}; +use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin}; +use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -360,7 +359,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// /// Not legal during a snapshot. pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { - assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log)); + assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&self.undo_log)); (mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data)) } @@ -377,7 +376,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// /// Not legal during a snapshot. pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> { - assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log)); + assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&self.undo_log)); // If you add a new field to `RegionConstraintCollector`, you // should think carefully about whether it needs to be cleared diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index f30e366c198..70ed7cf9af1 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -1,7 +1,7 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use crate::infer::CombinedSnapshot; +use crate::infer::snapshot::CombinedSnapshot; use crate::infer::InferCtxt; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::RelateResult; @@ -77,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> { // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. let value = self.enter_forall_and_leak_universe(forall); - debug!("?value"); + debug!(?value); f(value) } diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 99033922bdf..14de461cd17 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -2,9 +2,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; -use super::type_variable::TypeVariableOrigin; -use super::InferCtxt; -use super::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable}; +use crate::infer::type_variable::TypeVariableOrigin; +use crate::infer::InferCtxt; +use crate::infer::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable}; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs new file mode 100644 index 00000000000..9eef1471b1a --- /dev/null +++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs @@ -0,0 +1,102 @@ +use super::region_constraints::RegionSnapshot; +use super::InferCtxt; +use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::ty; + +mod fudge; +pub(crate) mod undo_log; + +use undo_log::{Snapshot, UndoLog}; + +#[must_use = "once you start a snapshot, you should always consume it"] +pub struct CombinedSnapshot<'tcx> { + pub(super) undo_snapshot: Snapshot<'tcx>, + region_constraints_snapshot: RegionSnapshot, + universe: ty::UniverseIndex, +} + +impl<'tcx> InferCtxt<'tcx> { + pub fn in_snapshot(&self) -> bool { + UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log) + } + + pub fn num_open_snapshots(&self) -> usize { + UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log) + } + + fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { + debug!("start_snapshot()"); + + let mut inner = self.inner.borrow_mut(); + + CombinedSnapshot { + undo_snapshot: inner.undo_log.start_snapshot(), + region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), + universe: self.universe(), + } + } + + #[instrument(skip(self, snapshot), level = "debug")] + fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; + + self.universe.set(universe); + + let mut inner = self.inner.borrow_mut(); + inner.rollback_to(undo_snapshot); + inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); + } + + #[instrument(skip(self, snapshot), level = "debug")] + fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } = + snapshot; + + self.inner.borrow_mut().commit(undo_snapshot); + } + + /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. + #[instrument(skip(self, f), level = "debug")] + pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> + where + F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>, + { + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); + match r { + Ok(_) => { + self.commit_from(snapshot); + } + Err(_) => { + self.rollback_to(snapshot); + } + } + r + } + + /// Execute `f` then unroll any bindings it creates. + #[instrument(skip(self, f), level = "debug")] + pub fn probe<R, F>(&self, f: F) -> R + where + F: FnOnce(&CombinedSnapshot<'tcx>) -> R, + { + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + self.rollback_to(snapshot); + r + } + + /// Scan the constraints produced since `snapshot` and check whether + /// we added any region constraints. + pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { + self.inner + .borrow_mut() + .unwrap_region_constraints() + .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) + } + + pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { + self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) + } +} diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 829b0a73a0d..829b0a73a0d 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index afba2e50a23..31ceb234332 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -2,7 +2,7 @@ use super::PredicateObligation; -use crate::infer::InferCtxtUndoLogs; +use crate::infer::snapshot::undo_log::InferCtxtUndoLogs; use rustc_data_structures::{ snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 085e9026051..4b4c1d6cf67 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -280,7 +280,7 @@ fn configure_and_expand( fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; - let (resolver, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let (resolver, krate) = &*tcx.resolver_for_lowering().borrow(); let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { @@ -531,10 +531,10 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } -fn resolver_for_lowering<'tcx>( +fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> { +) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -549,16 +549,15 @@ fn resolver_for_lowering<'tcx>( ast_lowering: untracked_resolver_for_lowering, } = resolver.into_outputs(); - let feed = tcx.feed_unit_query(); - feed.resolutions(tcx.arena.alloc(untracked_resolutions)); - tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) + let resolutions = tcx.arena.alloc(untracked_resolutions); + (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) } pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { // Make sure name resolution and macro expansion is run for // the side-effect of providing a complete set of all // accessed files and env vars. - let _ = tcx.resolver_for_lowering(()); + let _ = tcx.resolver_for_lowering(); let sess = tcx.sess; let _timer = sess.timer("write_dep_info"); @@ -607,7 +606,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; - providers.resolver_for_lowering = resolver_for_lowering; + providers.resolver_for_lowering_raw = resolver_for_lowering_raw; + providers.stripped_cfg_items = + |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); + providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); @@ -686,6 +688,11 @@ pub fn create_global_ctxt<'tcx>( /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { + if tcx.sess.opts.unstable_opts.hir_stats { + rustc_passes::hir_stats::print_hir_stats(tcx); + } + + #[cfg(debug_assertions)] rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 7cdf7cd25b1..da11d090b74 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -8,8 +8,7 @@ use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; use rustc_metadata::creader::CStore; @@ -144,10 +143,8 @@ impl<'tcx> Queries<'tcx> { stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); - let source_span = AppendOnlyIndexVec::new(); - let _id = source_span.push(krate.spans.inner_span); - debug_assert_eq!(_id, CRATE_DEF_ID); - let untracked = Untracked { cstore, source_span, definitions }; + let untracked = + Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions }; let qcx = passes::create_global_ctxt( self.compiler, @@ -172,9 +169,6 @@ impl<'tcx> Queries<'tcx> { ))); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); - - let feed = tcx.feed_local_def_id(CRATE_DEF_ID); - feed.def_kind(DefKind::Mod); }); Ok(qcx) }) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index a58a37bf3ac..a0be1c09c9a 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -143,7 +143,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di BuiltinLintDiag::RedundantImport(spans, ident) => { for (span, is_imported) in spans { let introduced = if is_imported { "imported" } else { "defined" }; - diag.span_label(span, format!("the item `{ident}` is already {introduced} here")); + let span_msg = if span.is_dummy() { "by prelude" } else { "here" }; + diag.span_label( + span, + format!("the item `{ident}` is already {introduced} {span_msg}"), + ); } } BuiltinLintDiag::DeprecatedMacro(suggestion, span) => { diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6cb6fd1cbd5..a4fd5a7c45f 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -14,6 +14,7 @@ declare_lint! { /// ### Example /// /// ```rust + /// #![warn(non_local_definitions)] /// trait MyTrait {} /// struct MyStruct; /// @@ -36,7 +37,7 @@ declare_lint! { /// All nested bodies (functions, enum discriminant, array length, consts) (expect for /// `const _: Ty = { ... }` in top-level module, which is still undecided) are checked. pub NON_LOCAL_DEFINITIONS, - Warn, + Allow, "checks for non-local definitions", report_in_external_macro } diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 6598f1db86d..c206380a06f 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -8,12 +8,7 @@ edition = "2021" libc = "0.2.73" # tidy-alphabetical-end -# FIXME: updating cc past 1.0.79 breaks libstd bootstrapping, pin -# to the last working version here so `cargo update` doesn't cause the -# a higher version to be selected -# https://github.com/rust-lang/cc-rs/issues/913 -# 1.0.{84, 85} fix this but have been yanked [build-dependencies] # tidy-alphabetical-start -cc = "=1.0.79" +cc = "1.0.90" # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 627be997513..60789b07e54 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -120,7 +120,7 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( } auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs)); - RawRustStringOstream OS(BufferOut); + auto OS = RawRustStringOstream(BufferOut); FilenamesWriter.write(OS); } @@ -160,7 +160,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs), Expressions, MappingRegions); - RawRustStringOstream OS(BufferOut); + auto OS = RawRustStringOstream(BufferOut); CoverageMappingWriter.write(OS); } @@ -168,23 +168,23 @@ extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar( LLVMValueRef F, const char *FuncName, size_t FuncNameLen) { - StringRef FuncNameRef(FuncName, FuncNameLen); + auto FuncNameRef = StringRef(FuncName, FuncNameLen); return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef)); } extern "C" uint64_t LLVMRustCoverageHashByteArray( const char *Bytes, size_t NumBytes) { - StringRef StrRef(Bytes, NumBytes); + auto StrRef = StringRef(Bytes, NumBytes); return IndexedInstrProf::ComputeHash(StrRef); } static void WriteSectionNameToString(LLVMModuleRef M, InstrProfSectKind SK, RustStringRef Str) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); + auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat()); - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); OS << name; } @@ -200,7 +200,7 @@ extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M, extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { auto name = getCoverageMappingVarName(); - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); OS << name; } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4ec784e2590..1cdfc22431e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -77,9 +77,9 @@ extern "C" void LLVMRustTimeTraceProfilerFinishThread() { } extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) { - StringRef FN(FileName); + auto FN = StringRef(FileName); std::error_code EC; - raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways); + auto OS = raw_fd_ostream(FN, EC, sys::fs::CD_CreateAlways); timeTraceProfilerWrite(OS); timeTraceProfilerCleanup(); @@ -424,7 +424,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( auto CM = fromRust(RustCM); std::string Error; - Triple Trip(Triple::normalize(TripleStr)); + auto Trip = Triple(Triple::normalize(TripleStr)); const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(), Error); if (TheTarget == nullptr) { @@ -537,8 +537,8 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { // TargetLibraryInfo pass, so we use this method to do so. extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl TLII(TargetTriple); + auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); + auto TLII = TargetLibraryInfoImpl(TargetTriple); if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); @@ -589,7 +589,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::OF_None); + auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -597,9 +597,9 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Failure; } - buffer_ostream BOS(OS); + auto BOS = buffer_ostream(OS); if (DwoPath) { - raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None); + auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None); EC.clear(); if (EC) ErrorInfo = EC.message(); @@ -607,7 +607,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, LLVMRustSetLastError(ErrorInfo.c_str()); return LLVMRustResult::Failure; } - buffer_ostream DBOS(DOS); + auto DBOS = buffer_ostream(DOS); unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false); PM->run(*unwrap(M)); } else { @@ -796,7 +796,7 @@ LLVMRustOptimize( DebugInfoForProfiling); } - PassBuilder PB(TM, PTO, PGOOpt, &PIC); + auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC); LoopAnalysisManager LAM; FunctionAnalysisManager FAM; CGSCCAnalysisManager CGAM; @@ -1112,7 +1112,7 @@ extern "C" LLVMRustResult LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { std::string ErrorInfo; std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::OF_None); + auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None); if (EC) ErrorInfo = EC.message(); if (ErrorInfo != "") { @@ -1120,8 +1120,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { return LLVMRustResult::Failure; } - RustAssemblyAnnotationWriter AAW(Demangle); - formatted_raw_ostream FOS(OS); + auto AAW = RustAssemblyAnnotationWriter(Demangle); + auto FOS = formatted_raw_ostream(OS); unwrap(M)->print(FOS, &AAW); return LLVMRustResult::Success; @@ -1281,8 +1281,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // Load each module's summary and merge it into one combined index for (int i = 0; i < num_modules; i++) { auto module = &modules[i]; - StringRef buffer(module->data, module->len); - MemoryBufferRef mem_buffer(buffer, module->identifier); + auto buffer = StringRef(module->data, module->len); + auto mem_buffer = MemoryBufferRef(buffer, module->identifier); Ret->ModuleMap[module->identifier] = mem_buffer; @@ -1485,7 +1485,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, return MOrErr; }; bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target); - FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal); + auto Importer = FunctionImporter(Data->Index, Loader, ClearDSOLocal); Expected<bool> Result = Importer.importFunctions(Mod, ImportList); if (!Result) { LLVMRustSetLastError(toString(Result.takeError()).c_str()); @@ -1510,7 +1510,7 @@ extern "C" LLVMRustThinLTOBuffer* LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { auto Ret = std::make_unique<LLVMRustThinLTOBuffer>(); { - raw_string_ostream OS(Ret->data); + auto OS = raw_string_ostream(Ret->data); { if (is_thin) { PassBuilder PB; @@ -1557,8 +1557,8 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context, const char *data, size_t len, const char *identifier) { - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, identifier); + auto Data = StringRef(data, len); + auto Buffer = MemoryBufferRef(Data, identifier); unwrap(Context)->enableDebugTypeODRUniquing(); Expected<std::unique_ptr<Module>> SrcOrError = parseBitcodeFile(Buffer, *unwrap(Context)); @@ -1576,8 +1576,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, const char *name, size_t *out_len) { *out_len = 0; - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, ""); // The id is unused. + auto Data = StringRef(data, len); + auto Buffer = MemoryBufferRef(Data, ""); // The id is unused. file_magic Type = identify_magic(Buffer.getBuffer()); Expected<std::unique_ptr<object::ObjectFile>> ObjFileOrError = object::ObjectFile::createObjectFile(Buffer, Type); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index cb7cce4da0d..d9262a92782 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -66,12 +66,22 @@ static LLVM_THREAD_LOCAL char *LastError; static void FatalErrorHandler(void *UserData, const char* Reason, bool GenCrashDiag) { - // Do the same thing that the default error handler does. - std::cerr << "LLVM ERROR: " << Reason << std::endl; + // Once upon a time we emitted "LLVM ERROR:" specifically to mimic LLVM. Then, + // we developed crater and other tools which only expose logs, not error codes. + // Use a more greppable prefix that will still match the "LLVM ERROR:" prefix. + std::cerr << "rustc-LLVM ERROR: " << Reason << std::endl; // Since this error handler exits the process, we have to run any cleanup that // LLVM would run after handling the error. This might change with an LLVM // upgrade. + // + // In practice, this will do nothing, because the only cleanup LLVM does is + // to remove all files that were registered with it via a frontend calling + // one of the `createOutputFile` family of functions in LLVM and passing true + // to RemoveFileOnSignal, something that rustc does not do. However, it would + // be... inadvisable to suddenly stop running these handlers, if LLVM gets + // "interesting" ideas in the future about what cleanup should be done. + // We might even find it useful for generating less artifacts. sys::RunInterruptHandlers(); exit(101); @@ -109,7 +119,7 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M, extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { std::string buf; - raw_string_ostream SS(buf); + auto SS = raw_string_ostream(buf); TimerGroup::printAll(SS); SS.flush(); *Len = buf.length(); @@ -120,7 +130,7 @@ extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) { extern "C" const char *LLVMRustPrintStatistics(size_t *Len) { std::string buf; - raw_string_ostream SS(buf); + auto SS = raw_string_ostream(buf); llvm::PrintStatistics(SS); SS.flush(); *Len = buf.length(); @@ -174,7 +184,7 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { Module *Mod = unwrap(M); - StringRef NameRef(Name, NameLen); + auto NameRef = StringRef(Name, NameLen); // We don't use Module::getOrInsertGlobal because that returns a Constant*, // which may either be the real GlobalVariable*, or a constant bitcast of it @@ -285,7 +295,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { template<typename T> static inline void AddAttributes(T *t, unsigned Index, LLVMAttributeRef *Attrs, size_t AttrsLen) { AttributeList PAL = t->getAttributes(); - AttrBuilder B(t->getContext()); + auto B = AttrBuilder(t->getContext()); for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen)) B.addAttribute(unwrap(Attr)); AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B); @@ -1195,13 +1205,13 @@ extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() { } extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); unwrap<llvm::Type>(Ty)->print(OS); } extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); if (!V) { OS << "(null)"; } else { @@ -1224,7 +1234,7 @@ extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); unwrap(T)->print(OS); } @@ -1236,11 +1246,11 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( llvm::DiagnosticInfoOptimizationBase *Opt = static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI)); - RawRustStringOstream PassNameOS(PassNameOut); + auto PassNameOS = RawRustStringOstream(PassNameOut); PassNameOS << Opt->getPassName(); *FunctionOut = wrap(&Opt->getFunction()); - RawRustStringOstream FilenameOS(FilenameOut); + auto FilenameOS = RawRustStringOstream(FilenameOut); DiagnosticLocation loc = Opt->getLocation(); if (loc.isValid()) { *Line = loc.getLine(); @@ -1248,7 +1258,7 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( FilenameOS << loc.getAbsolutePath(); } - RawRustStringOstream MessageOS(MessageOut); + auto MessageOS = RawRustStringOstream(MessageOut); MessageOS << Opt->getMsg(); } @@ -1291,8 +1301,8 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI, RustStringRef Str) { - RawRustStringOstream OS(Str); - DiagnosticPrinterRawOStream DP(OS); + auto OS = RawRustStringOstream(Str); + auto DP = DiagnosticPrinterRawOStream(OS); unwrap(DI)->print(DP); } @@ -1406,7 +1416,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { default: { std::string error; - llvm::raw_string_ostream stream(error); + auto stream = llvm::raw_string_ostream(error); stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID() << " for the type: " << *unwrap(Ty); stream.flush(); @@ -1432,7 +1442,7 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, unsigned* RangesOut, size_t* NumRanges) { SMDiagnostic& D = *unwrap(DRef); - RawRustStringOstream MessageOS(MessageOut); + auto MessageOS = RawRustStringOstream(MessageOut); MessageOS << D.getMessage(); switch (D.getKind()) { @@ -1547,7 +1557,7 @@ extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, const char *Name, size_t NameLen) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); + Triple TargetTriple = Triple(unwrap(M)->getTargetTriple()); GlobalObject *GV = unwrap<GlobalObject>(V); if (TargetTriple.supportsCOMDAT()) { StringRef NameRef(Name, NameLen); @@ -1711,7 +1721,7 @@ extern "C" LLVMRustModuleBuffer* LLVMRustModuleBufferCreate(LLVMModuleRef M) { auto Ret = std::make_unique<LLVMRustModuleBuffer>(); { - raw_string_ostream OS(Ret->data); + auto OS = raw_string_ostream(Ret->data); WriteBitcodeToFile(*unwrap(M), OS); } return Ret.release(); @@ -1741,8 +1751,8 @@ LLVMRustModuleCost(LLVMModuleRef M) { extern "C" void LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str) { - RawRustStringOstream OS(Str); - llvm::json::OStream JOS(OS); + auto OS = RawRustStringOstream(Str); + auto JOS = llvm::json::OStream(OS); auto Module = unwrap(M); JOS.object([&] { @@ -1857,7 +1867,7 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( MinGW); if (Error) { std::string errorString; - llvm::raw_string_ostream stream(errorString); + auto stream = llvm::raw_string_ostream(errorString); stream << Error; stream.flush(); LLVMRustSetLastError(errorString.c_str()); @@ -2041,7 +2051,7 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( } extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { - RawRustStringOstream OS(Str); + auto OS = RawRustStringOstream(Str); GlobalValue *GV = unwrap<GlobalValue>(V); Mangler().getNameWithPrefix(OS, GV, true); } diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index 91f84692df8..ee8239ef8e7 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/ObjectFile.h" +#include <llvm/Support/raw_ostream.h> using namespace llvm; using namespace llvm::sys; @@ -42,7 +43,7 @@ extern "C" void *LLVMRustGetSymbols( MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); SmallString<0> SymNameBuf; - raw_svector_ostream SymName(SymNameBuf); + auto SymName = raw_svector_ostream(SymNameBuf); // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. @@ -60,7 +61,7 @@ extern "C" void *LLVMRustGetSymbols( if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } @@ -70,7 +71,7 @@ extern "C" void *LLVMRustGetSymbols( if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } @@ -83,7 +84,7 @@ extern "C" void *LLVMRustGetSymbols( continue; if (Error E = S.printName(SymName)) { SmallString<0> ErrorBuf; - raw_svector_ostream Error(ErrorBuf); + auto Error = raw_svector_ostream(ErrorBuf); Error << E << '\0'; return ErrorCallback(Error.str().data()); } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 90e68a6b5b9..dcccace12b0 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1077,7 +1077,7 @@ impl CrateError { crate_rejections, }); } else { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info, @@ -1091,11 +1091,18 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } CrateError::NotFound(crate_name) => { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info: String::new(), @@ -1105,7 +1112,14 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3866d6fec2d..6e9cbfdcfee 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1993,9 +1993,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { record!(self.tables.impl_trait_header[def_id] <- header); - let trait_ref = header.map_bound(|h| h.trait_ref); - let trait_ref = trait_ref.instantiate_identity(); + let trait_ref = header.trait_ref.instantiate_identity(); let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 28166687606..8aa31ef564f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -423,7 +423,7 @@ define_tables! { variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, - impl_trait_header: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>, + impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>, const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>, object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index d0711baa181..33ee3371605 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -177,8 +177,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> { type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()]; } -impl EraseType for Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> { - type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>()]; +impl EraseType for Option<ty::ImplTraitHeader<'_>> { + type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()]; } impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b0431ae05d3..7c6e9762f2a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -125,12 +125,11 @@ rustc_queries! { } query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - feedable no_hash desc { "getting the resolver outputs" } } - query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> { + query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) { eval_always no_hash desc { "getting the resolver for lowering" } @@ -826,7 +825,7 @@ rustc_queries! { /// creates and returns the associated items that correspond to each impl trait in return position /// of the implemented trait. query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] { - desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) } + desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) } cache_on_disk_if { fn_def_id.is_local() } separate_provide_extern } @@ -834,13 +833,13 @@ rustc_queries! { /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding /// associated item. query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { - desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } + desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } cache_on_disk_if { true } } /// Given an `impl_id`, return the trait it implements along with some header information. /// Return `None` if this is an inherent impl. - query impl_trait_header(impl_id: DefId) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'tcx>>> { + query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern @@ -955,11 +954,6 @@ rustc_queries! { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } - ensure_forwards_result_if_red - } - query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } ensure_forwards_result_if_red @@ -2221,7 +2215,6 @@ rustc_queries! { /// Should not be called for the local crate before the resolver outputs are created, as it /// is only fed there. query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { - feedable desc { "getting cfg-ed out item names" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4eec93532a2..4f8e4aa90f4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,7 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal}; +use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; #[cfg(parallel_compiler)] use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordSet; @@ -60,7 +60,7 @@ use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_session::{Limit, MetadataKind, Session}; -use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::def_id::{DefPathHash, StableCrateId, CRATE_DEF_ID}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; @@ -74,6 +74,7 @@ use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter; +use std::marker::PhantomData; use std::mem; use std::ops::{Bound, Deref}; @@ -498,14 +499,55 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> { key: KEY, } +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl<KEY: Copy, CTX> !HashStable<CTX> for TyCtxtFeed<'_, KEY> {} + +/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`. +/// Use this to pass around when you have a `TyCtxt` elsewhere. +/// Just an optimization to save space and not store hundreds of +/// `TyCtxtFeed` in the resolver. +#[derive(Copy, Clone)] +pub struct Feed<'tcx, KEY: Copy> { + _tcx: PhantomData<TyCtxt<'tcx>>, + // Do not allow direct access, as downstream code must not mutate this field. + key: KEY, +} + +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl<KEY: Copy, CTX> !HashStable<CTX> for Feed<'_, KEY> {} + +impl<T: fmt::Debug + Copy> fmt::Debug for Feed<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.key.fmt(f) + } +} + +/// Some workarounds to use cases that cannot use `create_def`. +/// Do not add new ways to create `TyCtxtFeed` without consulting +/// with T-compiler and making an analysis about why your addition +/// does not cause incremental compilation issues. impl<'tcx> TyCtxt<'tcx> { + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: () } } + + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } - pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> { + + /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed + /// some queries for it. It will panic if used twice. + pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> { + let key = self.untracked().source_span.push(span); + assert_eq!(key, CRATE_DEF_ID); TyCtxtFeed { tcx: self, key } } @@ -523,6 +565,23 @@ impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { pub fn key(&self) -> KEY { self.key } + + #[inline(always)] + pub fn downgrade(self) -> Feed<'tcx, KEY> { + Feed { _tcx: PhantomData, key: self.key } + } +} + +impl<'tcx, KEY: Copy> Feed<'tcx, KEY> { + #[inline(always)] + pub fn key(&self) -> KEY { + self.key + } + + #[inline(always)] + pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> { + TyCtxtFeed { tcx, key: self.key } + } } impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { @@ -1067,7 +1126,7 @@ impl<'tcx> TyCtxt<'tcx> { // needs to be re-evaluated. self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - let feed = self.feed_local_def_id(def_id); + let feed = TyCtxtFeed { tcx: self, key: def_id }; feed.def_kind(def_kind); // Unique types created for closures participate in type privacy checking. // They have visibilities inherited from the module they are defined in. @@ -2304,18 +2363,21 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } + pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> { + self.resolver_for_lowering_raw(()).0 + } + /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. pub fn impl_trait_ref( self, def_id: impl IntoQueryParam<DefId>, ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> { - Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref)) + Some(self.impl_trait_header(def_id)?.trait_ref) } pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity { - self.impl_trait_header(def_id) - .map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity) + self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 260d0885089..9fc8d418f5b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -694,6 +694,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] + // Keep me in sync with try_instantiate_mir_and_normalize_erasing_regions pub fn instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, @@ -701,16 +702,17 @@ impl<'tcx> Instance<'tcx> { v: EarlyBinder<T>, ) -> T where - T: TypeFoldable<TyCtxt<'tcx>> + Clone, + T: TypeFoldable<TyCtxt<'tcx>>, { if let Some(args) = self.args_for_mir_body() { tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { - tcx.normalize_erasing_regions(param_env, v.skip_binder()) + tcx.normalize_erasing_regions(param_env, v.instantiate_identity()) } } #[inline(always)] + // Keep me in sync with instantiate_mir_and_normalize_erasing_regions pub fn try_instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0a38d379a52..4edec0e6951 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,6 +32,7 @@ pub use generic_args::*; pub use generics::*; pub use intrinsic::IntrinsicDef; use rustc_ast as ast; +use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; pub use rustc_ast_ir::{try_visit, Movability, Mutability}; use rustc_attr as attr; @@ -85,7 +86,8 @@ pub use self::consts::{ Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, + tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, + TyCtxtFeed, }; pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; @@ -189,6 +191,7 @@ pub struct ResolverGlobalCtxt { pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>, pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>, pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>, + pub stripped_cfg_items: Steal<Vec<StrippedCfgItem>>, } /// Resolutions that should only be used for lowering. @@ -250,9 +253,9 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec<Predicate<'tcx>>, } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)] +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ImplTraitHeader<'tcx> { - pub trait_ref: ty::TraitRef<'tcx>, + pub trait_ref: ty::EarlyBinder<ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub unsafety: hir::Unsafety, } @@ -1624,12 +1627,15 @@ impl<'tcx> TyCtxt<'tcx> { def_id1: DefId, def_id2: DefId, ) -> Option<ImplOverlapKind> { - let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity(); - let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity(); + let impl1 = self.impl_trait_header(def_id1).unwrap(); + let impl2 = self.impl_trait_header(def_id2).unwrap(); + + let trait_ref1 = impl1.trait_ref.skip_binder(); + let trait_ref2 = impl2.trait_ref.skip_binder(); // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if impl1.references_error() || impl2.references_error() { + if trait_ref1.references_error() || trait_ref2.references_error() { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -1650,7 +1656,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker }; - is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref) + is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2) }; if is_marker_overlap { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 9a6d4498352..8a9dc34bc7b 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -58,52 +58,60 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.thir[scrutinee].span, ), ExprKind::If { cond, then, else_opt, if_then_scope } => { - let then_blk; let then_span = this.thir[then].span; let then_source_info = this.source_info(then_span); let condition_scope = this.local_scope(); - let mut else_blk = unpack!( - then_blk = this.in_scope( - (if_then_scope, then_source_info), - LintLevel::Inherited, - |this| { - let source_info = if this.is_let(cond) { - let variable_scope = - this.new_source_scope(then_span, LintLevel::Inherited, None); - this.source_scope = variable_scope; - SourceInfo { span: then_span, scope: variable_scope } - } else { - this.source_info(then_span) - }; - let (then_block, else_block) = - this.in_if_then_scope(condition_scope, then_span, |this| { - let then_blk = unpack!(this.then_else_break( - block, - cond, - Some(condition_scope), // Temp scope - condition_scope, - source_info, - true, // Declare `let` bindings normally - )); - - this.expr_into_dest(destination, then_blk, then) - }); - then_block.and(else_block) - }, - ) + let then_and_else_blocks = this.in_scope( + (if_then_scope, then_source_info), + LintLevel::Inherited, + |this| { + // FIXME: Does this need extra logic to handle let-chains? + let source_info = if this.is_let(cond) { + let variable_scope = + this.new_source_scope(then_span, LintLevel::Inherited, None); + this.source_scope = variable_scope; + SourceInfo { span: then_span, scope: variable_scope } + } else { + this.source_info(then_span) + }; + + // Lower the condition, and have it branch into `then` and `else` blocks. + let (then_block, else_block) = + this.in_if_then_scope(condition_scope, then_span, |this| { + let then_blk = unpack!(this.then_else_break( + block, + cond, + Some(condition_scope), // Temp scope + source_info, + true, // Declare `let` bindings normally + )); + + // Lower the `then` arm into its block. + this.expr_into_dest(destination, then_blk, then) + }); + + // Pack `(then_block, else_block)` into `BlockAnd<BasicBlock>`. + then_block.and(else_block) + }, ); - else_blk = if let Some(else_opt) = else_opt { - unpack!(this.expr_into_dest(destination, else_blk, else_opt)) + // Unpack `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`. + let (then_blk, mut else_blk); + else_blk = unpack!(then_blk = then_and_else_blocks); + + // If there is an `else` arm, lower it into `else_blk`. + if let Some(else_expr) = else_opt { + unpack!(else_blk = this.expr_into_dest(destination, else_blk, else_expr)); } else { - // Body of the `if` expression without an `else` clause must return `()`, thus - // we implicitly generate an `else {}` if it is not specified. + // There is no `else` arm, so we know both arms have type `()`. + // Generate the implicit `else {}` by assigning unit. let correct_si = this.source_info(expr_span.shrink_to_hi()); this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx); - else_blk - }; + } + // The `then` and `else` arms have been lowered into their respective + // blocks, so make both of them meet up in a new block. let join_block = this.cfg.start_new_block(); this.cfg.goto(then_blk, source_info, join_block); this.cfg.goto(else_blk, source_info, join_block); @@ -147,7 +155,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, lhs, Some(condition_scope), // Temp scope - condition_scope, source_info, // This flag controls how inner `let` expressions are lowered, // but either way there shouldn't be any of those in here. diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 29ee07f5d79..31591983101 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -37,9 +37,6 @@ struct ThenElseArgs { /// Used as the temp scope for lowering `expr`. If absent (for match guards), /// `self.local_scope()` is used. temp_scope_override: Option<region::Scope>, - /// Scope to pass to [`Builder::break_for_else`]. Must match the scope used - /// by the enclosing call to [`Builder::in_if_then_scope`]. - break_scope: region::Scope, variable_source_info: SourceInfo, /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. /// When false (for match guards), `let` bindings won't be declared. @@ -58,19 +55,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, expr_id: ExprId, temp_scope_override: Option<region::Scope>, - break_scope: region::Scope, variable_source_info: SourceInfo, declare_let_bindings: bool, ) -> BlockAnd<()> { self.then_else_break_inner( block, expr_id, - ThenElseArgs { - temp_scope_override, - break_scope, - variable_source_info, - declare_let_bindings, - }, + ThenElseArgs { temp_scope_override, variable_source_info, declare_let_bindings }, ) } @@ -97,11 +88,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break_inner( block, lhs, - ThenElseArgs { - break_scope: local_scope, - declare_let_bindings: true, - ..args - }, + ThenElseArgs { declare_let_bindings: true, ..args }, ) }); let rhs_success_block = unpack!(this.then_else_break_inner( @@ -130,14 +117,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break_inner( block, arg, - ThenElseArgs { - break_scope: local_scope, - declare_let_bindings: true, - ..args - }, + ThenElseArgs { declare_let_bindings: true, ..args }, ) }); - this.break_for_else(success_block, args.break_scope, args.variable_source_info); + this.break_for_else(success_block, args.variable_source_info); failure_block.unit() } ExprKind::Scope { region_scope, lint_level, value } => { @@ -151,7 +134,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, expr, pat, - args.break_scope, Some(args.variable_source_info.scope), args.variable_source_info.span, args.declare_let_bindings, @@ -170,7 +152,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr_span); this.cfg.terminate(block, source_info, term); - this.break_for_else(else_block, args.break_scope, source_info); + this.break_for_else(else_block, source_info); then_block.unit() } @@ -1911,7 +1893,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, expr_id: ExprId, pat: &Pat<'tcx>, - else_target: region::Scope, source_scope: Option<SourceScope>, span: Span, declare_bindings: bool, @@ -1933,7 +1914,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_place = expr_place_builder.try_to_place(self); let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); - self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span)); + self.break_for_else(otherwise_post_guard_block, self.source_info(expr_span)); if declare_bindings { self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place); @@ -2110,7 +2091,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, guard, None, // Use `self.local_scope()` as the temp scope - match_scope, this.source_info(arm.span), false, // For guards, `let` bindings are declared separately ) @@ -2443,7 +2423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, true, ); - this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span)); + this.break_for_else(failure, this.source_info(initializer_span)); matching.unit() }); matching.and(failure) diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 04740a96291..961502566ba 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -683,20 +683,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.start_new_block().unit() } - pub(crate) fn break_for_else( - &mut self, - block: BasicBlock, - target: region::Scope, - source_info: SourceInfo, - ) { - let scope_index = self.scopes.scope_index(target, source_info.span); + /// Sets up the drops for breaking from `block` due to an `if` condition + /// that turned out to be false. + /// + /// Must be called in the context of [`Builder::in_if_then_scope`], so that + /// there is an if-then scope to tell us what the target scope is. + pub(crate) fn break_for_else(&mut self, block: BasicBlock, source_info: SourceInfo) { let if_then_scope = self .scopes .if_then_scope - .as_mut() + .as_ref() .unwrap_or_else(|| span_bug!(source_info.span, "no if-then scope found")); - assert_eq!(if_then_scope.region_scope, target, "breaking to incorrect scope"); + let target = if_then_scope.region_scope; + let scope_index = self.scopes.scope_index(target, source_info.span); + + // Upgrade `if_then_scope` to `&mut`. + let if_then_scope = self.scopes.if_then_scope.as_mut().expect("upgrading & to &mut"); let mut drop_idx = ROOT_NODE; let drops = &mut if_then_scope.else_drops; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 14d9b0b0350..19109735d48 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -929,7 +929,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _instance: ty::Instance<'tcx>, _abi: rustc_target::spec::abi::Abi, _args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>], - _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { @@ -947,7 +947,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], - _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, + _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx> { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b0cb9fa517f..37cce625c8e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1361,7 +1361,7 @@ fn create_mono_items_for_default_impls<'tcx>( return; }; - if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) { + if matches!(impl_.polarity, ty::ImplPolarity::Negative) { return; } @@ -1385,7 +1385,7 @@ fn create_mono_items_for_default_impls<'tcx>( } }; let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params); - let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref; + let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args); // Unlike 'lazy' monomorphization that begins by collecting items transitively // called by `main` or other global items, when eagerly monomorphizing impl diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 54854cd2da9..ea9c78ca34c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -787,13 +787,17 @@ impl<'a> Parser<'a> { let suggest_eq = if self.token.kind == token::Dot && let _ = self.bump() && let mut snapshot = self.create_snapshot_for_diagnostic() - && let Ok(_) = snapshot.parse_dot_suffix_expr( - colon_sp, - self.mk_expr_err( + && let Ok(_) = snapshot + .parse_dot_suffix_expr( colon_sp, - self.dcx().delayed_bug("error during `:` -> `=` recovery"), - ), - ) { + self.mk_expr_err( + colon_sp, + self.dcx() + .delayed_bug("error during `:` -> `=` recovery"), + ), + ) + .map_err(Diag::cancel) + { true } else if let Some(op) = self.check_assoc_op() && op.node.can_continue_expr_unambiguously() diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 4bfe6be5493..96893e58549 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -87,7 +87,7 @@ impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { /// Traverses and collects the debugger visualizers for a specific crate. fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> { - let resolver_and_krate = tcx.resolver_for_lowering(()).borrow(); + let resolver_and_krate = tcx.resolver_for_lowering().borrow(); let krate = &*resolver_and_krate.1; let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 02f56ecb10b..dd6c1166957 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,38 +1,26 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{intravisit, HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { - if tcx.sess.opts.unstable_opts.hir_stats { - crate::hir_stats::print_hir_stats(tcx); - } - - #[cfg(debug_assertions)] - { - let errors = Lock::new(Vec::new()); + let errors = Lock::new(Vec::new()); - tcx.hir().par_for_each_module(|module_id| { - let mut v = HirIdValidator { - tcx, - owner: None, - hir_ids_seen: Default::default(), - errors: &errors, - }; + tcx.hir().par_for_each_module(|module_id| { + let mut v = + HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors }; - tcx.hir().visit_item_likes_in_module(module_id, &mut v); - }); + tcx.hir().visit_item_likes_in_module(module_id, &mut v); + }); - let errors = errors.into_inner(); + let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.dcx().delayed_bug(message); - } + if !errors.is_empty() { + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + tcx.dcx().delayed_bug(message); } } @@ -90,7 +78,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {pretty_owner}. \ - Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" + Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" ) }); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index d3e3e183845..d1368267224 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -243,7 +243,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { /// Traverses and collects all the lang items in all crates. fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { - let resolver = tcx.resolver_for_lowering(()).borrow(); + let resolver = tcx.resolver_for_lowering().borrow(); let (resolver, krate) = &*resolver; // Initialize the collector. diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 7227b185f4d..e03052bcfed 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -28,6 +28,7 @@ mod debugger_visualizer; mod diagnostic_items; pub mod entry; mod errors; +#[cfg(debug_assertions)] pub mod hir_id_validator; pub mod hir_stats; mod lang_items; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1c4aeefcbcf..dd18ab7d9d2 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -25,6 +25,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; +use rustc_middle::ty::Feed; use rustc_middle::{bug, ty}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -407,7 +408,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Top level use tree reuses the item's id and list stems reuse their parent // use tree's ids, so in both cases their visibilities are already filled. if nested && !list_stem { - self.r.feed_visibility(self.r.local_def_id(id), vis); + self.r.feed_visibility(self.r.feed(id), vis); } let mut prefix_iter = parent_prefix @@ -632,7 +633,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { &mut self, fields: &[ast::FieldDef], ident: Ident, - def_id: LocalDefId, + feed: Feed<'tcx, LocalDefId>, adt_res: Res, adt_vis: ty::Visibility, adt_span: Span, @@ -643,7 +644,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a name in the type namespace if it is not anonymous. self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion)); - self.r.feed_visibility(def_id, adt_vis); + self.r.feed_visibility(feed, adt_vis); + let def_id = feed.key(); // Record field names for error reporting. self.insert_field_def_ids(def_id, fields); @@ -653,14 +655,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { match &field.ty.kind { ast::TyKind::AnonStruct(id, nested_fields) | ast::TyKind::AnonUnion(id, nested_fields) => { - let local_def_id = self.r.local_def_id(*id); + let feed = self.r.feed(*id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(local_def_id); let res = Res::Def(def_kind, def_id); self.build_reduced_graph_for_struct_variant( &nested_fields, Ident::empty(), - local_def_id, + feed, res, // Anonymous adts inherit visibility from their parent adts. adt_vis, @@ -680,12 +683,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(def_id); let res = Res::Def(def_kind, def_id); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); match item.kind { ItemKind::Use(ref use_tree) => { @@ -762,7 +766,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -795,10 +799,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ret_fields.push(field_vis.to_def_id()); } - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); // We need the field visibility spans also for the constructor for E0603. self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields()); @@ -812,7 +817,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -919,7 +924,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let ns = match item.kind { ForeignItemKind::Fn(..) => ValueNS, @@ -931,7 +937,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -1218,7 +1224,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let def_id = feed.key(); let (res, ident, span, macro_rules) = match &item.kind { ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), ItemKind::Fn(..) => match self.proc_macro_stub(item) { @@ -1269,7 +1276,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, def_id, item.id); } - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { parent_macro_rules_scope: parent_scope.macro_rules, @@ -1293,7 +1300,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); self.parent_scope.macro_rules } } @@ -1385,7 +1392,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); if !(ctxt == AssocCtxt::Impl @@ -1395,7 +1403,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Trait impl item visibility is inherited from its trait when not specified // explicitly. In that case we cannot determine it here in early resolve, // so we leave a hole in the visibility table to be filled later. - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } if ctxt == AssocCtxt::Trait { @@ -1469,7 +1477,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.visit_invoc(sf.id); } else { let vis = self.resolve_visibility(&sf.vis); - self.r.feed_visibility(self.r.local_def_id(sf.id), vis); + self.r.feed_visibility(self.r.feed(sf.id), vis); visit::walk_field_def(self, sf); } } @@ -1487,10 +1495,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = variant.ident; // Define a name in the type namespace. - let def_id = self.r.local_def_id(variant.id); + let feed = self.r.feed(variant.id); + let def_id = feed.key(); let vis = self.resolve_visibility(&variant.vis); self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); // If the variant is marked as non_exhaustive then lower the visibility to within the crate. let ctor_vis = @@ -1502,10 +1511,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a constructor name in the value namespace. if let Some(ctor_node_id) = variant.data.ctor_node_id() { - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); } // Record field names for error reporting. diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 13fec70e0a7..bf1ea2e2709 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { self.check_import_as_underscore(item, *id); } } + + fn report_unused_extern_crate_items( + &mut self, + maybe_unused_extern_crates: FxHashMap<ast::NodeId, Span>, + ) { + let tcx = self.r.tcx(); + for extern_crate in &self.extern_crate_items { + let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); + + // If the crate is fully unused, we suggest removing it altogether. + // We do this in any edition. + if warn_if_unused { + if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + span, + "unused extern crate", + BuiltinLintDiag::UnusedExternCrate { + removal_span: extern_crate.span_with_attributes, + }, + ); + continue; + } + } + + // If we are not in Rust 2018 edition, then we don't make any further + // suggestions. + if !tcx.sess.at_least_rust_2018() { + continue; + } + + // If the extern crate has any attributes, they may have funky + // semantics we can't faithfully represent using `use` (most + // notably `#[macro_use]`). Ignore it. + if extern_crate.has_attrs { + continue; + } + + // If the extern crate is renamed, then we cannot suggest replacing it with a use as this + // would not insert the new name into the prelude, where other imports in the crate may be + // expecting it. + if extern_crate.renames { + continue; + } + + // If the extern crate isn't in the extern prelude, + // there is no way it can be written as a `use`. + if !self + .r + .extern_prelude + .get(&extern_crate.ident) + .is_some_and(|entry| !entry.introduced_by_item) + { + continue; + } + + let vis_span = extern_crate + .vis_span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.vis_span); + let ident_span = extern_crate + .ident + .span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.ident.span); + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + extern_crate.span, + "`extern crate` is not idiomatic in the new edition", + BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, + ); + } + } } impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { @@ -335,6 +410,8 @@ impl Resolver<'_, '_> { }; visit::walk_crate(&mut visitor, krate); + visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); + for unused in visitor.unused_imports.values() { let mut fixes = Vec::new(); let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { @@ -416,75 +493,6 @@ impl Resolver<'_, '_> { ); } - for extern_crate in visitor.extern_crate_items { - let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); - - // If the crate is fully unused, we suggest removing it altogether. - // We do this in any edition. - if warn_if_unused { - if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - span, - "unused extern crate", - BuiltinLintDiag::UnusedExternCrate { - removal_span: extern_crate.span_with_attributes, - }, - ); - continue; - } - } - - // If we are not in Rust 2018 edition, then we don't make any further - // suggestions. - if !tcx.sess.at_least_rust_2018() { - continue; - } - - // If the extern crate has any attributes, they may have funky - // semantics we can't faithfully represent using `use` (most - // notably `#[macro_use]`). Ignore it. - if extern_crate.has_attrs { - continue; - } - - // If the extern crate is renamed, then we cannot suggest replacing it with a use as this - // would not insert the new name into the prelude, where other imports in the crate may be - // expecting it. - if extern_crate.renames { - continue; - } - - // If the extern crate isn't in the extern prelude, - // there is no way it can be written as a `use`. - if !visitor - .r - .extern_prelude - .get(&extern_crate.ident) - .is_some_and(|entry| !entry.introduced_by_item) - { - continue; - } - - let vis_span = extern_crate - .vis_span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.vis_span); - let ident_span = extern_crate - .ident - .span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.ident.span); - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - extern_crate.span, - "`extern crate` is not idiomatic in the new edition", - BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, - ); - } - let unused_imports = visitor.unused_imports; let mut check_redundant_imports = FxIndexSet::default(); for module in self.arenas.local_modules().iter() { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 12bf462a6fd..bb3b902c0de 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -38,14 +38,16 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", node_id, def_kind, parent_def ); - self.resolver.create_def( - parent_def, - node_id, - name, - def_kind, - self.expansion.to_expn_id(), - span.with_parent(None), - ) + self.resolver + .create_def( + parent_def, + node_id, + name, + def_kind, + self.expansion.to_expn_id(), + span.with_parent(None), + ) + .def_id() } fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9e5b2fe094f..ea08041f2aa 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1336,9 +1336,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut is_redundant = true; - let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; - self.per_ns(|this, ns| { if is_redundant && let Ok(binding) = source_bindings[ns].get() { if binding.res() == Res::Err { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 83ee1d8bdcb..455afb8de8e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2593,10 +2593,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let span = *entry.get(); let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); self.report_error(param.ident.span, err); - if let GenericParamKind::Lifetime = param.kind { - // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); - } + let rib = match param.kind { + GenericParamKind::Lifetime => { + // Record lifetime res, so lowering knows there is something fishy. + self.record_lifetime_param(param.id, LifetimeRes::Error); + continue; + } + GenericParamKind::Type { .. } => &mut function_type_rib, + GenericParamKind::Const { .. } => &mut function_value_rib, + }; + + // Taint the resolution in case of errors to prevent follow up errors in typeck + self.r.record_partial_res(param.id, PartialRes::new(Res::Err)); + rib.bindings.insert(ident, Res::Err); continue; } Entry::Vacant(entry) => { @@ -3112,7 +3121,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); rustc_middle::ty::Visibility::Public }; - this.r.feed_visibility(this.r.local_def_id(id), vis); + this.r.feed_visibility(this.r.feed(id), vis); }; let Some(binding) = binding else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5de147c2b24..ccb67ea78cf 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; -use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; +use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; +use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::LintBuffer; @@ -1117,7 +1117,7 @@ pub struct Resolver<'a, 'tcx> { next_node_id: NodeId, - node_id_to_def_id: NodeMap<LocalDefId>, + node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>, def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>, /// Indices of unnamed struct or variant fields with unresolved attributes. @@ -1233,11 +1233,19 @@ impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for Resolver<'a, 'tcx> { impl<'tcx> Resolver<'_, 'tcx> { fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { - self.node_id_to_def_id.get(&node).copied() + self.opt_feed(node).map(|f| f.key()) } fn local_def_id(&self, node: NodeId) -> LocalDefId { - self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) + self.feed(node).key() + } + + fn opt_feed(&self, node: NodeId) -> Option<Feed<'tcx, LocalDefId>> { + self.node_id_to_def_id.get(&node).copied() + } + + fn feed(&self, node: NodeId) -> Feed<'tcx, LocalDefId> { + self.opt_feed(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } fn local_def_kind(&self, node: NodeId) -> DefKind { @@ -1253,18 +1261,19 @@ impl<'tcx> Resolver<'_, 'tcx> { def_kind: DefKind, expn_id: ExpnId, span: Span, - ) -> LocalDefId { + ) -> TyCtxtFeed<'tcx, LocalDefId> { let data = def_kind.def_path_data(name); assert!( !self.node_id_to_def_id.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id]), + self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()), ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` - let def_id = self.tcx.create_def(parent, name, def_kind).def_id(); + let feed = self.tcx.create_def(parent, name, def_kind); + let def_id = feed.def_id(); // Create the definition. if expn_id != ExpnId::root() { @@ -1281,11 +1290,11 @@ impl<'tcx> Resolver<'_, 'tcx> { // we don't need a mapping from `NodeId` to `LocalDefId`. if node_id != ast::DUMMY_NODE_ID { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.node_id_to_def_id.insert(node_id, def_id); + self.node_id_to_def_id.insert(node_id, feed.downgrade()); } assert_eq!(self.def_id_to_node_id.push(node_id), def_id); - def_id + feed } fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { @@ -1333,7 +1342,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); - node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID); + let crate_feed = tcx.create_local_crate_def_id(crate_span); + + crate_feed.def_kind(DefKind::Mod); + let crate_feed = crate_feed.downgrade(); + node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed); let mut invocation_parents = FxHashMap::default(); invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential)); @@ -1484,7 +1497,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let root_parent_scope = ParentScope::module(graph_root, &resolver); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); - resolver.feed_visibility(CRATE_DEF_ID, ty::Visibility::Public); + resolver.feed_visibility(crate_feed, ty::Visibility::Public); resolver } @@ -1532,9 +1545,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Default::default() } - fn feed_visibility(&mut self, def_id: LocalDefId, vis: ty::Visibility) { - self.tcx.feed_local_def_id(def_id).visibility(vis.to_def_id()); - self.visibilities_for_hashing.push((def_id, vis)); + fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: ty::Visibility) { + let feed = feed.upgrade(self.tcx); + feed.visibility(vis.to_def_id()); + self.visibilities_for_hashing.push((feed.def_id(), vis)); } pub fn into_outputs(self) -> ResolverOutputs { @@ -1547,12 +1561,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let confused_type_with_std_module = self.confused_type_with_std_module; let effective_visibilities = self.effective_visibilities; - self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter( - self.stripped_cfg_items.into_iter().filter_map(|item| { - let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) - }), - )); + let stripped_cfg_items = Steal::new( + self.stripped_cfg_items + .into_iter() + .filter_map(|item| { + let parent_module = + self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); + Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) + }) + .collect(), + ); let global_ctxt = ResolverGlobalCtxt { expn_that_defined, @@ -1569,6 +1587,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_resolutions: self.doc_link_resolutions, doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, + stripped_cfg_items, }; let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, @@ -1578,7 +1597,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { lifetimes_res_map: self.lifetimes_res_map, extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, - node_id_to_def_id: self.node_id_to_def_id, + node_id_to_def_id: self + .node_id_to_def_id + .into_items() + .map(|(k, f)| (k, f.key())) + .collect(), def_id_to_node_id: self.def_id_to_node_id, trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 66177d551ba..f4967b94e93 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -814,7 +814,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } } }, - "aarch64" => { + "aarch64" | "arm64ec" => { let kind = if cx.target_spec().is_like_osx { aarch64::AbiKind::DarwinPCS } else if cx.target_spec().is_like_windows { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 3fda1e1833c..a68dae0ade3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1564,6 +1564,7 @@ supported_targets! { ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc), + ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc), ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc), diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs new file mode 100644 index 00000000000..f1af4d9a80e --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -0,0 +1,21 @@ +use crate::spec::{add_link_args, base, LinkerFlavor, Lld, Target}; + +pub fn target() -> Target { + let mut base = base::windows_msvc::opts(); + base.max_atomic_width = Some(128); + base.features = "+v8a,+neon,+fp-armv8".into(); + add_link_args( + &mut base.late_link_args, + LinkerFlavor::Msvc(Lld::No), + &["/machine:arm64ec", "softintrin.lib"], + ); + + Target { + llvm_target: "arm64ec-pc-windows-msvc".into(), + description: None, + pointer_width: 64, + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(), + arch: "arm64ec".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 2b7ac68c21d..c003982278e 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -377,10 +377,12 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start ("d", Unstable(sym::loongarch_target_feature)), ("f", Unstable(sym::loongarch_target_feature)), + ("frecipe", Unstable(sym::loongarch_target_feature)), ("lasx", Unstable(sym::loongarch_target_feature)), ("lbt", Unstable(sym::loongarch_target_feature)), ("lsx", Unstable(sym::loongarch_target_feature)), ("lvz", Unstable(sym::loongarch_target_feature)), + ("relax", Unstable(sym::loongarch_target_feature)), ("ual", Unstable(sym::loongarch_target_feature)), // tidy-alphabetical-end ]; @@ -409,7 +411,7 @@ impl super::spec::Target { pub fn supported_target_features(&self) -> &'static [(&'static str, Stability)] { match &*self.arch { "arm" => ARM_ALLOWED_FEATURES, - "aarch64" => AARCH64_ALLOWED_FEATURES, + "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES, "x86" | "x86_64" => X86_ALLOWED_FEATURES, "hexagon" => HEXAGON_ALLOWED_FEATURES, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES, @@ -425,7 +427,7 @@ impl super::spec::Target { pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] { match &*self.arch { - "aarch64" => AARCH64_TIED_FEATURES, + "aarch64" | "arm64ec" => AARCH64_TIED_FEATURES, _ => &[], } } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 248985715c2..ed839d14dc7 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -166,13 +166,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if !drcx.args_may_unify( goal.predicate.trait_ref(tcx).args, - impl_trait_header.skip_binder().trait_ref.args, + impl_trait_header.trait_ref.skip_binder().args, ) { return Err(NoSolution); } // We have to ignore negative impls when projecting. - let impl_polarity = impl_trait_header.skip_binder().polarity; + let impl_polarity = impl_trait_header.polarity; match impl_polarity { ty::ImplPolarity::Negative => return Err(NoSolution), ty::ImplPolarity::Reservation => { @@ -183,7 +183,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; + let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 80198ba39f9..281f5cc5685 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -47,14 +47,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if !drcx.args_may_unify( goal.predicate.trait_ref.args, - impl_trait_header.skip_binder().trait_ref.args, + impl_trait_header.trait_ref.skip_binder().args, ) { return Err(NoSolution); } // An upper bound of the certainty of this goal, used to lower the certainty // of reservation impl to ambiguous during coherence. - let impl_polarity = impl_trait_header.skip_binder().polarity; + let impl_polarity = impl_trait_header.polarity; let maximal_certainty = match impl_polarity { ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => { match impl_polarity == goal.predicate.polarity { @@ -70,7 +70,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; + let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; let where_clause_bounds = tcx @@ -102,7 +102,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { - // FIXME: Constness ecx.probe_misc_candidate("assumption").enter(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 7a930937255..ac2b738d3b6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1431,45 +1431,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] impl<'tcx> TypeErrCtxt<'_, 'tcx> { + fn can_match_trait( + &self, + goal: ty::TraitPredicate<'tcx>, + assumption: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + if goal.polarity != assumption.polarity() { + return false; + } + + let trait_goal = goal.trait_ref; + let trait_assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption.to_poly_trait_ref(), + ); + + self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption) + } + + fn can_match_projection( + &self, + goal: ty::ProjectionPredicate<'tcx>, + assumption: ty::PolyProjectionPredicate<'tcx>, + ) -> bool { + let assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption, + ); + + let param_env = ty::ParamEnv::empty(); + self.can_eq(param_env, goal.projection_ty, assumption.projection_ty) + && self.can_eq(param_env, goal.term, assumption.term) + } + // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. + #[instrument(level = "debug", skip(self), ret)] fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { if cond == error { return true; } - // FIXME: It should be possible to deal with `ForAll` in a cleaner way. - let bound_error = error.kind(); - let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), - ) => (cond, bound_error.rebind(error)), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for pred in elaborate(self.tcx, std::iter::once(cond)) { - let bound_predicate = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = - bound_predicate.skip_binder() - { - let error = error.to_poly_trait_ref(); - let implication = bound_predicate.rebind(implication.trait_ref); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication) { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } + if let Some(error) = error.to_opt_poly_trait_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .any(|implied| self.can_match_trait(error, implied)) + }) + } else if let Some(error) = error.to_opt_poly_projection_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_projection_pred()) + .any(|implied| self.can_match_projection(error, implied)) + }) + } else { + false } - - false } #[instrument(skip(self), level = "debug")] @@ -1888,13 +1907,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .tcx .all_impls(trait_pred.def_id()) .filter_map(|def_id| { - let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder(); + let imp = self.tcx.impl_trait_header(def_id).unwrap(); if imp.polarity == ty::ImplPolarity::Negative || !self.tcx.is_user_visible_dep(def_id.krate) { return None; } - let imp = imp.trait_ref; + let imp = imp.trait_ref.skip_binder(); self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, @@ -2078,12 +2097,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .all_impls(def_id) // Ignore automatically derived impls and `!Trait` impls. .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) - .map(ty::EarlyBinder::instantiate_identity) - .filter(|header| { - header.polarity != ty::ImplPolarity::Negative - || self.tcx.is_automatically_derived(def_id) + .filter_map(|header| { + (header.polarity != ty::ImplPolarity::Negative + || self.tcx.is_automatically_derived(def_id)) + .then(|| header.trait_ref.instantiate_identity()) }) - .map(|header| header.trait_ref) .filter(|trait_ref| { let self_ty = trait_ref.self_ty(); // Avoid mentioning type parameters. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 39f4ceda9f1..66f740b761d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -562,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and so forth that we need to. let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); if !drcx - .args_may_unify(obligation_args, impl_trait_header.skip_binder().trait_ref.args) + .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args) { return; } @@ -577,7 +577,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.reject_fn_ptr_impls( impl_def_id, obligation, - impl_trait_header.skip_binder().trait_ref.self_ty(), + impl_trait_header.trait_ref.skip_binder().self_ty(), ) { return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7dbea0cdb90..a6bd1ba9c3f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -42,7 +42,7 @@ use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; +use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Symbol; @@ -2441,7 +2441,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn match_impl( &mut self, impl_def_id: DefId, - impl_trait_header: EarlyBinder<ty::ImplTraitHeader<'tcx>>, + impl_trait_header: ty::ImplTraitHeader<'tcx>, obligation: &PolyTraitObligation<'tcx>, ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> { let placeholder_obligation = @@ -2450,8 +2450,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); - let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args); - if impl_trait_header.references_error() { + let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args); + if trait_ref.references_error() { return Err(()); } @@ -2464,7 +2464,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - impl_trait_header.trait_ref, + trait_ref, ) }); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index f5bc6c3ad2c..27dd8f26489 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -169,7 +169,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, } } - let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap().instantiate_identity(); + let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap(); // We determine whether there's a subset relationship by: // @@ -198,7 +198,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, fulfill_implication( &infcx, penv, - impl1_trait_header.trait_ref, + impl1_trait_header.trait_ref.instantiate_identity(), impl1_def_id, impl2_def_id, |_, _| ObligationCause::dummy(), diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 6e01e0b76aa..3f433a9e919 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { } // Get components of trait alias. - let predicates = tcx.implied_predicates_of(trait_ref.def_id()); + let predicates = tcx.super_predicates_of(trait_ref.def_id()); debug!(?predicates); let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 15059bc6613..b09a803e856 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -223,60 +223,87 @@ enum Elaborate { None, } +/// Points the cause span of a super predicate at the relevant associated type. +/// +/// Given a trait impl item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// } +/// ``` +/// +/// And a super predicate of `TargetTrait` that has any of the following forms: +/// +/// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc` +/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType` +/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait` +/// +/// Replace the span of the cause with the span of the associated item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// // ^^^^^^^^ this span +/// } +/// ``` +/// +/// Note that bounds that can be expressed as associated item bounds are **not** +/// super predicates. This means that form 2 and 3 from above are only relevant if +/// the [`GenericArgsRef`] of the projection type are not its identity arguments. fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: ty::Predicate<'tcx>, ) { - debug!( - "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", - trait_ref, item, cause, pred - ); + debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation"); let (items, impl_def_id) = match item { Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { (impl_.items, *owner_id) } _ => return, }; - let fix_span = - |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { - hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span, - _ => impl_item_ref.span, - }; + + let ty_to_impl_span = |ty: Ty<'_>| { + if let ty::Alias(ty::Projection, projection_ty) = ty.kind() + && let Some(&impl_item_id) = + tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) + && let Some(impl_item) = + items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id) + { + Some(tcx.hir().impl_item(impl_item.id).expect_type().span) + } else { + None + } + }; // It is fine to skip the binder as we don't care about regions here. match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { - // The obligation comes not from the current `impl` nor the `trait` being implemented, - // but rather from a "second order" obligation, where an associated type has a - // projection coming from another associated type. See - // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and - // `traits-assoc-type-in-supertrait-bad.rs`. - if let Some(ty::Alias(ty::Projection, projection_ty)) = - proj.term.ty().map(|ty| ty.kind()) - && let Some(&impl_item_id) = - tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) + // Form 1: The obligation comes not from the current `impl` nor the `trait` being + // implemented, but rather from a "second order" obligation, where an associated + // type has a projection coming from another associated type. + // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example. + if let Some(term_ty) = proj.term.ty() + && let Some(impl_item_span) = ty_to_impl_span(term_ty) { cause.span = impl_item_span; } + + // Form 2: A projection obligation for an associated item failed to be met. + // We overwrite the span from above to ensure that a bound like + // `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same + // span for both obligations that it is lowered to. + if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) { + cause.span = impl_item_span; + } } + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - // An associated item obligation born out of the `trait` failed to be met. An example - // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. + // Form 3: A trait obligation for an associated item failed to be met. debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); - if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind() - && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) - { + if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) { cause.span = impl_item_span; } } @@ -355,9 +382,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCauseCode::DerivedObligation, ); } - extend_cause_with_original_assoc_item_obligation( - tcx, trait_ref, item, &mut cause, predicate, - ); + extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate); traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) }; diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index f3fae63ecc7..b2b5c6cd909 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _}; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt, @@ -72,6 +72,13 @@ pub fn codegen_select_candidate<'tcx>( let impl_source = infcx.resolve_vars_if_possible(impl_source); let impl_source = infcx.tcx.erase_regions(impl_source); + if impl_source.has_infer() { + // Unused lifetimes on an impl get replaced with inference vars, but never resolved, + // causing the return value of a query to contain inference vars. We do not have a concept + // for this and will in fact ICE in stable hashing of the return value. So bail out instead. + infcx.tcx.dcx().has_errors().unwrap(); + return Err(CodegenObligationError::FulfillmentError); + } Ok(&*tcx.arena.alloc(impl_source)) } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index db37bec4b82..26d3370469a 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -4,7 +4,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt}; +use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_span::symbol::kw; pub(crate) fn provide(providers: &mut Providers) { @@ -284,48 +284,8 @@ fn associated_type_for_impl_trait_in_trait( // Copy defaultness of the containing function. trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id)); - // Copy type_of of the opaque. - trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque( - tcx, - opaque_ty_def_id.to_def_id(), - GenericArgs::identity_for_item(tcx, opaque_ty_def_id), - ))); - trait_assoc_ty.is_type_alias_impl_trait(false); - // Copy generics_of of the opaque type item but the trait is the parent. - trait_assoc_ty.generics_of({ - let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id); - let opaque_ty_parent_count = opaque_ty_generics.parent_count; - let mut params = opaque_ty_generics.params.clone(); - - let parent_generics = tcx.generics_of(trait_def_id); - let parent_count = parent_generics.parent_count + parent_generics.params.len(); - - let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone(); - - for param in &mut params { - param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32 - - opaque_ty_parent_count as u32; - } - - trait_fn_params.extend(params); - params = trait_fn_params; - - let param_def_id_to_index = - params.iter().map(|param| (param.def_id, param.index)).collect(); - - ty::Generics { - parent: Some(trait_def_id.to_def_id()), - parent_count, - params, - param_def_id_to_index, - has_self: opaque_ty_generics.has_self, - has_late_bound_regions: opaque_ty_generics.has_late_bound_regions, - host_effect_index: parent_generics.host_effect_index, - } - }); - // There are no inferred outlives for the synthesized associated type. trait_assoc_ty.inferred_outlives_of(&[]); @@ -382,8 +342,9 @@ fn associated_type_for_impl_trait_in_impl( impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id)); // Copy generics_of the trait's associated item but the impl as the parent. - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl - // generics. + // FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars + // here to paramswhose parent are items in the trait. We could synthesize new params + // here, but it seems overkill. impl_assoc_ty.generics_of({ let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id); let trait_assoc_parent_count = trait_assoc_generics.parent_count; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 48d9a5e27b7..2b6b91672c3 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -255,10 +255,9 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<' let impl_ = tcx .impl_trait_header(def_id) - .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)) - .skip_binder(); + .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)); - let trait_ref = impl_.trait_ref; + let trait_ref = impl_.trait_ref.skip_binder(); debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive diff --git a/config.example.toml b/config.example.toml index d12ed052fe4..c1939933850 100644 --- a/config.example.toml +++ b/config.example.toml @@ -300,6 +300,10 @@ # This is only useful for verifying that rustc generates reproducible builds. #full-bootstrap = false +# Set the bootstrap/download cache path. It is useful when building rust +# repeatedly in a CI invironment. +# bootstrap-cache-path = /shared/cache + # Enable a build of the extended Rust tool set which is not only the compiler # but also tools such as Cargo. This will also produce "combined installers" # which are used to install Rust and Cargo together. diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index dd8d6f6c7e6..4d9694d4beb 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -259,7 +259,7 @@ impl<T, A: Allocator> RawVec<T, A> { } else { // We could use Layout::array here which ensures the absence of isize and usize overflows // and could hypothetically handle differences between stride and size, but this memory - // has already been allocated so we know it can't overflow and currently rust does not + // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) }; unsafe { diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 8817ec0777b..31d6bc36fc8 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -6,10 +6,10 @@ pub use crate::core_arch::arch::*; /// Inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "asm", since = "1.59.0")] #[rustc_builtin_macro] @@ -19,10 +19,10 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /// Module-level inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "global_asm", since = "1.59.0")] #[rustc_builtin_macro] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 42663ff2b53..8b5b48c59c2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -360,6 +360,7 @@ where } } +/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] { #[inline] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7b735d48bdf..0f7885769c2 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -202,6 +202,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(diagnostic_namespace))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] @@ -223,7 +224,6 @@ #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] -#![feature(diagnostic_namespace)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 643968c35e8..0ee7e190e3d 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1481,7 +1481,7 @@ pub(crate) mod builtin { /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). /// /// When using the `include` macro to include stretches of documentation, remember that the - /// included file still needs to be a valid rust syntax. It is also possible to + /// included file still needs to be a valid Rust syntax. It is also possible to /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain /// text or markdown file. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 3eea065eef6..3508b0c7f23 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -3,7 +3,7 @@ use crate::num::NonZero; use crate::{cmp, fmt, hash, mem, num}; /// A type storing a `usize` which is a power of two, and thus -/// represents a possible alignment in the rust abstract machine. +/// represents a possible alignment in the Rust abstract machine. /// /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index e8b0010ba15..5bee4d55135 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -24,7 +24,7 @@ where #[stable(feature = "rust1", since = "1.0.0")] impl<T: Eq> Eq for [T] {} -/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison). +/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl<T: Ord> Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { @@ -32,7 +32,7 @@ impl<T: Ord> Ord for [T] { } } -/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison). +/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl<T: PartialOrd> PartialOrd for [T] { fn partial_cmp(&self, other: &[T]) -> Option<Ordering> { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index aaedbed0d55..643b7971a66 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -23,7 +23,7 @@ use crate::slice; issue = "none", reason = "exposed from core to be reused in std; use the memchr crate" )] -/// Pure rust memchr implementation, taken from rust-memchr +/// Pure Rust memchr implementation, taken from rust-memchr pub mod memchr; #[unstable( diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index fa02dd52e00..e8170c13ed2 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -19,7 +19,7 @@ use core::task::{Context, Poll}; /// /// Certain constructs like [`Future`]s can only be used with _exclusive_ access, /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the -/// rust compiler that something is `Sync` in practice. +/// Rust compiler that something is `Sync` in practice. /// /// ## Examples /// Using a non-`Sync` future prevents the wrapping struct from being `Sync` diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index e44da8e637e..8927e9a47fa 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -157,7 +157,7 @@ impl OsString { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -213,7 +213,7 @@ impl OsString { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the bytes over the network or storing it in a file /// will likely result in incompatible data. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. @@ -747,7 +747,7 @@ impl OsStr { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -955,7 +955,7 @@ impl OsStr { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the slice over the network or storing it in a file /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 288cce3aa08..55a5292a4a4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -84,7 +84,7 @@ //! //! # Contributing changes to the documentation //! -//! Check out the rust contribution guidelines [here]( +//! Check out the Rust contribution guidelines [here]( //! https://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation). //! The source for this documentation can be found on //! [GitHub](https://github.com/rust-lang/rust). diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 5ba8719e6ff..b0633fd7bfc 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -95,22 +95,6 @@ pub mod process; pub mod raw; pub mod thread; -#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "watchos", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "nto", -))] -pub mod ucred; - /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index 6da3e350bf1..28c1188677b 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -12,6 +12,20 @@ mod listener; mod stream; #[cfg(all(test, not(target_os = "emscripten")))] mod tests; +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "nto", +))] +mod ucred; #[stable(feature = "unix_socket", since = "1.10.0")] pub use self::addr::*; @@ -24,3 +38,18 @@ pub use self::datagram::*; pub use self::listener::*; #[stable(feature = "unix_socket", since = "1.10.0")] pub use self::stream::*; +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "nto", +))] +#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] +pub use self::ucred::*; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index b1cd504e219..069cb299e28 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -1,10 +1,3 @@ -#[cfg(any(doc, target_os = "android", target_os = "linux"))] -use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; -use super::{sockaddr_un, SocketAddr}; -use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::net::Shutdown; -use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; #[cfg(any( target_os = "android", target_os = "linux", @@ -17,28 +10,20 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned target_os = "netbsd", target_os = "openbsd" ))] -use crate::os::unix::ucred; +use super::{peer_cred, UCred}; +#[cfg(any(doc, target_os = "android", target_os = "linux"))] +use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; +use super::{sockaddr_un, SocketAddr}; +use crate::fmt; +use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::Shutdown; +use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::path::Path; use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner}; use crate::time::Duration; -#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "tvos", - target_os = "macos", - target_os = "watchos", - target_os = "netbsd", - target_os = "openbsd" -))] -pub use ucred::UCred; - /// A Unix stream socket. /// /// # Examples @@ -247,7 +232,7 @@ impl UnixStream { target_os = "openbsd" ))] pub fn peer_cred(&self) -> io::Result<UCred> { - ucred::peer_cred(self) + peer_cred(self) } /// Sets the read timeout for the socket. diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/net/ucred.rs index 6efa74182cc..de09c93840a 100644 --- a/library/std/src/os/unix/ucred.rs +++ b/library/std/src/os/unix/net/ucred.rs @@ -1,5 +1,3 @@ -//! Unix peer credentials. - // NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on // GitHub. // @@ -26,7 +24,7 @@ pub struct UCred { } #[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::impl_linux::peer_cred; +pub(super) use self::impl_linux::peer_cred; #[cfg(any( target_os = "dragonfly", @@ -34,13 +32,13 @@ pub use self::impl_linux::peer_cred; target_os = "openbsd", target_os = "netbsd" ))] -pub use self::impl_bsd::peer_cred; +pub(super) use self::impl_bsd::peer_cred; #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] -pub use self::impl_mac::peer_cred; +pub(super) use self::impl_mac::peer_cred; #[cfg(any(target_os = "linux", target_os = "android"))] -pub mod impl_linux { +mod impl_linux { use super::UCred; use crate::os::unix::io::AsRawFd; use crate::os::unix::net::UnixStream; @@ -82,7 +80,7 @@ pub mod impl_linux { target_os = "netbsd", target_os = "nto", ))] -pub mod impl_bsd { +mod impl_bsd { use super::UCred; use crate::io; use crate::os::unix::io::AsRawFd; @@ -99,7 +97,7 @@ pub mod impl_bsd { } #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] -pub mod impl_mac { +mod impl_mac { use super::UCred; use crate::os::unix::io::AsRawFd; use crate::os::unix::net::UnixStream; diff --git a/library/std/src/os/unix/ucred/tests.rs b/library/std/src/os/unix/net/ucred/tests.rs index dd99ecdd819..dd99ecdd819 100644 --- a/library/std/src/os/unix/ucred/tests.rs +++ b/library/std/src/os/unix/net/ucred/tests.rs diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f289dafd8bc..319b835a768 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -179,7 +179,7 @@ impl Sub<Instant> for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs index a8f1e9b726b..970bd9c6ce7 100644 --- a/library/std/src/sys/pal/windows/thread.rs +++ b/library/std/src/sys/pal/windows/thread.rs @@ -26,11 +26,8 @@ impl Thread { pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> { let p = Box::into_raw(Box::new(p)); - // FIXME On UNIX, we guard against stack sizes that are too small but - // that's because pthreads enforces that stacks are at least - // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's - // just that below a certain threshold you can't do anything useful. - // That threshold is application and architecture-specific, however. + // CreateThread rounds up values for the stack size to the nearest page size (at least 4kb). + // If a value of zero is given then the default stack size is used instead. let ret = c::CreateThread( ptr::null_mut(), stack, diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 813ede06415..589a5fdad1d 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -80,6 +80,7 @@ fn test_named_thread_truncation() { #[test] fn test_get_os_named_thread() { use crate::sys::thread::Thread; + // Spawn a new thread to avoid interfering with other tests running on this thread. let handler = thread::spawn(|| { let name = c"test me please"; Thread::set_name(name); @@ -423,3 +424,16 @@ fn scope_join_race() { }); } } + +// Test that the smallest value for stack_size works on Windows. +#[cfg(windows)] +#[test] +fn test_minimal_thread_stack() { + use crate::sync::atomic::AtomicU8; + static COUNT: AtomicU8 = AtomicU8::new(0); + + let builder = thread::Builder::new().stack_size(1); + let before = builder.spawn(|| COUNT.fetch_add(1, Ordering::Relaxed)).unwrap().join().unwrap(); + assert_eq!(before, 0); + assert_eq!(COUNT.load(Ordering::Relaxed), 1); +} diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 91c010ef2b5..6f1a354d28a 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -59,7 +59,7 @@ pub use core::time::TryFromFloatSecsError; /// experience time dilation (slow down or speed up), but it will never go /// backwards. /// As part of this non-guarantee it is also not specified whether system suspends count as -/// elapsed time or not. The behavior varies across platforms and rust versions. +/// elapsed time or not. The behavior varies across platforms and Rust versions. /// /// Instants are opaque types that can only be compared to one another. There is /// no method to get "the number of seconds" from an instant. Instead, it only @@ -142,7 +142,7 @@ pub use core::time::TryFromFloatSecsError; /// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. /// /// This workaround obscures programming errors where earlier and later instants are accidentally -/// swapped. For this reason future rust versions may reintroduce panics. +/// swapped. For this reason future Rust versions may reintroduce panics. /// /// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html /// [`duration_since`]: Instant::duration_since @@ -290,7 +290,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when `earlier` was later than `self`. Currently this + /// Previous Rust versions panicked when `earlier` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// @@ -365,7 +365,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when the current time was earlier than self. Currently this + /// Previous Rust versions panicked when the current time was earlier than self. Currently this /// method returns a Duration of zero in that case. Future versions may reintroduce the panic. /// See [Monotonicity]. /// @@ -450,7 +450,7 @@ impl Sub<Instant> for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 22c28e4954e..875c66e5fa3 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -84,7 +84,7 @@ impl<T: Write> TerseFormatter<T> { if self.test_column % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { // We insert a new line regularly in order to flush the // screen when dealing with line-buffered output (e.g., piping to - // `stamp` in the rust CI). + // `stamp` in the Rust CI). self.write_progress()?; } diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 1a8ae889c8c..6a7035a8e29 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -13,7 +13,7 @@ pub use NamePadding::*; pub use TestFn::*; pub use TestName::*; -/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) +/// Type of the test according to the [Rust book](https://doc.rust-lang.org/cargo/guide/tests.html) /// conventions. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TestType { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0d604c0d3e5..6e49bcc9744 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -557,7 +557,9 @@ class RustBuild(object): shutil.rmtree(bin_root) key = self.stage0_compiler.date - cache_dst = os.path.join(self.build_dir, "cache") + cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or + os.path.join(self.build_dir, "cache")) + rustc_cache = os.path.join(cache_dst, key) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 8b65e8ff9c3..4257c0f7991 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -149,6 +149,7 @@ v("default-linker", "rust.default-linker", "the default linker") # (others are conditionally saved). o("manage-submodules", "build.submodules", "let the build manage the git submodules") o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)") +o("bootstrap-cache-path", "build.bootstrap-cache-path", "use provided path for the bootstrap cache") o("extended", "build.extended", "build an extended rust tool set") v("tools", None, "List of extended tools will be installed") diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 6c7cc3bf6a7..1090edc9c92 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -129,6 +129,7 @@ pub struct RustcDocs { impl Step for RustcDocs { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -2046,7 +2047,15 @@ fn install_llvm_file( // projects like miri link against librustc_driver.so. We don't use a symlink, as // these are not allowed inside rustup components. let link = t!(fs::read_link(source)); - t!(std::fs::write(full_dest, format!("INPUT({})\n", link.display()))); + let mut linker_script = t!(fs::File::create(full_dest)); + t!(write!(linker_script, "INPUT({})\n", link.display())); + + // We also want the linker script to have the same mtime as the source, otherwise it + // can trigger rebuilds. + let meta = t!(fs::metadata(source)); + if let Ok(mtime) = meta.modified() { + t!(linker_script.set_modified(mtime)); + } } } else { builder.install(&source, destination, 0o644); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a4903ce2353..c4235755ba8 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -797,7 +797,10 @@ impl Step for Rustc { cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("--generate-link-to-definition"); + // FIXME: `--generate-link-to-definition` tries to resolve cfged out code + // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 + // cargo.rustdocflag("--generate-link-to-definition"); + compile::rustc_cargo(builder, &mut cargo, target, compiler.stage); cargo.arg("-Zunstable-options"); cargo.arg("-Zskip-rustdoc-fingerprint"); @@ -953,8 +956,10 @@ macro_rules! tool_doc { cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + // FIXME: `--generate-link-to-definition` tries to resolve cfged out code + // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 + // cargo.rustdocflag("--generate-link-to-definition"); let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); $(for krate in $crates { diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 700c3ee4fda..fc9f9789bd6 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -81,7 +81,7 @@ fn update_rustfmt_version(build: &Builder<'_>) { } /// Returns the Rust files modified between the `merge-base` of HEAD and -/// rust-lang/master and what is now on the disk. +/// rust-lang/master and what is now on the disk. Does not include removed files. /// /// Returns `None` if all files should be formatted. fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 875a4efae02..326f8f57173 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -161,6 +161,7 @@ pub struct Config { pub vendor: bool, pub target_config: HashMap<TargetSelection, Target>, pub full_bootstrap: bool, + pub bootstrap_cache_path: Option<PathBuf>, pub extended: bool, pub tools: Option<HashSet<String>>, pub sanitizers: bool, @@ -827,6 +828,7 @@ define_config! { locked_deps: Option<bool> = "locked-deps", vendor: Option<bool> = "vendor", full_bootstrap: Option<bool> = "full-bootstrap", + bootstrap_cache_path: Option<PathBuf> = "bootstrap-cache-path", extended: Option<bool> = "extended", tools: Option<HashSet<String>> = "tools", verbose: Option<usize> = "verbose", @@ -1389,6 +1391,7 @@ impl Config { locked_deps, vendor, full_bootstrap, + bootstrap_cache_path, extended, tools, verbose, @@ -1477,6 +1480,7 @@ impl Config { config.reuse = reuse.map(PathBuf::from); config.submodules = submodules; config.android_ndk = android_ndk; + config.bootstrap_cache_path = bootstrap_cache_path; set(&mut config.low_priority, low_priority); set(&mut config.compiler_docs, compiler_docs); set(&mut config.library_docs_private_items, library_docs_private_items); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 185089a646b..27829eab937 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -578,7 +578,9 @@ impl Config { return; } - let cache_dst = self.out.join("cache"); + let cache_dst = + self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache")); + let cache_dir = cache_dst.join(key); if !cache_dir.exists() { t!(fs::create_dir_all(&cache_dir)); @@ -705,7 +707,9 @@ download-rustc = false let llvm_assertions = self.llvm_assertions; let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}"); - let cache_dst = self.out.join("cache"); + let cache_dst = + self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache")); + let rustc_cache = cache_dst.join(cache_prefix); if !rustc_cache.exists() { t!(fs::create_dir_all(&rustc_cache)); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index f7748621d93..ab8f3c0d9e4 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -91,7 +91,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[ /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])), // (Some(Mode::Std), "target_os", Some(&[])), - (Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])), + (Some(Mode::Std), "target_arch", Some(&["arm64ec", "spirv", "nvptx", "xtensa"])), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. (Some(Mode::Rustc), "no_btreemap_remove_entry", None), diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 9a50ad4437e..d166b84e51f 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -136,4 +136,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "`x install` now skips providing tarball sources (under 'build/dist' path) to speed up the installation process.", }, + ChangeInfo { + change_id: 121976, + severity: ChangeSeverity::Info, + summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.", + }, ]; diff --git a/src/doc/rust.css b/src/doc/rust.css index e0bf64c33bc..bd2e0b94518 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -5,12 +5,13 @@ body { margin: 0 auto; padding: 0 15px; font-size: 18px; - color: #333; + color: #000; line-height: 1.428571429; -webkit-box-sizing: unset; -moz-box-sizing: unset; box-sizing: unset; + background: #fff; } @media (min-width: 768px) { body { @@ -39,7 +40,6 @@ h4, h5, h6 { padding: 5px 10px; } h5, h6 { - color: black; text-decoration: underline; } diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 26e43491c40..5a0168e30cb 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -18,6 +18,7 @@ - [arm64e-apple-ios.md](platform-support/arm64e-apple-ios.md) - [arm64e-apple-darwin.md](platform-support/arm64e-apple-darwin.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) + - [arm64ec-pc-windows-msvc](platform-support/arm64ec-pc-windows-msvc.md) - [\*-apple-tvos](platform-support/apple-tvos.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 4c4bbd29ac6..6819508caaa 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -32,7 +32,7 @@ All tier 1 targets with host tools support the full standard library. target | notes -------|------- -`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes] +`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) `i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] `i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI] @@ -41,10 +41,6 @@ target | notes `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support] `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) -[^missing-stack-probes]: Stack probes support is missing on - `aarch64-unknown-linux-gnu`, but it's planned to be implemented in the near - future. The implementation is tracked on [issue #77071][77071]. - [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community. [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue]. @@ -241,6 +237,7 @@ target | std | host | notes -------|:---:|:----:|------- [`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin +[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ? | | Arm64EC Windows MSVC `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS Simulator diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md new file mode 100644 index 00000000000..1bb2c677b08 --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md @@ -0,0 +1,69 @@ +# `arm64ec-pc-windows-msvc` + +**Tier: 3** + +Arm64EC ("Emulation Compatible") for mixed architecture (AArch64 and x86_64) +applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windows/arm/arm64ec>. + +## Target maintainers + +- [@dpaoliello](https://github.com/dpaoliello) + +## Requirements + +Target only supports cross-compilation, `core` and `alloc` are supported but +`std` is not. + +Builds Arm64EC static and dynamic libraries and executables which can be run on +AArch64 Windows 11 devices. Arm64EC static libraries can also be linked into +Arm64X dynamic libraries and executables. + +Uses `arm64ec` as its `target_arch` - code built for Arm64EC must be compatible +with x86_64 code (e.g., same structure layouts, function signatures, etc.) but +use AArch64 intrinsics. + +Only supported backend is LLVM 18 (or above). + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` +list in `config.toml` and disabling `std`: + +```toml +[build] +target = [ "arm64ec-pc-windows-msvc" ] + +[target.arm64ec-pc-windows-msvc] +no-std = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Tests can be run on AArch64 Windows 11 devices. + +Since this is a `no_std` target, the Rust test suite is not supported. + +## Cross-compilation toolchains and C code + +C code can be built using the Arm64-targetting MSVC toolchain. + +To compile: + +```bash +cl /arm64EC /c ... +``` + +To link: + +```bash +link /MACHINE:ARM64EC ... +``` + +Further reading: <https://learn.microsoft.com/en-us/windows/arm/arm64ec-build> diff --git a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md deleted file mode 100644 index 7c46811a27a..00000000000 --- a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md +++ /dev/null @@ -1,84 +0,0 @@ -# `diagnostic_namespace` - -The tracking issue for this feature is: [#111996] - -[#111996]: https://github.com/rust-lang/rust/issues/111996 - ------------------------- - -The `diagnostic_namespace` feature permits customization of compilation errors. - -## diagnostic::on_unimplemented - -With [#114452] support for `diagnostic::on_unimplemented` was added. - -When used on a trait declaration, the following options are available: - -* `message` to customize the primary error message -* `note` to add a customized note message to an error message -* `label` to customize the label part of the error message - -The attribute will hint to the compiler to use these in error messages: -```rust -// some library -#![feature(diagnostic_namespace)] - -#[diagnostic::on_unimplemented( - message = "cannot insert element", - label = "cannot be put into a table", - note = "see <link> for more information about the Table api" -)] -pub trait Element { - // ... -} -``` - -```rust,compile_fail,E0277 -# #![feature(diagnostic_namespace)] -# -# #[diagnostic::on_unimplemented( -# message = "cannot insert element", -# label = "cannot be put into a table", -# note = "see <link> for more information about the Table api" -# )] -# pub trait Element { -# // ... -# } -# struct Table; -# impl Table { -# fn insert<T: Element>(&self, element: T) { -# // .. -# } -# } -# fn main() { -# let table = Table; -# let element = (); -// user code -table.insert(element); -# } -``` - -```text -error[E0277]: cannot insert element - --> src/main.rs:24:18 - | -24 | table.insert(element); - | ------ ^^^^^^^ cannot be put into a table - | | - | required by a bound introduced by this call - | - = help: the trait `Element` is not implemented for `<type>` - = note: see <link> for more information about the Table api -note: required by a bound in `Table::insert` - --> src/main.rs:15:18 - | -15 | fn insert<T: Element>(&self, element: T) { - | ^^^^^^^ required by this bound in `Table::insert` - -For more information about this error, try `rustc --explain E0277`. -``` - -See [RFC 3368] for more information. - -[#114452]: https://github.com/rust-lang/rust/pull/114452 -[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index b91dc38e924..a3c857b0268 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -113,6 +113,7 @@ pub fn get_git_merge_base( /// Returns the files that have been modified in the current branch compared to the master branch. /// The `extensions` parameter can be used to filter the files by their extension. +/// Does not include removed files. /// If `extensions` is empty, all files will be returned. pub fn get_git_modified_files( config: &GitConfig<'_>, @@ -125,13 +126,19 @@ pub fn get_git_modified_files( if let Some(git_dir) = git_dir { git.current_dir(git_dir); } - let files = output_result(git.args(["diff-index", "--name-only", merge_base.trim()]))? + let files = output_result(git.args(["diff-index", "--name-status", merge_base.trim()]))? .lines() - .map(|s| s.trim().to_owned()) - .filter(|f| { - Path::new(f).extension().map_or(false, |ext| { + .filter_map(|f| { + let (status, name) = f.trim().split_once(char::is_whitespace).unwrap(); + if status == "D" { + None + } else if Path::new(name).extension().map_or(false, |ext| { extensions.is_empty() || extensions.contains(&ext.to_str().unwrap()) - }) + }) { + Some(name.to_owned()) + } else { + None + } }) .collect(); Ok(Some(files)) diff --git a/src/tools/cargo b/src/tools/cargo -Subproject f772ec0224d3755ce52ac5128a80319fb2eb45d +Subproject a4c63fe5388beaa09e5f91196c86addab0a0358 diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh index 11fd6b5c79e..2eafdd0fbc8 100755 --- a/src/tools/clippy/.github/driver.sh +++ b/src/tools/clippy/.github/driver.sh @@ -50,11 +50,11 @@ diff -u normalized.stderr tests/ui/double_neg.stderr # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same SYSROOT=$(rustc --print sysroot) -diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose) +diff -u <(./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose) echo "fn main() {}" >target/driver_test.rs # we can't run 2 rustcs on the same file at the same time -CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc) +CLIPPY=$(./target/debug/clippy-driver ./target/driver_test.rs --rustc) RUSTC=$(rustc ./target/driver_test.rs) diff -u <($CLIPPY) <($RUSTC) diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml index 5ba960db66d..603f91a910b 100644 --- a/src/tools/clippy/.github/workflows/clippy.yml +++ b/src/tools/clippy/.github/workflows/clippy.yml @@ -44,11 +44,6 @@ jobs: run: rustup show active-toolchain # Run - - name: Set LD_LIBRARY_PATH (Linux) - run: | - SYSROOT=$(rustc --print sysroot) - echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV - - name: Build run: cargo build --tests --features deny-warnings,internal @@ -72,6 +67,6 @@ jobs: working-directory: clippy_dev - name: Test clippy-driver - run: bash .github/driver.sh - env: - OS: ${{ runner.os }} + run: | + TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ') + rustup run $TOOLCHAIN bash .github/driver.sh diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index 012797e5ca7..0bc28c1f9d9 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -59,7 +59,7 @@ jobs: host: i686-unknown-linux-gnu - os: windows-latest host: x86_64-pc-windows-msvc - - os: macos-latest + - os: macos-13 host: x86_64-apple-darwin runs-on: ${{ matrix.os }} @@ -87,23 +87,6 @@ jobs: rustup show active-toolchain # Run - - name: Set LD_LIBRARY_PATH (Linux) - if: runner.os == 'Linux' - run: | - SYSROOT=$(rustc --print sysroot) - echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV - - name: Link rustc dylib (MacOS) - if: runner.os == 'macOS' - run: | - SYSROOT=$(rustc --print sysroot) - sudo mkdir -p /usr/local/lib - sudo find "${SYSROOT}/lib" -maxdepth 1 -name '*dylib' -exec ln -s {} /usr/local/lib \; - - name: Set PATH (Windows) - if: runner.os == 'Windows' - run: | - SYSROOT=$(rustc --print sysroot) - echo "$SYSROOT/bin" >> $GITHUB_PATH - - name: Build run: cargo build --tests --features deny-warnings,internal @@ -136,7 +119,9 @@ jobs: working-directory: clippy_dev - name: Test clippy-driver - run: bash .github/driver.sh + run: | + TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ') + rustup run $TOOLCHAIN bash .github/driver.sh env: OS: ${{ runner.os }} @@ -236,11 +221,6 @@ jobs: - name: Install toolchain run: rustup show active-toolchain - - name: Set LD_LIBRARY_PATH - run: | - SYSROOT=$(rustc --print sysroot) - echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV - # Download - name: Download target dir uses: actions/download-artifact@v3 @@ -254,8 +234,8 @@ jobs: # Run - name: Test ${{ matrix.integration }} run: | - RUSTUP_TOOLCHAIN="$(rustup show active-toolchain | grep -o -E "nightly-[0-9]{4}-[0-9]{2}-[0-9]{2}")" \ - $CARGO_TARGET_DIR/debug/integration --show-output + TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ') + rustup run $TOOLCHAIN $CARGO_TARGET_DIR/debug/integration --show-output env: INTEGRATION: ${{ matrix.integration }} diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index f0b01742deb..d3b2c0a7bf6 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -5046,6 +5046,7 @@ Released 2018-09-13 [`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops +[`assigning_clones`]: https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones [`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async [`await_holding_invalid_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock @@ -5423,6 +5424,7 @@ Released 2018-09-13 [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes +[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression [`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files @@ -5816,74 +5818,74 @@ Released 2018-09-13 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset <!-- end autogenerated links to lint list --> <!-- begin autogenerated links to configuration documentation --> +[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates +[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments +[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes +[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement +[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero +[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests +[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests +[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings +[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests +[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception +[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles +[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates +[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars +[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts +[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports [`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed [`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary [`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary +[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold [`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api -[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv +[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types +[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish +[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold -[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros +[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods [`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names -[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline -[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types [`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents -[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold -[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold -[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold -[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send +[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow +[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames [`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold -[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold [`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold -[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability +[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold -[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else +[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools +[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size +[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools +[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length +[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds +[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold +[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items +[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit -[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold -[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold +[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior +[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline +[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold [`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold -[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold -[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds -[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools -[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools -[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports -[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros -[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods -[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types -[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions -[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive -[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else -[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish [`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces -[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames -[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts -[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send -[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length -[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types -[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size -[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests -[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests -[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests -[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests -[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold -[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability -[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold [`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const -[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items -[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold +[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold +[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold [`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size -[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception -[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars -[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold -[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement -[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes -[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings -[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments -[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates -[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles -[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates -[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow -[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items -[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior -[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero -[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports +[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions +[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive +[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold +[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports <!-- end autogenerated links to configuration documentation --> diff --git a/src/tools/clippy/book/src/development/trait_checking.md b/src/tools/clippy/book/src/development/trait_checking.md index fb263922cf8..b7d229ccc19 100644 --- a/src/tools/clippy/book/src/development/trait_checking.md +++ b/src/tools/clippy/book/src/development/trait_checking.md @@ -94,6 +94,53 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait { } ``` +## Creating Types Programmatically + +Traits are often generic over a type parameter, e.g. `Borrow<T>` is generic +over `T`. Rust allows us to implement a trait for a specific type. For example, +we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose +that we would like to find whether our type actually implements `Borrow<[u8]>`. + +To do so, we can use the same `implements_trait` function as above, and supply +a type parameter that represents `[u8]`. Since `[u8]` is a specialization of +`[T]`, we can use the [`Ty::new_slice`][new_slice] method to create a type +that represents `[T]` and supply `u8` as a type parameter. +To create a `ty::Ty` programmatically, we rely on `Ty::new_*` methods. These +methods create a `TyKind` and then wrap it in a `Ty` struct. This means we +have access to all the primitive types, such as `Ty::new_char`, +`Ty::new_bool`, `Ty::new_int`, etc. We can also create more complex types, +such as slices, tuples, and references out of these basic building blocks. + +For trait checking, it is not enough to create the types, we need to convert +them into [GenericArg]. In rustc, a generic is an entity that the compiler +understands and has three kinds, type, const and lifetime. By calling +`.into()` on a constructed [Ty], we wrap the type into a generic which can +then be used by the query system to decide whether the specialized trait +is implemented. + +The following code demonstrates how to do this: + +```rust + +use rustc_middle::ty::Ty; +use clippy_utils::ty::implements_trait; +use rustc_span::symbol::sym; + +let ty = todo!("Get the `Foo` type to check for a trait implementation"); +let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code +let slice_of_bytes_t = Ty::new_slice(cx.tcx, cx.tcx.types.u8); +let generic_param = slice_of_bytes_t.into(); +if implements_trait(cx, ty, borrow_id, &[generic_param]) { + todo!("Rest of lint implementation") +} +``` + +In essence, the [Ty] struct allows us to create types programmatically in a +representation that can be used by the compiler and the query engine. We then +use the `rustc_middle::Ty` of the type we are interested in, and query the +compiler to see if it indeed implements the trait we are interested in. + + [DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html [lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html @@ -102,4 +149,7 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait { [symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html [symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html [TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html +[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html [rust]: https://github.com/rust-lang/rust +[new_slice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.new_slice +[GenericArg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md index dc29ab5d08d..136b3fd0270 100644 --- a/src/tools/clippy/book/src/development/type_checking.md +++ b/src/tools/clippy/book/src/development/type_checking.md @@ -123,6 +123,22 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies. > **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs. +## Creating Types programmatically + +A common usecase for creating types programmatically is when we want to check if a type implements a trait (see +[Trait Checking](trait_checking.md)). + +Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]` + +```rust +use rustc_middle::ty::Ty; +// assume we have access to a LateContext +let ty = Ty::new_slice(cx.tcx, Ty::new_u8()); +``` + +In general, we rely on `Ty::new_*` methods. These methods define the basic building-blocks that the +type-system and trait-system use to define and understand the written code. + ## Useful Links Below are some useful links to further explore the concepts covered diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 214a60d3bfd..a985346b3c0 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -10,334 +10,252 @@ and lints affected. --- -## `arithmetic-side-effects-allowed` -Suppress checking of the passed type names in all types of operations. - -If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. - -#### Example - -```toml -arithmetic-side-effects-allowed = ["SomeType", "AnotherType"] -``` - -#### Noteworthy - -A type, say `SomeType`, listed in this configuration has the same behavior of -`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. +## `absolute-paths-allowed-crates` +Which crates to allow absolute paths from **Default Value:** `[]` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) - - -## `arithmetic-side-effects-allowed-binary` -Suppress checking of the passed type pair names in binary operations like addition or -multiplication. - -Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless -of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`. +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) -Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as -`["AnotherType", "SomeType"]`. -#### Example - -```toml -arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] -``` +## `absolute-paths-max-segments` +The maximum number of segments a path can have before being linted, anything above this will +be linted. -**Default Value:** `[]` +**Default Value:** `2` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) - - -## `arithmetic-side-effects-allowed-unary` -Suppress checking of the passed type names in unary operations like "negation" (`-`). +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) -#### Example -```toml -arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] -``` +## `accept-comment-above-attributes` +Whether to accept a safety comment to be placed above the attributes for the `unsafe` block -**Default Value:** `[]` +**Default Value:** `true` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) -## `avoid-breaking-exported-api` -Suppress lints whenever the suggested change would cause breakage for other crates. +## `accept-comment-above-statement` +Whether to accept a safety comment to be placed above the statement containing the `unsafe` block **Default Value:** `true` --- **Affected lints:** -* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) -* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) -* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) -* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) -* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) -* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) -* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) -* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) -## `msrv` -The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` +## `allow-comparison-to-zero` +Don't lint when comparing the result of a modulo operation to zero. + +**Default Value:** `true` --- **Affected lints:** -* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) -* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) -* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) -* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) -* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) -* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) -* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) -* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) -* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) -* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) -* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) -* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) -* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) -* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) -* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) -* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) -* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) -* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) -* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) -* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) -* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) -* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) -* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) -* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) -* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) -* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) -* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) -* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) -* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) -* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) -* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) -* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) -* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) -* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) -* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) -* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) -* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) -* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) -* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) -* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) -* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) -* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) -* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) +* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) -## `cognitive-complexity-threshold` -The maximum cognitive complexity a function can have +## `allow-dbg-in-tests` +Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` -**Default Value:** `25` +**Default Value:** `false` --- **Affected lints:** -* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) -## `excessive-nesting-threshold` -The maximum amount of nesting a block can reside in +## `allow-expect-in-tests` +Whether `expect` should be allowed in test functions or `#[cfg(test)]` -**Default Value:** `0` +**Default Value:** `false` --- **Affected lints:** -* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) -## `disallowed-names` -The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value -`".."` can be used as part of the list to indicate that the configured values should be appended to the -default configuration of Clippy. By default, any configuration will replace the default value. +## `allow-mixed-uninlined-format-args` +Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` -**Default Value:** `["foo", "baz", "quux"]` +**Default Value:** `true` --- **Affected lints:** -* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -## `semicolon-inside-block-ignore-singleline` -Whether to lint only if it's multiline. +## `allow-one-hash-in-raw-strings` +Whether to allow `r#""#` when `r""` can be used **Default Value:** `false` --- **Affected lints:** -* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) +* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) -## `semicolon-outside-block-ignore-multiline` -Whether to lint only if it's singleline. +## `allow-print-in-tests` +Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` --- **Affected lints:** -* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) +* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -## `doc-valid-idents` -The list of words this lint should not consider as identifiers needing ticks. The value -`".."` can be used as part of the list to indicate, that the configured values should be appended to the -default configuration of Clippy. By default, any configuration will replace the default value. For example: -* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. -* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. +## `allow-private-module-inception` +Whether to allow module inception if it's not public. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `false` --- **Affected lints:** -* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) +* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) -## `too-many-arguments-threshold` -The maximum number of argument a function or method can have +## `allow-unwrap-in-tests` +Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` -**Default Value:** `7` +**Default Value:** `false` --- **Affected lints:** -* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) -## `type-complexity-threshold` -The maximum complexity a type can have +## `allowed-dotfiles` +Additional dotfiles (files or directories starting with a dot) to allow -**Default Value:** `250` +**Default Value:** `[]` --- **Affected lints:** -* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) +* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) -## `single-char-binding-names-threshold` -The maximum number of single char bindings a scope may have +## `allowed-duplicate-crates` +A list of crate names to allow duplicates of -**Default Value:** `4` +**Default Value:** `[]` --- **Affected lints:** -* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) -## `too-large-for-stack` -The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap +## `allowed-idents-below-min-chars` +Allowed names below the minimum allowed characters. The value `".."` can be used as part of +the list to indicate, that the configured values should be appended to the default +configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `200` +**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` --- **Affected lints:** -* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) -* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) -## `enum-variant-name-threshold` -The minimum number of enum variants for the lints about variant names to trigger +## `allowed-scripts` +The list of unicode scripts allowed to be used in the scope. -**Default Value:** `3` +**Default Value:** `["Latin"]` --- **Affected lints:** -* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) -## `struct-field-name-threshold` -The minimum number of struct fields for the lints about field names to trigger +## `allowed-wildcard-imports` +List of path segments allowed to have wildcard imports. -**Default Value:** `3` +#### Example ---- -**Affected lints:** -* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) +```toml +allowed-wildcard-imports = [ "utils", "common" ] +``` +#### Noteworthy -## `enum-variant-size-threshold` -The maximum size of an enum's variant to avoid box suggestion +1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. +2. Paths with any segment that containing the word 'prelude' +are already allowed by default. -**Default Value:** `200` +**Default Value:** `[]` --- **Affected lints:** -* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) -## `verbose-bit-mask-threshold` -The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' +## `arithmetic-side-effects-allowed` +Suppress checking of the passed type names in all types of operations. -**Default Value:** `1` +If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. ---- -**Affected lints:** -* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) +#### Example +```toml +arithmetic-side-effects-allowed = ["SomeType", "AnotherType"] +``` -## `literal-representation-threshold` -The lower bound for linting decimal literals +#### Noteworthy -**Default Value:** `16384` +A type, say `SomeType`, listed in this configuration has the same behavior of +`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. + +**Default Value:** `[]` --- **Affected lints:** -* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -## `trivial-copy-size-limit` -The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by -reference. By default there is no limit +## `arithmetic-side-effects-allowed-binary` +Suppress checking of the passed type pair names in binary operations like addition or +multiplication. ---- -**Affected lints:** -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless +of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`. +Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as +`["AnotherType", "SomeType"]`. -## `pass-by-value-size-limit` -The minimum size (in bytes) to consider a type for passing by reference instead of by value. +#### Example -**Default Value:** `256` +```toml +arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] +``` + +**Default Value:** `[]` --- **Affected lints:** -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -## `too-many-lines-threshold` -The maximum number of lines a function or method can have +## `arithmetic-side-effects-allowed-unary` +Suppress checking of the passed type names in unary operations like "negation" (`-`). -**Default Value:** `100` +#### Example + +```toml +arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] +``` + +**Default Value:** `[]` --- **Affected lints:** -* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) ## `array-size-threshold` @@ -347,68 +265,76 @@ The maximum allowed size for arrays on the stack --- **Affected lints:** -* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) * [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) +* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) -## `stack-size-threshold` -The maximum allowed stack size for functions in bytes - -**Default Value:** `512000` - ---- -**Affected lints:** -* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) - - -## `vec-box-size-threshold` -The size of the boxed type in bytes, where boxing in a `Vec` is allowed +## `avoid-breaking-exported-api` +Suppress lints whenever the suggested change would cause breakage for other crates. -**Default Value:** `4096` +**Default Value:** `true` --- **Affected lints:** +* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) +* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) +* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) +* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) +* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) +* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) +* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) * [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -## `max-trait-bounds` -The maximum number of bounds a trait can have to be linted +## `await-holding-invalid-types` -**Default Value:** `3` + +**Default Value:** `[]` --- **Affected lints:** -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) -## `max-struct-bools` -The maximum number of bool fields a struct can have +## `cargo-ignore-publish` +For internal testing only, ignores the current `publish` settings in the Cargo manifest. -**Default Value:** `3` +**Default Value:** `false` --- **Affected lints:** -* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) +* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) -## `max-fn-params-bools` -The maximum number of bool parameters a function can have +## `check-private-items` +Whether to also run the listed lints on private items. -**Default Value:** `3` +**Default Value:** `false` --- **Affected lints:** -* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) +* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) +* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) +* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) +* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) -## `warn-on-all-wildcard-imports` -Whether to allow certain wildcard imports (prelude, super in tests). +## `cognitive-complexity-threshold` +The maximum cognitive complexity a function can have -**Default Value:** `false` +**Default Value:** `25` --- **Affected lints:** -* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) ## `disallowed-macros` @@ -431,218 +357,231 @@ The list of disallowed methods, written as fully qualified paths. * [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) -## `disallowed-types` -The list of disallowed types, written as fully qualified paths. +## `disallowed-names` +The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value +`".."` can be used as part of the list to indicate that the configured values should be appended to the +default configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `[]` +**Default Value:** `["foo", "baz", "quux"]` --- **Affected lints:** -* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) +* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) -## `unreadable-literal-lint-fractions` -Should the fraction of a decimal be linted to include separators. +## `disallowed-types` +The list of disallowed types, written as fully qualified paths. -**Default Value:** `true` +**Default Value:** `[]` --- **Affected lints:** -* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) +* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) -## `upper-case-acronyms-aggressive` -Enables verbose mode. Triggers if there is more than one uppercase char next to each other +## `doc-valid-idents` +The list of words this lint should not consider as identifiers needing ticks. The value +`".."` can be used as part of the list to indicate, that the configured values should be appended to the +default configuration of Clippy. By default, any configuration will replace the default value. For example: +* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. +* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `false` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) -## `matches-for-let-else` -Whether the matches should be considered by the lint, and whether there should -be filtering for common types. +## `enable-raw-pointer-heuristic-for-send` +Whether to apply the raw pointer heuristic to determine if a type is `Send`. -**Default Value:** `"WellKnownTypes"` +**Default Value:** `true` --- **Affected lints:** -* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) -## `cargo-ignore-publish` -For internal testing only, ignores the current `publish` settings in the Cargo manifest. +## `enforce-iter-loop-reborrow` +Whether to recommend using implicit into iter for reborrowed values. + +#### Example +```no_run +let mut vec = vec![1, 2, 3]; +let rmvec = &mut vec; +for _ in rmvec.iter() {} +for _ in rmvec.iter_mut() {} +``` + +Use instead: +```no_run +let mut vec = vec![1, 2, 3]; +let rmvec = &mut vec; +for _ in &*rmvec {} +for _ in &mut *rmvec {} +``` **Default Value:** `false` --- **Affected lints:** -* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) - +* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) -## `standard-macro-braces` -Enforce the named macros always use the braces specified. -A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro -could be used with a full path two `MacroMatcher`s have to be added one with the full path -`crate_name::macro_name` and one with just the macro name. +## `enforced-import-renames` +The list of imports to always rename, a fully qualified path followed by the rename. **Default Value:** `[]` --- **Affected lints:** -* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) +* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) -## `enforced-import-renames` -The list of imports to always rename, a fully qualified path followed by the rename. +## `enum-variant-name-threshold` +The minimum number of enum variants for the lints about variant names to trigger -**Default Value:** `[]` +**Default Value:** `3` --- **Affected lints:** -* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -## `allowed-scripts` -The list of unicode scripts allowed to be used in the scope. +## `enum-variant-size-threshold` +The maximum size of an enum's variant to avoid box suggestion -**Default Value:** `["Latin"]` +**Default Value:** `200` --- **Affected lints:** -* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) +* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) -## `enable-raw-pointer-heuristic-for-send` -Whether to apply the raw pointer heuristic to determine if a type is `Send`. +## `excessive-nesting-threshold` +The maximum amount of nesting a block can reside in -**Default Value:** `true` +**Default Value:** `0` --- **Affected lints:** -* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) +* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) -## `max-suggested-slice-pattern-length` -When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in -the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. -For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. +## `future-size-threshold` +The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint -**Default Value:** `3` +**Default Value:** `16384` --- **Affected lints:** -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) - +* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) -## `await-holding-invalid-types` +## `ignore-interior-mutability` +A list of paths to types that should be treated like `Arc`, i.e. ignored but +for the generic parameters for determining interior mutability -**Default Value:** `[]` +**Default Value:** `["bytes::Bytes"]` --- **Affected lints:** -* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) +* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -## `max-include-file-size` -The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes +## `large-error-threshold` +The maximum size of the `Err`-variant in a `Result` returned from a function -**Default Value:** `1000000` +**Default Value:** `128` --- **Affected lints:** -* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) -## `allow-expect-in-tests` -Whether `expect` should be allowed in test functions or `#[cfg(test)]` +## `literal-representation-threshold` +The lower bound for linting decimal literals -**Default Value:** `false` +**Default Value:** `16384` --- **Affected lints:** -* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) -## `allow-unwrap-in-tests` -Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` +## `matches-for-let-else` +Whether the matches should be considered by the lint, and whether there should +be filtering for common types. -**Default Value:** `false` +**Default Value:** `"WellKnownTypes"` --- **Affected lints:** -* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -## `allow-dbg-in-tests` -Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` +## `max-fn-params-bools` +The maximum number of bool parameters a function can have -**Default Value:** `false` +**Default Value:** `3` --- **Affected lints:** -* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) -## `allow-print-in-tests` -Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` +## `max-include-file-size` +The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes -**Default Value:** `false` +**Default Value:** `1000000` --- **Affected lints:** -* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) -## `large-error-threshold` -The maximum size of the `Err`-variant in a `Result` returned from a function +## `max-struct-bools` +The maximum number of bool fields a struct can have -**Default Value:** `128` +**Default Value:** `3` --- **Affected lints:** -* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) -## `ignore-interior-mutability` -A list of paths to types that should be treated like `Arc`, i.e. ignored but -for the generic parameters for determining interior mutability +## `max-suggested-slice-pattern-length` +When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in +the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. +For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. -**Default Value:** `["bytes::Bytes"]` +**Default Value:** `3` --- **Affected lints:** -* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -## `allow-mixed-uninlined-format-args` -Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` +## `max-trait-bounds` +The maximum number of bounds a trait can have to be linted -**Default Value:** `true` +**Default Value:** `3` --- **Affected lints:** -* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -## `suppress-restriction-lint-in-const` -Whether to suppress a restriction lint in constant code. In same -cases the restructured operation might not be unavoidable, as the -suggested counterparts are unavailable in constant code. This -configuration will cause restriction lints to trigger even -if no suggestion can be made. +## `min-ident-chars-threshold` +Minimum chars an ident can have, anything below or equal to this will be linted. -**Default Value:** `false` +**Default Value:** `1` --- **Affected lints:** -* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) ## `missing-docs-in-crate-items` @@ -656,205 +595,266 @@ crate. For example, `pub(crate)` items. * [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) -## `future-size-threshold` -The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint +## `msrv` +The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` + +--- +**Affected lints:** +* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) +* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) +* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) +* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) +* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) +* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) +* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) +* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) +* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) +* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) +* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) +* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) +* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) +* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) +* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) +* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) +* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) +* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) +* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) +* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) +* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) +* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) +* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) +* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) +* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) +* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) +* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) +* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) +* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) +* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) +* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) +* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) +* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) +* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) +* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) +* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) +* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) +* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) +* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) +* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) +* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -**Default Value:** `16384` + +## `pass-by-value-size-limit` +The minimum size (in bytes) to consider a type for passing by reference instead of by value. + +**Default Value:** `256` --- **Affected lints:** -* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -## `unnecessary-box-size` -The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint +## `pub-underscore-fields-behavior` +Lint "public" fields in a struct that are prefixed with an underscore based on their +exported visibility, or whether they are marked as "pub". -**Default Value:** `128` +**Default Value:** `"PubliclyExported"` --- **Affected lints:** -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) -## `allow-private-module-inception` -Whether to allow module inception if it's not public. +## `semicolon-inside-block-ignore-singleline` +Whether to lint only if it's multiline. **Default Value:** `false` --- **Affected lints:** -* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) +* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) -## `allowed-idents-below-min-chars` -Allowed names below the minimum allowed characters. The value `".."` can be used as part of -the list to indicate, that the configured values should be appended to the default -configuration of Clippy. By default, any configuration will replace the default value. +## `semicolon-outside-block-ignore-multiline` +Whether to lint only if it's singleline. -**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` +**Default Value:** `false` --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) -## `min-ident-chars-threshold` -Minimum chars an ident can have, anything below or equal to this will be linted. +## `single-char-binding-names-threshold` +The maximum number of single char bindings a scope may have -**Default Value:** `1` +**Default Value:** `4` --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) -## `accept-comment-above-statement` -Whether to accept a safety comment to be placed above the statement containing the `unsafe` block +## `stack-size-threshold` +The maximum allowed stack size for functions in bytes -**Default Value:** `true` +**Default Value:** `512000` --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) -## `accept-comment-above-attributes` -Whether to accept a safety comment to be placed above the attributes for the `unsafe` block +## `standard-macro-braces` +Enforce the named macros always use the braces specified. -**Default Value:** `true` +A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro +could be used with a full path two `MacroMatcher`s have to be added one with the full path +`crate_name::macro_name` and one with just the macro name. + +**Default Value:** `[]` --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) -## `allow-one-hash-in-raw-strings` -Whether to allow `r#""#` when `r""` can be used +## `struct-field-name-threshold` +The minimum number of struct fields for the lints about field names to trigger -**Default Value:** `false` +**Default Value:** `3` --- **Affected lints:** -* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) +* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) -## `absolute-paths-max-segments` -The maximum number of segments a path can have before being linted, anything above this will -be linted. +## `suppress-restriction-lint-in-const` +Whether to suppress a restriction lint in constant code. In same +cases the restructured operation might not be unavoidable, as the +suggested counterparts are unavailable in constant code. This +configuration will cause restriction lints to trigger even +if no suggestion can be made. -**Default Value:** `2` +**Default Value:** `false` --- **Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) +* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) -## `absolute-paths-allowed-crates` -Which crates to allow absolute paths from +## `too-large-for-stack` +The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap -**Default Value:** `[]` +**Default Value:** `200` --- **Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) +* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) -## `allowed-dotfiles` -Additional dotfiles (files or directories starting with a dot) to allow +## `too-many-arguments-threshold` +The maximum number of argument a function or method can have -**Default Value:** `[]` +**Default Value:** `7` --- **Affected lints:** -* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) +* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) -## `allowed-duplicate-crates` -A list of crate names to allow duplicates of +## `too-many-lines-threshold` +The maximum number of lines a function or method can have -**Default Value:** `[]` +**Default Value:** `100` --- **Affected lints:** -* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) +* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) -## `enforce-iter-loop-reborrow` -Whether to recommend using implicit into iter for reborrowed values. +## `trivial-copy-size-limit` +The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by +reference. By default there is no limit -#### Example -```no_run -let mut vec = vec![1, 2, 3]; -let rmvec = &mut vec; -for _ in rmvec.iter() {} -for _ in rmvec.iter_mut() {} -``` +--- +**Affected lints:** +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -Use instead: -```no_run -let mut vec = vec![1, 2, 3]; -let rmvec = &mut vec; -for _ in &*rmvec {} -for _ in &mut *rmvec {} -``` -**Default Value:** `false` +## `type-complexity-threshold` +The maximum complexity a type can have + +**Default Value:** `250` --- **Affected lints:** -* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) +* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) -## `check-private-items` -Whether to also run the listed lints on private items. +## `unnecessary-box-size` +The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint -**Default Value:** `false` +**Default Value:** `128` --- **Affected lints:** -* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) -* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) -* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) -* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) -## `pub-underscore-fields-behavior` -Lint "public" fields in a struct that are prefixed with an underscore based on their -exported visibility, or whether they are marked as "pub". +## `unreadable-literal-lint-fractions` +Should the fraction of a decimal be linted to include separators. -**Default Value:** `"PubliclyExported"` +**Default Value:** `true` --- **Affected lints:** -* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) +* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) -## `allow-comparison-to-zero` -Don't lint when comparing the result of a modulo operation to zero. +## `upper-case-acronyms-aggressive` +Enables verbose mode. Triggers if there is more than one uppercase char next to each other -**Default Value:** `true` +**Default Value:** `false` --- **Affected lints:** -* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -## `allowed-wildcard-imports` -List of path segments allowed to have wildcard imports. +## `vec-box-size-threshold` +The size of the boxed type in bytes, where boxing in a `Vec` is allowed -#### Example +**Default Value:** `4096` -```toml -allowed-wildcard-imports = [ "utils", "common" ] -``` +--- +**Affected lints:** +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -#### Noteworthy -1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. -2. Paths with any segment that containing the word 'prelude' -are already allowed by default. +## `verbose-bit-mask-threshold` +The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' -**Default Value:** `[]` +**Default Value:** `1` + +--- +**Affected lints:** +* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) + + +## `warn-on-all-wildcard-imports` +Whether to allow certain wildcard imports (prelude, super in tests). + +**Default Value:** `false` --- **Affected lints:** diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index b781259ad96..673b6328b39 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -193,7 +193,7 @@ macro_rules! define_Conf { } pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> { - vec![ + let mut sorted = vec![ $( { let deprecation_reason = wrap_option!($($dep)?); @@ -206,7 +206,9 @@ macro_rules! define_Conf { ) }, )+ - ] + ]; + sorted.sort_by(|a, b| a.name.cmp(&b.name)); + sorted } }; } diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index 3d5002f1780..01e2aa6e0a6 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -5,7 +5,7 @@ clippy::must_use_candidate, clippy::missing_panics_doc, rustc::diagnostic_outside_of_impl, - rustc::untranslatable_diagnostic, + rustc::untranslatable_diagnostic )] extern crate rustc_ast; diff --git a/src/tools/clippy/clippy_config/src/metadata.rs b/src/tools/clippy/clippy_config/src/metadata.rs index 3ba2796e18d..400887185e8 100644 --- a/src/tools/clippy/clippy_config/src/metadata.rs +++ b/src/tools/clippy/clippy_config/src/metadata.rs @@ -26,9 +26,11 @@ impl ClippyConfiguration { doc_comment: &'static str, deprecation_reason: Option<&'static str>, ) -> Self { - let (lints, doc) = parse_config_field_doc(doc_comment) + let (mut lints, doc) = parse_config_field_doc(doc_comment) .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string())); + lints.sort(); + Self { name: to_kebab(name), lints, diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index f4389db627d..a8a32f7ed20 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -24,6 +24,7 @@ msrv_aliases! { 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } + 1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } 1,55,0 { SEEK_REWIND } 1,54,0 { INTO_KEYS } diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs new file mode 100644 index 00000000000..b1c552c7a8d --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -0,0 +1,322 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::macros::HirNode; +use clippy_utils::sugg::Sugg; +use clippy_utils::{is_trait_method, path_to_local}; +use rustc_errors::Applicability; +use rustc_hir::{self as hir, Expr, ExprKind, Node}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Instance, Mutability}; +use rustc_session::declare_lint_pass; +use rustc_span::def_id::DefId; +use rustc_span::symbol::sym; +use rustc_span::ExpnKind; + +declare_clippy_lint! { + /// ### What it does + /// Checks for code like `foo = bar.clone();` + /// + /// ### Why is this bad? + /// Custom `Clone::clone_from()` or `ToOwned::clone_into` implementations allow the objects + /// to share resources and therefore avoid allocations. + /// + /// ### Example + /// ```rust + /// struct Thing; + /// + /// impl Clone for Thing { + /// fn clone(&self) -> Self { todo!() } + /// fn clone_from(&mut self, other: &Self) { todo!() } + /// } + /// + /// pub fn assign_to_ref(a: &mut Thing, b: Thing) { + /// *a = b.clone(); + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct Thing; + /// impl Clone for Thing { + /// fn clone(&self) -> Self { todo!() } + /// fn clone_from(&mut self, other: &Self) { todo!() } + /// } + /// + /// pub fn assign_to_ref(a: &mut Thing, b: Thing) { + /// a.clone_from(&b); + /// } + /// ``` + #[clippy::version = "1.77.0"] + pub ASSIGNING_CLONES, + perf, + "assigning the result of cloning may be inefficient" +} +declare_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); + +impl<'tcx> LateLintPass<'tcx> for AssigningClones { + fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) { + // Do not fire the lint in macros + let expn_data = assign_expr.span().ctxt().outer_expn_data(); + match expn_data.kind { + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) | ExpnKind::Macro(..) => return, + ExpnKind::Root => {}, + } + + let ExprKind::Assign(lhs, rhs, _span) = assign_expr.kind else { + return; + }; + + let Some(call) = extract_call(cx, rhs) else { + return; + }; + + if is_ok_to_suggest(cx, lhs, &call) { + suggest(cx, assign_expr, lhs, &call); + } + } +} + +// Try to resolve the call to `Clone::clone` or `ToOwned::to_owned`. +fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<CallCandidate<'tcx>> { + let fn_def_id = clippy_utils::fn_def_id(cx, expr)?; + + // Fast paths to only check method calls without arguments or function calls with a single argument + let (target, kind, resolved_method) = match expr.kind { + ExprKind::MethodCall(path, receiver, [], _span) => { + let args = cx.typeck_results().node_args(expr.hir_id); + + // If we could not resolve the method, don't apply the lint + let Ok(Some(resolved_method)) = Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args) else { + return None; + }; + if is_trait_method(cx, expr, sym::Clone) && path.ident.name == sym::clone { + (TargetTrait::Clone, CallKind::MethodCall { receiver }, resolved_method) + } else if is_trait_method(cx, expr, sym::ToOwned) && path.ident.name.as_str() == "to_owned" { + (TargetTrait::ToOwned, CallKind::MethodCall { receiver }, resolved_method) + } else { + return None; + } + }, + ExprKind::Call(function, [arg]) => { + let kind = cx.typeck_results().node_type(function.hir_id).kind(); + + // If we could not resolve the method, don't apply the lint + let Ok(Some(resolved_method)) = (match kind { + ty::FnDef(_, args) => Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args), + _ => Ok(None), + }) else { + return None; + }; + if cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id) { + ( + TargetTrait::ToOwned, + CallKind::FunctionCall { self_arg: arg }, + resolved_method, + ) + } else if let Some(trait_did) = cx.tcx.trait_of_item(fn_def_id) + && cx.tcx.is_diagnostic_item(sym::Clone, trait_did) + { + ( + TargetTrait::Clone, + CallKind::FunctionCall { self_arg: arg }, + resolved_method, + ) + } else { + return None; + } + }, + _ => return None, + }; + + Some(CallCandidate { + target, + kind, + method_def_id: resolved_method.def_id(), + }) +} + +// Return true if we find that the called method has a custom implementation and isn't derived or +// provided by default by the corresponding trait. +fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) -> bool { + // If the left-hand side is a local variable, it might be uninitialized at this point. + // In that case we do not want to suggest the lint. + if let Some(local) = path_to_local(lhs) { + // TODO: This check currently bails if the local variable has no initializer. + // That is overly conservative - the lint should fire even if there was no initializer, + // but the variable has been initialized before `lhs` was evaluated. + if let Some(Node::Local(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p)) + && local.init.is_none() + { + return false; + } + } + + let Some(impl_block) = cx.tcx.impl_of_method(call.method_def_id) else { + return false; + }; + + // If the method implementation comes from #[derive(Clone)], then don't suggest the lint. + // Automatically generated Clone impls do not currently override `clone_from`. + // See e.g. https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 for more details. + if cx.tcx.is_builtin_derived(impl_block) { + return false; + } + + // Find the function for which we want to check that it is implemented. + let provided_fn = match call.target { + TargetTrait::Clone => cx.tcx.get_diagnostic_item(sym::Clone).and_then(|clone| { + cx.tcx + .provided_trait_methods(clone) + .find(|item| item.name == sym::clone_from) + }), + TargetTrait::ToOwned => cx.tcx.get_diagnostic_item(sym::ToOwned).and_then(|to_owned| { + cx.tcx + .provided_trait_methods(to_owned) + .find(|item| item.name.as_str() == "clone_into") + }), + }; + let Some(provided_fn) = provided_fn else { + return false; + }; + + // Now take a look if the impl block defines an implementation for the method that we're interested + // in. If not, then we're using a default implementation, which is not interesting, so we will + // not suggest the lint. + let implemented_fns = cx.tcx.impl_item_implementor_ids(impl_block); + implemented_fns.contains_key(&provided_fn.def_id) +} + +fn suggest<'tcx>( + cx: &LateContext<'tcx>, + assign_expr: &hir::Expr<'tcx>, + lhs: &hir::Expr<'tcx>, + call: &CallCandidate<'tcx>, +) { + span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| { + let mut applicability = Applicability::MachineApplicable; + + diag.span_suggestion( + assign_expr.span, + call.suggestion_msg(), + call.suggested_replacement(cx, lhs, &mut applicability), + applicability, + ); + }); +} + +#[derive(Copy, Clone, Debug)] +enum CallKind<'tcx> { + MethodCall { receiver: &'tcx Expr<'tcx> }, + FunctionCall { self_arg: &'tcx Expr<'tcx> }, +} + +#[derive(Copy, Clone, Debug)] +enum TargetTrait { + Clone, + ToOwned, +} + +#[derive(Debug)] +struct CallCandidate<'tcx> { + target: TargetTrait, + kind: CallKind<'tcx>, + // DefId of the called method from an impl block that implements the target trait + method_def_id: DefId, +} + +impl<'tcx> CallCandidate<'tcx> { + #[inline] + fn message(&self) -> &'static str { + match self.target { + TargetTrait::Clone => "assigning the result of `Clone::clone()` may be inefficient", + TargetTrait::ToOwned => "assigning the result of `ToOwned::to_owned()` may be inefficient", + } + } + + #[inline] + fn suggestion_msg(&self) -> &'static str { + match self.target { + TargetTrait::Clone => "use `clone_from()`", + TargetTrait::ToOwned => "use `clone_into()`", + } + } + + fn suggested_replacement( + &self, + cx: &LateContext<'tcx>, + lhs: &hir::Expr<'tcx>, + applicability: &mut Applicability, + ) -> String { + match self.target { + TargetTrait::Clone => { + match self.kind { + CallKind::MethodCall { receiver } => { + let receiver_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind { + // `*lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)` + Sugg::hir_with_applicability(cx, ref_expr, "_", applicability) + } else { + // `lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)` + Sugg::hir_with_applicability(cx, lhs, "_", applicability) + } + .maybe_par(); + + // Determine whether we need to reference the argument to clone_from(). + let clone_receiver_type = cx.typeck_results().expr_ty(receiver); + let clone_receiver_adj_type = cx.typeck_results().expr_ty_adjusted(receiver); + let mut arg_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability); + if clone_receiver_type != clone_receiver_adj_type { + // The receiver may have been a value type, so we need to add an `&` to + // be sure the argument to clone_from will be a reference. + arg_sugg = arg_sugg.addr(); + }; + + format!("{receiver_sugg}.clone_from({arg_sugg})") + }, + CallKind::FunctionCall { self_arg, .. } => { + let self_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind { + // `*lhs = Clone::clone(self_expr);` -> `Clone::clone_from(lhs, self_expr)` + Sugg::hir_with_applicability(cx, ref_expr, "_", applicability) + } else { + // `lhs = Clone::clone(self_expr);` -> `Clone::clone_from(&mut lhs, self_expr)` + Sugg::hir_with_applicability(cx, lhs, "_", applicability).mut_addr() + }; + // The RHS had to be exactly correct before the call, there is no auto-deref for function calls. + let rhs_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability); + + format!("Clone::clone_from({self_sugg}, {rhs_sugg})") + }, + } + }, + TargetTrait::ToOwned => { + let rhs_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind { + // `*lhs = rhs.to_owned()` -> `rhs.clone_into(lhs)` + // `*lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, lhs)` + let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", applicability).maybe_par(); + let inner_type = cx.typeck_results().expr_ty(ref_expr); + // If after unwrapping the dereference, the type is not a mutable reference, we add &mut to make it + // deref to a mutable reference. + if matches!(inner_type.kind(), ty::Ref(_, _, Mutability::Mut)) { + sugg + } else { + sugg.mut_addr() + } + } else { + // `lhs = rhs.to_owned()` -> `rhs.clone_into(&mut lhs)` + // `lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, &mut lhs)` + Sugg::hir_with_applicability(cx, lhs, "_", applicability) + .maybe_par() + .mut_addr() + }; + + match self.kind { + CallKind::MethodCall { receiver } => { + let receiver_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability); + format!("{receiver_sugg}.clone_into({rhs_sugg})") + }, + CallKind::FunctionCall { self_arg, .. } => { + let self_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability); + format!("ToOwned::clone_into({self_sugg}, {rhs_sugg})") + }, + } + }, + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs deleted file mode 100644 index f2937d51340..00000000000 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ /dev/null @@ -1,1210 +0,0 @@ -//! checks for attributes - -use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::{ - span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, -}; -use clippy_utils::is_from_proc_macro; -use clippy_utils::macros::{is_panic, macro_backtrace}; -use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; -use rustc_ast::token::{Token, TokenKind}; -use rustc_ast::tokenstream::TokenTree; -use rustc_ast::{ - AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem, -}; -use rustc_errors::Applicability; -use rustc_hir::{ - Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, -}; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, impl_lint_pass}; -use rustc_span::symbol::Symbol; -use rustc_span::{sym, Span, DUMMY_SP}; -use semver::Version; - -static UNIX_SYSTEMS: &[&str] = &[ - "android", - "dragonfly", - "emscripten", - "freebsd", - "fuchsia", - "haiku", - "illumos", - "ios", - "l4re", - "linux", - "macos", - "netbsd", - "openbsd", - "redox", - "solaris", - "vxworks", -]; - -// NOTE: windows is excluded from the list because it's also a valid target family. -static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"]; - -declare_clippy_lint! { - /// ### What it does - /// Checks for items annotated with `#[inline(always)]`, - /// unless the annotated function is empty or simply panics. - /// - /// ### Why is this bad? - /// While there are valid uses of this annotation (and once - /// you know when to use it, by all means `allow` this lint), it's a common - /// newbie-mistake to pepper one's code with it. - /// - /// As a rule of thumb, before slapping `#[inline(always)]` on a function, - /// measure if that additional function call really affects your runtime profile - /// sufficiently to make up for the increase in compile time. - /// - /// ### Known problems - /// False positives, big time. This lint is meant to be - /// deactivated by everyone doing serious performance work. This means having - /// done the measurement. - /// - /// ### Example - /// ```ignore - /// #[inline(always)] - /// fn not_quite_hot_code(..) { ... } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub INLINE_ALWAYS, - pedantic, - "use of `#[inline(always)]`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `extern crate` and `use` items annotated with - /// lint attributes. - /// - /// This lint permits lint attributes for lints emitted on the items themself. - /// For `use` items these lints are: - /// * deprecated - /// * unreachable_pub - /// * unused_imports - /// * clippy::enum_glob_use - /// * clippy::macro_use_imports - /// * clippy::wildcard_imports - /// - /// For `extern crate` items these lints are: - /// * `unused_imports` on items with `#[macro_use]` - /// - /// ### Why is this bad? - /// Lint attributes have no effect on crate imports. Most - /// likely a `!` was forgotten. - /// - /// ### Example - /// ```ignore - /// #[deny(dead_code)] - /// extern crate foo; - /// #[forbid(dead_code)] - /// use foo::bar; - /// ``` - /// - /// Use instead: - /// ```rust,ignore - /// #[allow(unused_imports)] - /// use foo::baz; - /// #[allow(unused_imports)] - /// #[macro_use] - /// extern crate baz; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub USELESS_ATTRIBUTE, - correctness, - "use of lint attributes on `extern crate` items" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[deprecated]` annotations with a `since` - /// field that is not a valid semantic version. Also allows "TBD" to signal - /// future deprecation. - /// - /// ### Why is this bad? - /// For checking the version of the deprecation, it must be - /// a valid semver. Failing that, the contained information is useless. - /// - /// ### Example - /// ```no_run - /// #[deprecated(since = "forever")] - /// fn something_else() { /* ... */ } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DEPRECATED_SEMVER, - correctness, - "use of `#[deprecated(since = \"x\")]` where x is not semver" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for empty lines after outer attributes - /// - /// ### Why is this bad? - /// Most likely the attribute was meant to be an inner attribute using a '!'. - /// If it was meant to be an outer attribute, then the following item - /// should not be separated by empty lines. - /// - /// ### Known problems - /// Can cause false positives. - /// - /// From the clippy side it's difficult to detect empty lines between an attributes and the - /// following item because empty lines and comments are not part of the AST. The parsing - /// currently works for basic cases but is not perfect. - /// - /// ### Example - /// ```no_run - /// #[allow(dead_code)] - /// - /// fn not_quite_good_code() { } - /// ``` - /// - /// Use instead: - /// ```no_run - /// // Good (as inner attribute) - /// #![allow(dead_code)] - /// - /// fn this_is_fine() { } - /// - /// // or - /// - /// // Good (as outer attribute) - /// #[allow(dead_code)] - /// fn this_is_fine_too() { } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub EMPTY_LINE_AFTER_OUTER_ATTR, - nursery, - "empty line after outer attribute" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for empty lines after documentation comments. - /// - /// ### Why is this bad? - /// The documentation comment was most likely meant to be an inner attribute or regular comment. - /// If it was intended to be a documentation comment, then the empty line should be removed to - /// be more idiomatic. - /// - /// ### Known problems - /// Only detects empty lines immediately following the documentation. If the doc comment is followed - /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr` - /// in combination with this lint to detect both cases. - /// - /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`). - /// - /// ### Example - /// ```no_run - /// /// Some doc comment with a blank line after it. - /// - /// fn not_quite_good_code() { } - /// ``` - /// - /// Use instead: - /// ```no_run - /// /// Good (no blank line) - /// fn this_is_fine() { } - /// ``` - /// - /// ```no_run - /// // Good (convert to a regular comment) - /// - /// fn this_is_fine_too() { } - /// ``` - /// - /// ```no_run - /// //! Good (convert to a comment on an inner attribute) - /// - /// fn this_is_fine_as_well() { } - /// ``` - #[clippy::version = "1.70.0"] - pub EMPTY_LINE_AFTER_DOC_COMMENTS, - nursery, - "empty line after documentation comments" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category. - /// - /// ### Why is this bad? - /// Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust. - /// These lints should only be enabled on a lint-by-lint basis and with careful consideration. - /// - /// ### Example - /// ```no_run - /// #![deny(clippy::restriction)] - /// ``` - /// - /// Use instead: - /// ```no_run - /// #![deny(clippy::as_conversions)] - /// ``` - #[clippy::version = "1.47.0"] - pub BLANKET_CLIPPY_RESTRICTION_LINTS, - suspicious, - "enabling the complete restriction group" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it - /// with `#[rustfmt::skip]`. - /// - /// ### Why is this bad? - /// Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690)) - /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes. - /// - /// ### Known problems - /// This lint doesn't detect crate level inner attributes, because they get - /// processed before the PreExpansionPass lints get executed. See - /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765) - /// - /// ### Example - /// ```no_run - /// #[cfg_attr(rustfmt, rustfmt_skip)] - /// fn main() { } - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[rustfmt::skip] - /// fn main() { } - /// ``` - #[clippy::version = "1.32.0"] - pub DEPRECATED_CFG_ATTR, - complexity, - "usage of `cfg_attr(rustfmt)` instead of tool attributes" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for cfg attributes having operating systems used in target family position. - /// - /// ### Why is this bad? - /// The configuration option will not be recognised and the related item will not be included - /// by the conditional compilation engine. - /// - /// ### Example - /// ```no_run - /// #[cfg(linux)] - /// fn conditional() { } - /// ``` - /// - /// Use instead: - /// ```no_run - /// # mod hidden { - /// #[cfg(target_os = "linux")] - /// fn conditional() { } - /// # } - /// - /// // or - /// - /// #[cfg(unix)] - /// fn conditional() { } - /// ``` - /// Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details. - #[clippy::version = "1.45.0"] - pub MISMATCHED_TARGET_OS, - correctness, - "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for attributes that allow lints without a reason. - /// - /// (This requires the `lint_reasons` feature) - /// - /// ### Why is this bad? - /// Allowing a lint should always have a reason. This reason should be documented to - /// ensure that others understand the reasoning - /// - /// ### Example - /// ```no_run - /// #![feature(lint_reasons)] - /// - /// #![allow(clippy::some_lint)] - /// ``` - /// - /// Use instead: - /// ```no_run - /// #![feature(lint_reasons)] - /// - /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] - /// ``` - #[clippy::version = "1.61.0"] - pub ALLOW_ATTRIBUTES_WITHOUT_REASON, - restriction, - "ensures that all `allow` and `expect` attributes have a reason" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[should_panic]` attributes without specifying the expected panic message. - /// - /// ### Why is this bad? - /// The expected panic message should be specified to ensure that the test is actually - /// panicking with the expected message, and not another unrelated panic. - /// - /// ### Example - /// ```no_run - /// fn random() -> i32 { 0 } - /// - /// #[should_panic] - /// #[test] - /// fn my_test() { - /// let _ = 1 / random(); - /// } - /// ``` - /// - /// Use instead: - /// ```no_run - /// fn random() -> i32 { 0 } - /// - /// #[should_panic = "attempt to divide by zero"] - /// #[test] - /// fn my_test() { - /// let _ = 1 / random(); - /// } - /// ``` - #[clippy::version = "1.74.0"] - pub SHOULD_PANIC_WITHOUT_EXPECT, - pedantic, - "ensures that all `should_panic` attributes specify its expected panic message" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `any` and `all` combinators in `cfg` with only one condition. - /// - /// ### Why is this bad? - /// If there is only one condition, no need to wrap it into `any` or `all` combinators. - /// - /// ### Example - /// ```no_run - /// #[cfg(any(unix))] - /// pub struct Bar; - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[cfg(unix)] - /// pub struct Bar; - /// ``` - #[clippy::version = "1.71.0"] - pub NON_MINIMAL_CFG, - style, - "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[cfg(features = "...")]` and suggests to replace it with - /// `#[cfg(feature = "...")]`. - /// - /// It also checks if `cfg(test)` was misspelled. - /// - /// ### Why is this bad? - /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It - /// may cause conditional compilation not work quietly. - /// - /// ### Example - /// ```no_run - /// #[cfg(features = "some-feature")] - /// fn conditional() { } - /// #[cfg(tests)] - /// mod tests { } - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[cfg(feature = "some-feature")] - /// fn conditional() { } - /// #[cfg(test)] - /// mod tests { } - /// ``` - #[clippy::version = "1.69.0"] - pub MAYBE_MISUSED_CFG, - suspicious, - "prevent from misusing the wrong attr name" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for - /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with - /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`. - /// - /// ### Why is this bad? - /// This feature has been deprecated for years and shouldn't be used anymore. - /// - /// ### Example - /// ```no_run - /// #[cfg(feature = "cargo-clippy")] - /// struct Bar; - /// ``` - /// - /// Use instead: - /// ```no_run - /// #[cfg(clippy)] - /// struct Bar; - /// ``` - #[clippy::version = "1.78.0"] - pub DEPRECATED_CLIPPY_CFG_ATTR, - suspicious, - "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`" -} - -declare_clippy_lint! { - /// ### What it does - /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` - /// and suggests to replace it with `#[allow(clippy::lint)]`. - /// - /// ### Why is this bad? - /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not - /// run by anything else than clippy. - /// - /// ### Example - /// ```no_run - /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))] - /// ``` - /// - /// Use instead: - /// ```no_run - /// #![allow(clippy::deprecated_cfg_attr)] - /// ``` - #[clippy::version = "1.78.0"] - pub UNNECESSARY_CLIPPY_CFG, - suspicious, - "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" -} - -declare_lint_pass!(Attributes => [ - ALLOW_ATTRIBUTES_WITHOUT_REASON, - INLINE_ALWAYS, - DEPRECATED_SEMVER, - USELESS_ATTRIBUTE, - BLANKET_CLIPPY_RESTRICTION_LINTS, - SHOULD_PANIC_WITHOUT_EXPECT, -]); - -impl<'tcx> LateLintPass<'tcx> for Attributes { - fn check_crate(&mut self, cx: &LateContext<'tcx>) { - for (name, level) in &cx.sess().opts.lint_opts { - if name == "clippy::restriction" && *level > Level::Allow { - span_lint_and_then( - cx, - BLANKET_CLIPPY_RESTRICTION_LINTS, - DUMMY_SP, - "`clippy::restriction` is not meant to be enabled as a group", - |diag| { - diag.note(format!( - "because of the command line `--{} clippy::restriction`", - level.as_str() - )); - diag.help("enable the restriction lints you need individually"); - }, - ); - } - } - } - - fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) { - if let Some(items) = &attr.meta_item_list() { - if let Some(ident) = attr.ident() { - if is_lint_level(ident.name) { - check_clippy_lint_names(cx, ident.name, items); - } - if matches!(ident.name, sym::allow | sym::expect) { - check_lint_reason(cx, ident.name, items, attr); - } - if items.is_empty() || !attr.has_name(sym::deprecated) { - return; - } - for item in items { - if let NestedMetaItem::MetaItem(mi) = &item - && let MetaItemKind::NameValue(lit) = &mi.kind - && mi.has_name(sym::since) - { - check_deprecated_since(cx, item.span(), lit); - } - } - } - } - if attr.has_name(sym::should_panic) { - check_should_panic_reason(cx, attr); - } - } - - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let attrs = cx.tcx.hir().attrs(item.hir_id()); - if is_relevant_item(cx, item) { - check_attrs(cx, item.span, item.ident.name, attrs); - } - match item.kind { - ItemKind::ExternCrate(..) | ItemKind::Use(..) => { - let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); - - for attr in attrs { - if in_external_macro(cx.sess(), attr.span) { - return; - } - if let Some(lint_list) = &attr.meta_item_list() { - if attr.ident().map_or(false, |ident| is_lint_level(ident.name)) { - for lint in lint_list { - match item.kind { - ItemKind::Use(..) => { - if is_word(lint, sym::unused_imports) - || is_word(lint, sym::deprecated) - || is_word(lint, sym!(unreachable_pub)) - || is_word(lint, sym!(unused)) - || is_word(lint, sym!(unused_import_braces)) - || extract_clippy_lint(lint).map_or(false, |s| { - matches!( - s.as_str(), - "wildcard_imports" - | "enum_glob_use" - | "redundant_pub_crate" - | "macro_use_imports" - | "unsafe_removed_from_name" - | "module_name_repetitions" - | "single_component_path_imports" - ) - }) - { - return; - } - }, - ItemKind::ExternCrate(..) => { - if is_word(lint, sym::unused_imports) && skip_unused_imports { - return; - } - if is_word(lint, sym!(unused_extern_crates)) { - return; - } - }, - _ => {}, - } - } - let line_span = first_line_of_span(cx, attr.span); - - if let Some(mut sugg) = snippet_opt(cx, line_span) { - if sugg.contains("#[") { - span_lint_and_then( - cx, - USELESS_ATTRIBUTE, - line_span, - "useless lint attribute", - |diag| { - sugg = sugg.replacen("#[", "#![", 1); - diag.span_suggestion( - line_span, - "if you just forgot a `!`, use", - sugg, - Applicability::MaybeIncorrect, - ); - }, - ); - } - } - } - } - } - }, - _ => {}, - } - } - - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { - if is_relevant_impl(cx, item) { - check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); - } - } - - fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if is_relevant_trait(cx, item) { - check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); - } - } -} - -/// Returns the lint name if it is clippy lint. -fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> { - if let Some(meta_item) = lint.meta_item() - && meta_item.path.segments.len() > 1 - && let tool_name = meta_item.path.segments[0].ident - && tool_name.name == sym::clippy - { - let lint_name = meta_item.path.segments.last().unwrap().ident.name; - return Some(lint_name); - } - None -} - -fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) { - if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args { - // `#[should_panic = ".."]` found, good - return; - } - - if let AttrArgs::Delimited(args) = &normal_attr.item.args - && let mut tt_iter = args.tokens.trees() - && let Some(TokenTree::Token( - Token { - kind: TokenKind::Ident(sym::expected, _), - .. - }, - _, - )) = tt_iter.next() - && let Some(TokenTree::Token( - Token { - kind: TokenKind::Eq, .. - }, - _, - )) = tt_iter.next() - && let Some(TokenTree::Token( - Token { - kind: TokenKind::Literal(_), - .. - }, - _, - )) = tt_iter.next() - { - // `#[should_panic(expected = "..")]` found, good - return; - } - - span_lint_and_sugg( - cx, - SHOULD_PANIC_WITHOUT_EXPECT, - attr.span, - "#[should_panic] attribute without a reason", - "consider specifying the expected panic", - "#[should_panic(expected = /* panic message */)]".into(), - Applicability::HasPlaceholders, - ); - } -} - -fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) { - for lint in items { - if let Some(lint_name) = extract_clippy_lint(lint) { - if lint_name.as_str() == "restriction" && name != sym::allow { - span_lint_and_help( - cx, - BLANKET_CLIPPY_RESTRICTION_LINTS, - lint.span(), - "`clippy::restriction` is not meant to be enabled as a group", - None, - "enable the restriction lints you need individually", - ); - } - } - } -} - -fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { - // Check for the feature - if !cx.tcx.features().lint_reasons { - return; - } - - // Check if the reason is present - if let Some(item) = items.last().and_then(NestedMetaItem::meta_item) - && let MetaItemKind::NameValue(_) = &item.kind - && item.path == sym::reason - { - return; - } - - // Check if the attribute is in an external macro and therefore out of the developer's control - if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) { - return; - } - - span_lint_and_help( - cx, - ALLOW_ATTRIBUTES_WITHOUT_REASON, - attr.span, - &format!("`{}` attribute without specifying a reason", name.as_str()), - None, - "try adding a reason at the end with `, reason = \"..\"`", - ); -} - -fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { - if let ItemKind::Fn(_, _, eid) = item.kind { - is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) - } else { - true - } -} - -fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool { - match item.kind { - ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value), - _ => false, - } -} - -fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { - match item.kind { - TraitItemKind::Fn(_, TraitFn::Required(_)) => true, - TraitItemKind::Fn(_, TraitFn::Provided(eid)) => { - is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) - }, - _ => false, - } -} - -fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, block: &Block<'_>) -> bool { - block.stmts.first().map_or( - block - .expr - .as_ref() - .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), - |stmt| match &stmt.kind { - StmtKind::Local(_) => true, - StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), - StmtKind::Item(_) => false, - }, - ) -} - -fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool { - if macro_backtrace(expr.span).last().map_or(false, |macro_call| { - is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable - }) { - return false; - } - match &expr.kind { - ExprKind::Block(block, _) => is_relevant_block(cx, typeck_results, block), - ExprKind::Ret(Some(e)) => is_relevant_expr(cx, typeck_results, e), - ExprKind::Ret(None) | ExprKind::Break(_, None) => false, - _ => true, - } -} - -fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) { - if span.from_expansion() { - return; - } - - for attr in attrs { - if let Some(values) = attr.meta_item_list() { - if values.len() != 1 || !attr.has_name(sym::inline) { - continue; - } - if is_word(&values[0], sym::always) { - span_lint( - cx, - INLINE_ALWAYS, - attr.span, - &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"), - ); - } - } - } -} - -fn check_deprecated_since(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) { - if let LitKind::Str(is, _) = lit.kind { - if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() { - return; - } - } - span_lint( - cx, - DEPRECATED_SEMVER, - span, - "the since field must contain a semver-compliant version", - ); -} - -fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool { - if let NestedMetaItem::MetaItem(mi) = &nmi { - mi.is_word() && mi.has_name(expected) - } else { - false - } -} - -pub struct EarlyAttributes { - pub msrv: Msrv, -} - -impl_lint_pass!(EarlyAttributes => [ - DEPRECATED_CFG_ATTR, - MISMATCHED_TARGET_OS, - EMPTY_LINE_AFTER_OUTER_ATTR, - EMPTY_LINE_AFTER_DOC_COMMENTS, - NON_MINIMAL_CFG, - MAYBE_MISUSED_CFG, - DEPRECATED_CLIPPY_CFG_ATTR, - UNNECESSARY_CLIPPY_CFG, -]); - -impl EarlyLintPass for EarlyAttributes { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { - check_empty_line_after_outer_attr(cx, item); - } - - fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { - check_deprecated_cfg_attr(cx, attr, &self.msrv); - check_deprecated_cfg(cx, attr); - check_mismatched_target_os(cx, attr); - check_minimal_cfg_condition(cx, attr); - check_misused_cfg(cx, attr); - } - - extract_msrv_attr!(EarlyContext); -} - -/// Check for empty lines after outer attributes. -/// -/// Attributes and documentation comments are both considered outer attributes -/// by the AST. However, the average user likely considers them to be different. -/// Checking for empty lines after each of these attributes is split into two different -/// lints but can share the same logic. -fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { - let mut iter = item.attrs.iter().peekable(); - while let Some(attr) = iter.next() { - if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..))) - && attr.style == AttrStyle::Outer - && is_present_in_source(cx, attr.span) - { - let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent()); - let end_of_attr_to_next_attr_or_item = Span::new( - attr.span.hi(), - iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()), - item.span.ctxt(), - item.span.parent(), - ); - - if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) { - let lines = snippet.split('\n').collect::<Vec<_>>(); - let lines = without_block_comments(lines); - - if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { - let (lint_msg, lint_type) = match attr.kind { - AttrKind::DocComment(..) => ( - "found an empty line after a doc comment. \ - Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?", - EMPTY_LINE_AFTER_DOC_COMMENTS, - ), - AttrKind::Normal(..) => ( - "found an empty line after an outer attribute. \ - Perhaps you forgot to add a `!` to make it an inner attribute?", - EMPTY_LINE_AFTER_OUTER_ATTR, - ), - }; - - span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg); - } - } - } - } -} - -fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) { - if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") { - span_lint_and_sugg( - cx, - DEPRECATED_CLIPPY_CFG_ATTR, - item.span, - "`feature = \"cargo-clippy\"` was replaced by `clippy`", - "replace with", - "clippy".to_string(), - Applicability::MachineApplicable, - ); - } -} - -fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) { - if let Some(ident) = attr.ident() { - if ["any", "all", "not"].contains(&ident.name.as_str()) { - let Some(list) = attr.meta_item_list() else { return }; - for item in list.iter().filter_map(|item| item.meta_item()) { - check_deprecated_cfg_recursively(cx, item); - } - } else { - check_cargo_clippy_attr(cx, attr); - } - } -} - -fn check_deprecated_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { - if attr.has_name(sym::cfg) - && let Some(list) = attr.meta_item_list() - { - for item in list.iter().filter_map(|item| item.meta_item()) { - check_deprecated_cfg_recursively(cx, item); - } - } -} - -fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { - // check cfg_attr - if attr.has_name(sym::cfg_attr) - && let Some(items) = attr.meta_item_list() - && items.len() == 2 - && let Some(feature_item) = items[0].meta_item() - { - // check for `rustfmt` - if feature_item.has_name(sym::rustfmt) - && msrv.meets(msrvs::TOOL_ATTRIBUTES) - // check for `rustfmt_skip` and `rustfmt::skip` - && let Some(skip_item) = &items[1].meta_item() - && (skip_item.has_name(sym!(rustfmt_skip)) - || skip_item - .path - .segments - .last() - .expect("empty path in attribute") - .ident - .name - == sym::skip) - // Only lint outer attributes, because custom inner attributes are unstable - // Tracking issue: https://github.com/rust-lang/rust/issues/54726 - && attr.style == AttrStyle::Outer - { - span_lint_and_sugg( - cx, - DEPRECATED_CFG_ATTR, - attr.span, - "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", - "use", - "#[rustfmt::skip]".to_string(), - Applicability::MachineApplicable, - ); - } else { - check_deprecated_cfg_recursively(cx, feature_item); - if let Some(behind_cfg_attr) = items[1].meta_item() { - check_clippy_cfg_attr(cx, feature_item, behind_cfg_attr, attr); - } - } - } -} - -fn check_clippy_cfg_attr( - cx: &EarlyContext<'_>, - cfg_attr: &rustc_ast::MetaItem, - behind_cfg_attr: &rustc_ast::MetaItem, - attr: &Attribute, -) { - if cfg_attr.has_name(sym::clippy) - && let Some(ident) = behind_cfg_attr.ident() - && Level::from_symbol(ident.name, Some(attr.id)).is_some() - && let Some(items) = behind_cfg_attr.meta_item_list() - { - let nb_items = items.len(); - let mut clippy_lints = Vec::with_capacity(items.len()); - for item in items { - if let Some(meta_item) = item.meta_item() - && let [part1, _] = meta_item.path.segments.as_slice() - && part1.ident.name == sym::clippy - { - clippy_lints.push(item.span()); - } - } - if clippy_lints.is_empty() { - return; - } - if nb_items == clippy_lints.len() { - if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) { - span_lint_and_sugg( - cx, - UNNECESSARY_CLIPPY_CFG, - attr.span, - "no need to put clippy lints behind a `clippy` cfg", - "replace with", - format!( - "#{}[{}]", - if attr.style == AttrStyle::Inner { "!" } else { "" }, - snippet - ), - Applicability::MachineApplicable, - ); - } - } else { - let snippet = clippy_lints - .iter() - .filter_map(|sp| snippet_opt(cx, *sp)) - .collect::<Vec<_>>() - .join(","); - span_lint_and_note( - cx, - UNNECESSARY_CLIPPY_CFG, - clippy_lints, - "no need to put clippy lints behind a `clippy` cfg", - None, - &format!( - "write instead: `#{}[{}({})]`", - if attr.style == AttrStyle::Inner { "!" } else { "" }, - ident.name, - snippet - ), - ); - } - } -} - -fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { - for item in items { - if let NestedMetaItem::MetaItem(meta) = item { - if !meta.has_name(sym::any) && !meta.has_name(sym::all) { - continue; - } - if let MetaItemKind::List(list) = &meta.kind { - check_nested_cfg(cx, list); - if list.len() == 1 { - span_lint_and_then( - cx, - NON_MINIMAL_CFG, - meta.span, - "unneeded sub `cfg` when there is only one condition", - |diag| { - if let Some(snippet) = snippet_opt(cx, list[0].span()) { - diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect); - } - }, - ); - } else if list.is_empty() && meta.has_name(sym::all) { - span_lint_and_then( - cx, - NON_MINIMAL_CFG, - meta.span, - "unneeded sub `cfg` when there is no condition", - |_| {}, - ); - } - } - } - } -} - -fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { - for item in items { - if let NestedMetaItem::MetaItem(meta) = item { - if let Some(ident) = meta.ident() - && ident.name.as_str() == "features" - && let Some(val) = meta.value_str() - { - span_lint_and_sugg( - cx, - MAYBE_MISUSED_CFG, - meta.span, - "'feature' may be misspelled as 'features'", - "did you mean", - format!("feature = \"{val}\""), - Applicability::MaybeIncorrect, - ); - } - if let MetaItemKind::List(list) = &meta.kind { - check_nested_misused_cfg(cx, list); - // If this is not a list, then we check for `cfg(test)`. - } else if let Some(ident) = meta.ident() - && matches!(ident.name.as_str(), "tests" | "Test") - { - span_lint_and_sugg( - cx, - MAYBE_MISUSED_CFG, - meta.span, - &format!("'test' may be misspelled as '{}'", ident.name.as_str()), - "did you mean", - "test".to_string(), - Applicability::MaybeIncorrect, - ); - } - } - } -} - -fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) { - if attr.has_name(sym::cfg) - && let Some(items) = attr.meta_item_list() - { - check_nested_cfg(cx, &items); - } -} - -fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { - if attr.has_name(sym::cfg) - && let Some(items) = attr.meta_item_list() - { - check_nested_misused_cfg(cx, &items); - } -} - -fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { - fn find_os(name: &str) -> Option<&'static str> { - UNIX_SYSTEMS - .iter() - .chain(NON_UNIX_SYSTEMS.iter()) - .find(|&&os| os == name) - .copied() - } - - fn is_unix(name: &str) -> bool { - UNIX_SYSTEMS.iter().any(|&os| os == name) - } - - fn find_mismatched_target_os(items: &[NestedMetaItem]) -> Vec<(&str, Span)> { - let mut mismatched = Vec::new(); - - for item in items { - if let NestedMetaItem::MetaItem(meta) = item { - match &meta.kind { - MetaItemKind::List(list) => { - mismatched.extend(find_mismatched_target_os(list)); - }, - MetaItemKind::Word => { - if let Some(ident) = meta.ident() - && let Some(os) = find_os(ident.name.as_str()) - { - mismatched.push((os, ident.span)); - } - }, - MetaItemKind::NameValue(..) => {}, - } - } - } - - mismatched - } - - if attr.has_name(sym::cfg) - && let Some(list) = attr.meta_item_list() - && let mismatched = find_mismatched_target_os(&list) - && !mismatched.is_empty() - { - let mess = "operating system used in target family position"; - - span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| { - // Avoid showing the unix suggestion multiple times in case - // we have more than one mismatch for unix-like systems - let mut unix_suggested = false; - - for (os, span) in mismatched { - let sugg = format!("target_os = \"{os}\""); - diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect); - - if !unix_suggested && is_unix(os) { - diag.help("did you mean `unix`?"); - unix_suggested = true; - } - } - }); - } -} - -fn is_lint_level(symbol: Symbol) -> bool { - matches!(symbol, sym::allow | sym::expect | sym::warn | sym::deny | sym::forbid) -} diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs new file mode 100644 index 00000000000..df00f23e37e --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -0,0 +1,37 @@ +use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_from_proc_macro; +use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::sym; +use rustc_span::symbol::Symbol; + +pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { + // Check for the feature + if !cx.tcx.features().lint_reasons { + return; + } + + // Check if the reason is present + if let Some(item) = items.last().and_then(NestedMetaItem::meta_item) + && let MetaItemKind::NameValue(_) = &item.kind + && item.path == sym::reason + { + return; + } + + // Check if the attribute is in an external macro and therefore out of the developer's control + if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) { + return; + } + + span_lint_and_help( + cx, + ALLOW_ATTRIBUTES_WITHOUT_REASON, + attr.span, + &format!("`{}` attribute without specifying a reason", name.as_str()), + None, + "try adding a reason at the end with `, reason = \"..\"`", + ); +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs new file mode 100644 index 00000000000..9b08fd6d654 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs @@ -0,0 +1,44 @@ +use super::utils::extract_clippy_lint; +use super::BLANKET_CLIPPY_RESTRICTION_LINTS; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; +use rustc_ast::NestedMetaItem; +use rustc_lint::{LateContext, Level, LintContext}; +use rustc_span::symbol::Symbol; +use rustc_span::{sym, DUMMY_SP}; + +pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) { + for lint in items { + if let Some(lint_name) = extract_clippy_lint(lint) { + if lint_name.as_str() == "restriction" && name != sym::allow { + span_lint_and_help( + cx, + BLANKET_CLIPPY_RESTRICTION_LINTS, + lint.span(), + "`clippy::restriction` is not meant to be enabled as a group", + None, + "enable the restriction lints you need individually", + ); + } + } + } +} + +pub(super) fn check_command_line(cx: &LateContext<'_>) { + for (name, level) in &cx.sess().opts.lint_opts { + if name == "clippy::restriction" && *level > Level::Allow { + span_lint_and_then( + cx, + BLANKET_CLIPPY_RESTRICTION_LINTS, + DUMMY_SP, + "`clippy::restriction` is not meant to be enabled as a group", + |diag| { + diag.note(format!( + "because of the command line `--{} clippy::restriction`", + level.as_str() + )); + diag.help("enable the restriction lints you need individually"); + }, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs new file mode 100644 index 00000000000..e872ab6b4b5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -0,0 +1,87 @@ +use super::{unnecessary_clippy_cfg, Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR}; +use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::AttrStyle; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; +use rustc_span::sym; + +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { + // check cfg_attr + if attr.has_name(sym::cfg_attr) + && let Some(items) = attr.meta_item_list() + && items.len() == 2 + && let Some(feature_item) = items[0].meta_item() + { + // check for `rustfmt` + if feature_item.has_name(sym::rustfmt) + && msrv.meets(msrvs::TOOL_ATTRIBUTES) + // check for `rustfmt_skip` and `rustfmt::skip` + && let Some(skip_item) = &items[1].meta_item() + && (skip_item.has_name(sym!(rustfmt_skip)) + || skip_item + .path + .segments + .last() + .expect("empty path in attribute") + .ident + .name + == sym::skip) + // Only lint outer attributes, because custom inner attributes are unstable + // Tracking issue: https://github.com/rust-lang/rust/issues/54726 + && attr.style == AttrStyle::Outer + { + span_lint_and_sugg( + cx, + DEPRECATED_CFG_ATTR, + attr.span, + "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", + "use", + "#[rustfmt::skip]".to_string(), + Applicability::MachineApplicable, + ); + } else { + check_deprecated_cfg_recursively(cx, feature_item); + if let Some(behind_cfg_attr) = items[1].meta_item() { + unnecessary_clippy_cfg::check(cx, feature_item, behind_cfg_attr, attr); + } + } + } +} + +pub(super) fn check_clippy(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) + && let Some(list) = attr.meta_item_list() + { + for item in list.iter().filter_map(|item| item.meta_item()) { + check_deprecated_cfg_recursively(cx, item); + } + } +} + +fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) { + if let Some(ident) = attr.ident() { + if ["any", "all", "not"].contains(&ident.name.as_str()) { + let Some(list) = attr.meta_item_list() else { return }; + for item in list.iter().filter_map(|item| item.meta_item()) { + check_deprecated_cfg_recursively(cx, item); + } + } else { + check_cargo_clippy_attr(cx, attr); + } + } +} + +fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) { + if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") { + span_lint_and_sugg( + cx, + DEPRECATED_CLIPPY_CFG_ATTR, + item.span, + "`feature = \"cargo-clippy\"` was replaced by `clippy`", + "replace with", + "clippy".to_string(), + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs new file mode 100644 index 00000000000..1898c145c76 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs @@ -0,0 +1,20 @@ +use super::DEPRECATED_SEMVER; +use clippy_utils::diagnostics::span_lint; +use rustc_ast::{LitKind, MetaItemLit}; +use rustc_lint::LateContext; +use rustc_span::Span; +use semver::Version; + +pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) { + if let LitKind::Str(is, _) = lit.kind { + if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() { + return; + } + } + span_lint( + cx, + DEPRECATED_SEMVER, + span, + "the since field must contain a semver-compliant version", + ); +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs new file mode 100644 index 00000000000..ca43e76ac57 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs @@ -0,0 +1,52 @@ +use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR}; +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments}; +use rustc_ast::{AttrKind, AttrStyle}; +use rustc_lint::EarlyContext; +use rustc_span::Span; + +/// Check for empty lines after outer attributes. +/// +/// Attributes and documentation comments are both considered outer attributes +/// by the AST. However, the average user likely considers them to be different. +/// Checking for empty lines after each of these attributes is split into two different +/// lints but can share the same logic. +pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { + let mut iter = item.attrs.iter().peekable(); + while let Some(attr) = iter.next() { + if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..))) + && attr.style == AttrStyle::Outer + && is_present_in_source(cx, attr.span) + { + let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent()); + let end_of_attr_to_next_attr_or_item = Span::new( + attr.span.hi(), + iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()), + item.span.ctxt(), + item.span.parent(), + ); + + if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) { + let lines = snippet.split('\n').collect::<Vec<_>>(); + let lines = without_block_comments(lines); + + if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { + let (lint_msg, lint_type) = match attr.kind { + AttrKind::DocComment(..) => ( + "found an empty line after a doc comment. \ + Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?", + EMPTY_LINE_AFTER_DOC_COMMENTS, + ), + AttrKind::Normal(..) => ( + "found an empty line after an outer attribute. \ + Perhaps you forgot to add a `!` to make it an inner attribute?", + EMPTY_LINE_AFTER_OUTER_ATTR, + ), + }; + + span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg); + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs new file mode 100644 index 00000000000..cfcd2cc6a00 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs @@ -0,0 +1,29 @@ +use super::utils::is_word; +use super::INLINE_ALWAYS; +use clippy_utils::diagnostics::span_lint; +use rustc_ast::Attribute; +use rustc_lint::LateContext; +use rustc_span::symbol::Symbol; +use rustc_span::{sym, Span}; + +pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) { + if span.from_expansion() { + return; + } + + for attr in attrs { + if let Some(values) = attr.meta_item_list() { + if values.len() != 1 || !attr.has_name(sym::inline) { + continue; + } + if is_word(&values[0], sym::always) { + span_lint( + cx, + INLINE_ALWAYS, + attr.span, + &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"), + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs new file mode 100644 index 00000000000..5a70866eda5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs @@ -0,0 +1,51 @@ +use super::{Attribute, MAYBE_MISUSED_CFG}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; +use rustc_span::sym; + +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) + && let Some(items) = attr.meta_item_list() + { + check_nested_misused_cfg(cx, &items); + } +} + +fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { + for item in items { + if let NestedMetaItem::MetaItem(meta) = item { + if let Some(ident) = meta.ident() + && ident.name.as_str() == "features" + && let Some(val) = meta.value_str() + { + span_lint_and_sugg( + cx, + MAYBE_MISUSED_CFG, + meta.span, + "'feature' may be misspelled as 'features'", + "did you mean", + format!("feature = \"{val}\""), + Applicability::MaybeIncorrect, + ); + } + if let MetaItemKind::List(list) = &meta.kind { + check_nested_misused_cfg(cx, list); + // If this is not a list, then we check for `cfg(test)`. + } else if let Some(ident) = meta.ident() + && matches!(ident.name.as_str(), "tests" | "Test") + { + span_lint_and_sugg( + cx, + MAYBE_MISUSED_CFG, + meta.span, + &format!("'test' may be misspelled as '{}'", ident.name.as_str()), + "did you mean", + "test".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs b/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs new file mode 100644 index 00000000000..b1cc0a763c5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs @@ -0,0 +1,90 @@ +use super::{Attribute, MISMATCHED_TARGET_OS}; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; +use rustc_span::{sym, Span}; + +static UNIX_SYSTEMS: &[&str] = &[ + "android", + "dragonfly", + "emscripten", + "freebsd", + "fuchsia", + "haiku", + "illumos", + "ios", + "l4re", + "linux", + "macos", + "netbsd", + "openbsd", + "redox", + "solaris", + "vxworks", +]; + +// NOTE: windows is excluded from the list because it's also a valid target family. +static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"]; + +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { + fn find_os(name: &str) -> Option<&'static str> { + UNIX_SYSTEMS + .iter() + .chain(NON_UNIX_SYSTEMS.iter()) + .find(|&&os| os == name) + .copied() + } + + fn is_unix(name: &str) -> bool { + UNIX_SYSTEMS.iter().any(|&os| os == name) + } + + fn find_mismatched_target_os(items: &[NestedMetaItem]) -> Vec<(&str, Span)> { + let mut mismatched = Vec::new(); + + for item in items { + if let NestedMetaItem::MetaItem(meta) = item { + match &meta.kind { + MetaItemKind::List(list) => { + mismatched.extend(find_mismatched_target_os(list)); + }, + MetaItemKind::Word => { + if let Some(ident) = meta.ident() + && let Some(os) = find_os(ident.name.as_str()) + { + mismatched.push((os, ident.span)); + } + }, + MetaItemKind::NameValue(..) => {}, + } + } + } + + mismatched + } + + if attr.has_name(sym::cfg) + && let Some(list) = attr.meta_item_list() + && let mismatched = find_mismatched_target_os(&list) + && !mismatched.is_empty() + { + let mess = "operating system used in target family position"; + + span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| { + // Avoid showing the unix suggestion multiple times in case + // we have more than one mismatch for unix-like systems + let mut unix_suggested = false; + + for (os, span) in mismatched { + let sugg = format!("target_os = \"{os}\""); + diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect); + + if !unix_suggested && is_unix(os) { + diag.help("did you mean `unix`?"); + unix_suggested = true; + } + } + }); + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs new file mode 100644 index 00000000000..c2e21cfd330 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs @@ -0,0 +1,30 @@ +use super::MIXED_ATTRIBUTES_STYLE; +use clippy_utils::diagnostics::span_lint; +use rustc_ast::AttrStyle; +use rustc_lint::EarlyContext; + +pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { + let mut has_outer = false; + let mut has_inner = false; + + for attr in &item.attrs { + if attr.span.from_expansion() { + continue; + } + match attr.style { + AttrStyle::Inner => has_inner = true, + AttrStyle::Outer => has_outer = true, + } + } + if !has_outer || !has_inner { + return; + } + let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion()); + let span = attrs_iter.next().unwrap().span; + span_lint( + cx, + MIXED_ATTRIBUTES_STYLE, + span.with_hi(attrs_iter.last().unwrap().span.hi()), + "item has both inner and outer attributes", + ); +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs new file mode 100644 index 00000000000..c4c65d3248a --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -0,0 +1,588 @@ +//! checks for attributes + +mod allow_attributes_without_reason; +mod blanket_clippy_restriction_lints; +mod deprecated_cfg_attr; +mod deprecated_semver; +mod empty_line_after; +mod inline_always; +mod maybe_misused_cfg; +mod mismatched_target_os; +mod mixed_attributes_style; +mod non_minimal_cfg; +mod should_panic_without_expect; +mod unnecessary_clippy_cfg; +mod useless_attribute; +mod utils; + +use clippy_config::msrvs::Msrv; +use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem}; +use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, impl_lint_pass}; +use rustc_span::sym; +use utils::{is_lint_level, is_relevant_impl, is_relevant_item, is_relevant_trait}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for items annotated with `#[inline(always)]`, + /// unless the annotated function is empty or simply panics. + /// + /// ### Why is this bad? + /// While there are valid uses of this annotation (and once + /// you know when to use it, by all means `allow` this lint), it's a common + /// newbie-mistake to pepper one's code with it. + /// + /// As a rule of thumb, before slapping `#[inline(always)]` on a function, + /// measure if that additional function call really affects your runtime profile + /// sufficiently to make up for the increase in compile time. + /// + /// ### Known problems + /// False positives, big time. This lint is meant to be + /// deactivated by everyone doing serious performance work. This means having + /// done the measurement. + /// + /// ### Example + /// ```ignore + /// #[inline(always)] + /// fn not_quite_hot_code(..) { ... } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub INLINE_ALWAYS, + pedantic, + "use of `#[inline(always)]`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `extern crate` and `use` items annotated with + /// lint attributes. + /// + /// This lint permits lint attributes for lints emitted on the items themself. + /// For `use` items these lints are: + /// * deprecated + /// * unreachable_pub + /// * unused_imports + /// * clippy::enum_glob_use + /// * clippy::macro_use_imports + /// * clippy::wildcard_imports + /// + /// For `extern crate` items these lints are: + /// * `unused_imports` on items with `#[macro_use]` + /// + /// ### Why is this bad? + /// Lint attributes have no effect on crate imports. Most + /// likely a `!` was forgotten. + /// + /// ### Example + /// ```ignore + /// #[deny(dead_code)] + /// extern crate foo; + /// #[forbid(dead_code)] + /// use foo::bar; + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// #[allow(unused_imports)] + /// use foo::baz; + /// #[allow(unused_imports)] + /// #[macro_use] + /// extern crate baz; + /// ``` + #[clippy::version = "pre 1.29.0"] + pub USELESS_ATTRIBUTE, + correctness, + "use of lint attributes on `extern crate` items" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[deprecated]` annotations with a `since` + /// field that is not a valid semantic version. Also allows "TBD" to signal + /// future deprecation. + /// + /// ### Why is this bad? + /// For checking the version of the deprecation, it must be + /// a valid semver. Failing that, the contained information is useless. + /// + /// ### Example + /// ```no_run + /// #[deprecated(since = "forever")] + /// fn something_else() { /* ... */ } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub DEPRECATED_SEMVER, + correctness, + "use of `#[deprecated(since = \"x\")]` where x is not semver" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for empty lines after outer attributes + /// + /// ### Why is this bad? + /// Most likely the attribute was meant to be an inner attribute using a '!'. + /// If it was meant to be an outer attribute, then the following item + /// should not be separated by empty lines. + /// + /// ### Known problems + /// Can cause false positives. + /// + /// From the clippy side it's difficult to detect empty lines between an attributes and the + /// following item because empty lines and comments are not part of the AST. The parsing + /// currently works for basic cases but is not perfect. + /// + /// ### Example + /// ```no_run + /// #[allow(dead_code)] + /// + /// fn not_quite_good_code() { } + /// ``` + /// + /// Use instead: + /// ```no_run + /// // Good (as inner attribute) + /// #![allow(dead_code)] + /// + /// fn this_is_fine() { } + /// + /// // or + /// + /// // Good (as outer attribute) + /// #[allow(dead_code)] + /// fn this_is_fine_too() { } + /// ``` + #[clippy::version = "pre 1.29.0"] + pub EMPTY_LINE_AFTER_OUTER_ATTR, + nursery, + "empty line after outer attribute" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for empty lines after documentation comments. + /// + /// ### Why is this bad? + /// The documentation comment was most likely meant to be an inner attribute or regular comment. + /// If it was intended to be a documentation comment, then the empty line should be removed to + /// be more idiomatic. + /// + /// ### Known problems + /// Only detects empty lines immediately following the documentation. If the doc comment is followed + /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr` + /// in combination with this lint to detect both cases. + /// + /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`). + /// + /// ### Example + /// ```no_run + /// /// Some doc comment with a blank line after it. + /// + /// fn not_quite_good_code() { } + /// ``` + /// + /// Use instead: + /// ```no_run + /// /// Good (no blank line) + /// fn this_is_fine() { } + /// ``` + /// + /// ```no_run + /// // Good (convert to a regular comment) + /// + /// fn this_is_fine_too() { } + /// ``` + /// + /// ```no_run + /// //! Good (convert to a comment on an inner attribute) + /// + /// fn this_is_fine_as_well() { } + /// ``` + #[clippy::version = "1.70.0"] + pub EMPTY_LINE_AFTER_DOC_COMMENTS, + nursery, + "empty line after documentation comments" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category. + /// + /// ### Why is this bad? + /// Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust. + /// These lints should only be enabled on a lint-by-lint basis and with careful consideration. + /// + /// ### Example + /// ```no_run + /// #![deny(clippy::restriction)] + /// ``` + /// + /// Use instead: + /// ```no_run + /// #![deny(clippy::as_conversions)] + /// ``` + #[clippy::version = "1.47.0"] + pub BLANKET_CLIPPY_RESTRICTION_LINTS, + suspicious, + "enabling the complete restriction group" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it + /// with `#[rustfmt::skip]`. + /// + /// ### Why is this bad? + /// Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690)) + /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes. + /// + /// ### Known problems + /// This lint doesn't detect crate level inner attributes, because they get + /// processed before the PreExpansionPass lints get executed. See + /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765) + /// + /// ### Example + /// ```no_run + /// #[cfg_attr(rustfmt, rustfmt_skip)] + /// fn main() { } + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[rustfmt::skip] + /// fn main() { } + /// ``` + #[clippy::version = "1.32.0"] + pub DEPRECATED_CFG_ATTR, + complexity, + "usage of `cfg_attr(rustfmt)` instead of tool attributes" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for cfg attributes having operating systems used in target family position. + /// + /// ### Why is this bad? + /// The configuration option will not be recognised and the related item will not be included + /// by the conditional compilation engine. + /// + /// ### Example + /// ```no_run + /// #[cfg(linux)] + /// fn conditional() { } + /// ``` + /// + /// Use instead: + /// ```no_run + /// # mod hidden { + /// #[cfg(target_os = "linux")] + /// fn conditional() { } + /// # } + /// + /// // or + /// + /// #[cfg(unix)] + /// fn conditional() { } + /// ``` + /// Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details. + #[clippy::version = "1.45.0"] + pub MISMATCHED_TARGET_OS, + correctness, + "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for attributes that allow lints without a reason. + /// + /// (This requires the `lint_reasons` feature) + /// + /// ### Why is this bad? + /// Allowing a lint should always have a reason. This reason should be documented to + /// ensure that others understand the reasoning + /// + /// ### Example + /// ```no_run + /// #![feature(lint_reasons)] + /// + /// #![allow(clippy::some_lint)] + /// ``` + /// + /// Use instead: + /// ```no_run + /// #![feature(lint_reasons)] + /// + /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] + /// ``` + #[clippy::version = "1.61.0"] + pub ALLOW_ATTRIBUTES_WITHOUT_REASON, + restriction, + "ensures that all `allow` and `expect` attributes have a reason" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[should_panic]` attributes without specifying the expected panic message. + /// + /// ### Why is this bad? + /// The expected panic message should be specified to ensure that the test is actually + /// panicking with the expected message, and not another unrelated panic. + /// + /// ### Example + /// ```no_run + /// fn random() -> i32 { 0 } + /// + /// #[should_panic] + /// #[test] + /// fn my_test() { + /// let _ = 1 / random(); + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// fn random() -> i32 { 0 } + /// + /// #[should_panic = "attempt to divide by zero"] + /// #[test] + /// fn my_test() { + /// let _ = 1 / random(); + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub SHOULD_PANIC_WITHOUT_EXPECT, + pedantic, + "ensures that all `should_panic` attributes specify its expected panic message" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `any` and `all` combinators in `cfg` with only one condition. + /// + /// ### Why is this bad? + /// If there is only one condition, no need to wrap it into `any` or `all` combinators. + /// + /// ### Example + /// ```no_run + /// #[cfg(any(unix))] + /// pub struct Bar; + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[cfg(unix)] + /// pub struct Bar; + /// ``` + #[clippy::version = "1.71.0"] + pub NON_MINIMAL_CFG, + style, + "ensure that all `cfg(any())` and `cfg(all())` have more than one condition" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg(features = "...")]` and suggests to replace it with + /// `#[cfg(feature = "...")]`. + /// + /// It also checks if `cfg(test)` was misspelled. + /// + /// ### Why is this bad? + /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It + /// may cause conditional compilation not work quietly. + /// + /// ### Example + /// ```no_run + /// #[cfg(features = "some-feature")] + /// fn conditional() { } + /// #[cfg(tests)] + /// mod tests { } + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[cfg(feature = "some-feature")] + /// fn conditional() { } + /// #[cfg(test)] + /// mod tests { } + /// ``` + #[clippy::version = "1.69.0"] + pub MAYBE_MISUSED_CFG, + suspicious, + "prevent from misusing the wrong attr name" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for + /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with + /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`. + /// + /// ### Why is this bad? + /// This feature has been deprecated for years and shouldn't be used anymore. + /// + /// ### Example + /// ```no_run + /// #[cfg(feature = "cargo-clippy")] + /// struct Bar; + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[cfg(clippy)] + /// struct Bar; + /// ``` + #[clippy::version = "1.78.0"] + pub DEPRECATED_CLIPPY_CFG_ATTR, + suspicious, + "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` + /// and suggests to replace it with `#[allow(clippy::lint)]`. + /// + /// ### Why is this bad? + /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not + /// run by anything else than clippy. + /// + /// ### Example + /// ```no_run + /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))] + /// ``` + /// + /// Use instead: + /// ```no_run + /// #![allow(clippy::deprecated_cfg_attr)] + /// ``` + #[clippy::version = "1.78.0"] + pub UNNECESSARY_CLIPPY_CFG, + suspicious, + "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks that an item has only one kind of attributes. + /// + /// ### Why is this bad? + /// Having both kinds of attributes makes it more complicated to read code. + /// + /// ### Example + /// ```no_run + /// #[cfg(linux)] + /// pub fn foo() { + /// #![cfg(windows)] + /// } + /// ``` + /// Use instead: + /// ```no_run + /// #[cfg(linux)] + /// #[cfg(windows)] + /// pub fn foo() { + /// } + /// ``` + #[clippy::version = "1.78.0"] + pub MIXED_ATTRIBUTES_STYLE, + suspicious, + "item has both inner and outer attributes" +} + +declare_lint_pass!(Attributes => [ + ALLOW_ATTRIBUTES_WITHOUT_REASON, + INLINE_ALWAYS, + DEPRECATED_SEMVER, + USELESS_ATTRIBUTE, + BLANKET_CLIPPY_RESTRICTION_LINTS, + SHOULD_PANIC_WITHOUT_EXPECT, +]); + +impl<'tcx> LateLintPass<'tcx> for Attributes { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { + blanket_clippy_restriction_lints::check_command_line(cx); + } + + fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) { + if let Some(items) = &attr.meta_item_list() { + if let Some(ident) = attr.ident() { + if is_lint_level(ident.name, attr.id) { + blanket_clippy_restriction_lints::check(cx, ident.name, items); + } + if matches!(ident.name, sym::allow | sym::expect) { + allow_attributes_without_reason::check(cx, ident.name, items, attr); + } + if items.is_empty() || !attr.has_name(sym::deprecated) { + return; + } + for item in items { + if let NestedMetaItem::MetaItem(mi) = &item + && let MetaItemKind::NameValue(lit) = &mi.kind + && mi.has_name(sym::since) + { + deprecated_semver::check(cx, item.span(), lit); + } + } + } + } + if attr.has_name(sym::should_panic) { + should_panic_without_expect::check(cx, attr); + } + } + + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let attrs = cx.tcx.hir().attrs(item.hir_id()); + if is_relevant_item(cx, item) { + inline_always::check(cx, item.span, item.ident.name, attrs); + } + match item.kind { + ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs), + _ => {}, + } + } + + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { + if is_relevant_impl(cx, item) { + inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); + } + } + + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { + if is_relevant_trait(cx, item) { + inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); + } + } +} + +pub struct EarlyAttributes { + pub msrv: Msrv, +} + +impl_lint_pass!(EarlyAttributes => [ + DEPRECATED_CFG_ATTR, + MISMATCHED_TARGET_OS, + EMPTY_LINE_AFTER_OUTER_ATTR, + EMPTY_LINE_AFTER_DOC_COMMENTS, + NON_MINIMAL_CFG, + MAYBE_MISUSED_CFG, + DEPRECATED_CLIPPY_CFG_ATTR, + UNNECESSARY_CLIPPY_CFG, + MIXED_ATTRIBUTES_STYLE, +]); + +impl EarlyLintPass for EarlyAttributes { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { + empty_line_after::check(cx, item); + mixed_attributes_style::check(cx, item); + } + + fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { + deprecated_cfg_attr::check(cx, attr, &self.msrv); + deprecated_cfg_attr::check_clippy(cx, attr); + mismatched_target_os::check(cx, attr); + non_minimal_cfg::check(cx, attr); + maybe_misused_cfg::check(cx, attr); + } + + extract_msrv_attr!(EarlyContext); +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs new file mode 100644 index 00000000000..3fde7061585 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs @@ -0,0 +1,49 @@ +use super::{Attribute, NON_MINIMAL_CFG}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; +use rustc_span::sym; + +pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) + && let Some(items) = attr.meta_item_list() + { + check_nested_cfg(cx, &items); + } +} + +fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { + for item in items { + if let NestedMetaItem::MetaItem(meta) = item { + if !meta.has_name(sym::any) && !meta.has_name(sym::all) { + continue; + } + if let MetaItemKind::List(list) = &meta.kind { + check_nested_cfg(cx, list); + if list.len() == 1 { + span_lint_and_then( + cx, + NON_MINIMAL_CFG, + meta.span, + "unneeded sub `cfg` when there is only one condition", + |diag| { + if let Some(snippet) = snippet_opt(cx, list[0].span()) { + diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect); + } + }, + ); + } else if list.is_empty() && meta.has_name(sym::all) { + span_lint_and_then( + cx, + NON_MINIMAL_CFG, + meta.span, + "unneeded sub `cfg` when there is no condition", + |_| {}, + ); + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs new file mode 100644 index 00000000000..2d45cbbf621 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -0,0 +1,54 @@ +use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::token::{Token, TokenKind}; +use rustc_ast::tokenstream::TokenTree; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind}; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::sym; + +pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) { + if let AttrKind::Normal(normal_attr) = &attr.kind { + if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args { + // `#[should_panic = ".."]` found, good + return; + } + + if let AttrArgs::Delimited(args) = &normal_attr.item.args + && let mut tt_iter = args.tokens.trees() + && let Some(TokenTree::Token( + Token { + kind: TokenKind::Ident(sym::expected, _), + .. + }, + _, + )) = tt_iter.next() + && let Some(TokenTree::Token( + Token { + kind: TokenKind::Eq, .. + }, + _, + )) = tt_iter.next() + && let Some(TokenTree::Token( + Token { + kind: TokenKind::Literal(_), + .. + }, + _, + )) = tt_iter.next() + { + // `#[should_panic(expected = "..")]` found, good + return; + } + + span_lint_and_sugg( + cx, + SHOULD_PANIC_WITHOUT_EXPECT, + attr.span, + "#[should_panic] attribute without a reason", + "consider specifying the expected panic", + "#[should_panic(expected = /* panic message */)]".into(), + Applicability::HasPlaceholders, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs new file mode 100644 index 00000000000..05da69636c6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -0,0 +1,70 @@ +use super::{Attribute, UNNECESSARY_CLIPPY_CFG}; +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; +use clippy_utils::source::snippet_opt; +use rustc_ast::AttrStyle; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, Level}; +use rustc_span::sym; + +pub(super) fn check( + cx: &EarlyContext<'_>, + cfg_attr: &rustc_ast::MetaItem, + behind_cfg_attr: &rustc_ast::MetaItem, + attr: &Attribute, +) { + if cfg_attr.has_name(sym::clippy) + && let Some(ident) = behind_cfg_attr.ident() + && Level::from_symbol(ident.name, Some(attr.id)).is_some() + && let Some(items) = behind_cfg_attr.meta_item_list() + { + let nb_items = items.len(); + let mut clippy_lints = Vec::with_capacity(items.len()); + for item in items { + if let Some(meta_item) = item.meta_item() + && let [part1, _] = meta_item.path.segments.as_slice() + && part1.ident.name == sym::clippy + { + clippy_lints.push(item.span()); + } + } + if clippy_lints.is_empty() { + return; + } + if nb_items == clippy_lints.len() { + if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) { + span_lint_and_sugg( + cx, + UNNECESSARY_CLIPPY_CFG, + attr.span, + "no need to put clippy lints behind a `clippy` cfg", + "replace with", + format!( + "#{}[{}]", + if attr.style == AttrStyle::Inner { "!" } else { "" }, + snippet + ), + Applicability::MachineApplicable, + ); + } + } else { + let snippet = clippy_lints + .iter() + .filter_map(|sp| snippet_opt(cx, *sp)) + .collect::<Vec<_>>() + .join(","); + span_lint_and_note( + cx, + UNNECESSARY_CLIPPY_CFG, + clippy_lints, + "no need to put clippy lints behind a `clippy` cfg", + None, + &format!( + "write instead: `#{}[{}({})]`", + if attr.style == AttrStyle::Inner { "!" } else { "" }, + ident.name, + snippet + ), + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs new file mode 100644 index 00000000000..7575f502a7c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -0,0 +1,73 @@ +use super::utils::{extract_clippy_lint, is_lint_level, is_word}; +use super::{Attribute, USELESS_ATTRIBUTE}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::{first_line_of_span, snippet_opt}; +use rustc_errors::Applicability; +use rustc_hir::{Item, ItemKind}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_span::sym; + +pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) { + let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); + + for attr in attrs { + if in_external_macro(cx.sess(), attr.span) { + return; + } + if let Some(lint_list) = &attr.meta_item_list() { + if attr.ident().map_or(false, |ident| is_lint_level(ident.name, attr.id)) { + for lint in lint_list { + match item.kind { + ItemKind::Use(..) => { + if is_word(lint, sym::unused_imports) + || is_word(lint, sym::deprecated) + || is_word(lint, sym!(unreachable_pub)) + || is_word(lint, sym!(unused)) + || is_word(lint, sym!(unused_import_braces)) + || extract_clippy_lint(lint).map_or(false, |s| { + matches!( + s.as_str(), + "wildcard_imports" + | "enum_glob_use" + | "redundant_pub_crate" + | "macro_use_imports" + | "unsafe_removed_from_name" + | "module_name_repetitions" + | "single_component_path_imports" + ) + }) + { + return; + } + }, + ItemKind::ExternCrate(..) => { + if is_word(lint, sym::unused_imports) && skip_unused_imports { + return; + } + if is_word(lint, sym!(unused_extern_crates)) { + return; + } + }, + _ => {}, + } + } + let line_span = first_line_of_span(cx, attr.span); + + if let Some(mut sugg) = snippet_opt(cx, line_span) { + if sugg.contains("#[") { + span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| { + sugg = sugg.replacen("#[", "#![", 1); + diag.span_suggestion( + line_span, + "if you just forgot a `!`, use", + sugg, + Applicability::MaybeIncorrect, + ); + }); + } + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs new file mode 100644 index 00000000000..9b36cc00444 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -0,0 +1,87 @@ +use clippy_utils::macros::{is_panic, macro_backtrace}; +use rustc_ast::{AttrId, NestedMetaItem}; +use rustc_hir::{ + Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, +}; +use rustc_lint::{LateContext, Level}; +use rustc_middle::ty; +use rustc_span::sym; +use rustc_span::symbol::Symbol; + +pub(super) fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool { + if let NestedMetaItem::MetaItem(mi) = &nmi { + mi.is_word() && mi.has_name(expected) + } else { + false + } +} + +pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool { + Level::from_symbol(symbol, Some(attr_id)).is_some() +} + +pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { + if let ItemKind::Fn(_, _, eid) = item.kind { + is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) + } else { + true + } +} + +pub(super) fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool { + match item.kind { + ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value), + _ => false, + } +} + +pub(super) fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool { + match item.kind { + TraitItemKind::Fn(_, TraitFn::Required(_)) => true, + TraitItemKind::Fn(_, TraitFn::Provided(eid)) => { + is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value) + }, + _ => false, + } +} + +fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, block: &Block<'_>) -> bool { + block.stmts.first().map_or( + block + .expr + .as_ref() + .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), + |stmt| match &stmt.kind { + StmtKind::Local(_) => true, + StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), + StmtKind::Item(_) => false, + }, + ) +} + +fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool { + if macro_backtrace(expr.span).last().map_or(false, |macro_call| { + is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable + }) { + return false; + } + match &expr.kind { + ExprKind::Block(block, _) => is_relevant_block(cx, typeck_results, block), + ExprKind::Ret(Some(e)) => is_relevant_expr(cx, typeck_results, e), + ExprKind::Ret(None) | ExprKind::Break(_, None) => false, + _ => true, + } +} + +/// Returns the lint name if it is clippy lint. +pub(super) fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> { + if let Some(meta_item) = lint.meta_item() + && meta_item.path.segments.len() > 1 + && let tool_name = meta_item.path.segments[0].ident + && tool_name.name == sym::clippy + { + let lint_name = meta_item.path.segments.last().unwrap().ident.name; + return Some(lint_name); + } + None +} diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 0d66f2d644d..a474356608f 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -88,7 +88,6 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { match expr.kind { - ExprKind::Unary(UnOp::Not, sub) => check_inverted_condition(cx, expr.span, sub), // This check the case where an element in a boolean comparison is inverted, like: // // ``` @@ -119,27 +118,6 @@ fn bin_op_eq_str(op: BinOpKind) -> Option<&'static str> { } } -fn check_inverted_condition(cx: &LateContext<'_>, expr_span: Span, sub_expr: &Expr<'_>) { - if !expr_span.from_expansion() - && let ExprKind::Binary(op, left, right) = sub_expr.kind - && let Some(left) = snippet_opt(cx, left.span) - && let Some(right) = snippet_opt(cx, right.span) - { - let Some(op) = inverted_bin_op_eq_str(op.node) else { - return; - }; - span_lint_and_sugg( - cx, - NONMINIMAL_BOOL, - expr_span, - "this boolean expression can be simplified", - "try", - format!("{left} {op} {right}",), - Applicability::MachineApplicable, - ); - } -} - fn check_inverted_bool_in_condition( cx: &LateContext<'_>, expr_span: Span, @@ -148,8 +126,8 @@ fn check_inverted_bool_in_condition( right: &Expr<'_>, ) { if expr_span.from_expansion() - && (!cx.typeck_results().node_types()[left.hir_id].is_bool() - || !cx.typeck_results().node_types()[right.hir_id].is_bool()) + || !cx.typeck_results().node_types()[left.hir_id].is_bool() + || !cx.typeck_results().node_types()[right.hir_id].is_bool() { return; } diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index cc513d46bf4..08341ff32f3 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -151,13 +151,24 @@ pub(super) fn check<'tcx>( return false; } + // If the whole cast expression is a unary expression (`(*x as T)`) or an addressof + // expression (`(&x as T)`), then not surrounding the suggestion into a block risks us + // changing the precedence of operators if the cast expression is followed by an operation + // with higher precedence than the unary operator (`(*x as T).foo()` would become + // `*x.foo()`, which changes what the `*` applies on). + // The same is true if the expression encompassing the cast expression is a unary + // expression or an addressof expression. + let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)) + || get_parent_expr(cx, expr) + .map_or(false, |e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))); + span_lint_and_sugg( cx, UNNECESSARY_CAST, expr.span, &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"), "try", - if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(..))) { + if needs_block { format!("{{ {cast_str} }}") } else { cast_str diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index fb3ae2457e3..2b324f5f96e 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -47,6 +47,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO, crate::assertions_on_constants::ASSERTIONS_ON_CONSTANTS_INFO, crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO, + crate::assigning_clones::ASSIGNING_CLONES_INFO, crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO, crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO, crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO, @@ -58,6 +59,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::INLINE_ALWAYS_INFO, crate::attrs::MAYBE_MISUSED_CFG_INFO, crate::attrs::MISMATCHED_TARGET_OS_INFO, + crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO, crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO, diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 6144ec7b3ca..f0f2c7d6658 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -451,8 +451,8 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && !has_non_exhaustive_attr(cx.tcx, *adt) + && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) - && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]) // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() @@ -471,6 +471,10 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r } } +fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: DefId) -> bool { + tcx.non_blanket_impls_for_ty(eq_trait_id, ty).next().is_some() +} + /// Creates the `ParamEnv` used for the give type's derived `Eq` impl. fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> { // Initial map from generic index to param def. diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs index a58219c2946..d2f14756591 100644 --- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs +++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs @@ -8,7 +8,7 @@ use url::Url; use crate::doc::DOC_MARKDOWN; -pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) { +pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span, code_level: isize) { for orig_word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ @@ -46,11 +46,11 @@ pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span.parent(), ); - check_word(cx, word, span); + check_word(cx, word, span, code_level); } } -fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { +fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) { /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case /// letter (`NASA` is ok). @@ -60,7 +60,14 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { return false; } - let s = s.strip_suffix('s').unwrap_or(s); + let s = if let Some(prefix) = s.strip_suffix("es") + && prefix.chars().all(|c| c.is_ascii_uppercase()) + && matches!(prefix.chars().last(), Some('S' | 'X')) + { + prefix + } else { + s.strip_suffix('s').unwrap_or(s) + }; s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 @@ -90,7 +97,7 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { } // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) - if has_underscore(word) && has_hyphen(word) { + if code_level > 0 || (has_underscore(word) && has_hyphen(word)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 9af34c3a7bf..003d26b7b89 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -599,10 +599,19 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize let mut ignore = false; let mut edition = None; let mut ticks_unbalanced = false; - let mut text_to_check: Vec<(CowStr<'_>, Range<usize>)> = Vec::new(); + let mut text_to_check: Vec<(CowStr<'_>, Range<usize>, isize)> = Vec::new(); let mut paragraph_range = 0..0; + let mut code_level = 0; + for (event, range) in events { match event { + Html(tag) => { + if tag.starts_with("<code") { + code_level += 1; + } else if tag.starts_with("</code") { + code_level -= 1; + } + }, Start(CodeBlock(ref kind)) => { in_code = true; if let CodeBlockKind::Fenced(lang) = kind { @@ -652,16 +661,15 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize "a backtick may be missing a pair", ); } else { - for (text, range) in text_to_check { + for (text, range, assoc_code_level) in text_to_check { if let Some(span) = fragments.span(cx, range) { - markdown::check(cx, valid_idents, &text, span); + markdown::check(cx, valid_idents, &text, span, assoc_code_level); } } } text_to_check = Vec::new(); }, Start(_tag) | End(_tag) => (), // We don't care about other tags - Html(_html) => (), // HTML is weird, just ignore it SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (), FootnoteReference(text) | Text(text) => { paragraph_range.end = range.end; @@ -694,7 +702,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize // Don't check the text associated with external URLs continue; } - text_to_check.push((text, range)); + text_to_check.push((text, range, code_level)); } }, } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 0b4bc375df0..de6073c2723 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -214,12 +214,31 @@ impl MapType { } } +/// Details on an expression checking whether a map contains a key. +/// +/// For instance, with the following: +/// ```ignore +/// !!!self.the_map.contains_key("the_key") +/// ``` +/// +/// - `negated` will be set to `true` (the 3 `!` negate the condition) +/// - `map` will be the `self.the_map` expression +/// - `key` will be the `"the_key"` expression struct ContainsExpr<'tcx> { + /// Whether the check for `contains_key` was negated. negated: bool, + /// The map on which the check is performed. map: &'tcx Expr<'tcx>, + /// The key that is checked to be contained. key: &'tcx Expr<'tcx>, + /// The context of the whole condition expression. call_ctxt: SyntaxContext, } + +/// Inspect the given expression and return details about the `contains_key` check. +/// +/// If the given expression is not a `contains_key` check against a `BTreeMap` or a `HashMap`, +/// return `None`. fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(MapType, ContainsExpr<'tcx>)> { let mut negated = false; let expr = peel_hir_expr_while(expr, |e| match e.kind { @@ -229,6 +248,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio }, _ => None, }); + match expr.kind { ExprKind::MethodCall( _, @@ -261,11 +281,28 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio } } +/// Details on an expression inserting a key into a map. +/// +/// For instance, on the following: +/// ```ignore +/// self.the_map.insert("the_key", 3 + 4); +/// ``` +/// +/// - `map` will be the `self.the_map` expression +/// - `key` will be the `"the_key"` expression +/// - `value` will be the `3 + 4` expression struct InsertExpr<'tcx> { + /// The map into which the insertion is performed. map: &'tcx Expr<'tcx>, + /// The key at which to insert. key: &'tcx Expr<'tcx>, + /// The value to insert. value: &'tcx Expr<'tcx>, } + +/// Inspect the given expression and return details about the `insert` call. +/// +/// If the given expression is not an `insert` call into a `BTreeMap` or a `HashMap`, return `None`. fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> { if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; @@ -298,7 +335,7 @@ struct Insertion<'tcx> { value: &'tcx Expr<'tcx>, } -/// This visitor needs to do a multiple things: +/// This visitor needs to do multiple things: /// * Find all usages of the map. An insertion can only be made before any other usages of the map. /// * Determine if there's an insertion using the same key. There's no need for the entry api /// otherwise. @@ -346,7 +383,7 @@ impl<'tcx> InsertSearcher<'_, 'tcx> { res } - /// Visits an expression which is not itself in a tail position, but other sibling expressions + /// Visit an expression which is not itself in a tail position, but other sibling expressions /// may be. e.g. if conditions fn visit_non_tail_expr(&mut self, e: &'tcx Expr<'_>) { let in_tail_pos = self.in_tail_pos; @@ -354,6 +391,19 @@ impl<'tcx> InsertSearcher<'_, 'tcx> { self.visit_expr(e); self.in_tail_pos = in_tail_pos; } + + /// Visit the key and value expression of an insert expression. + /// There may not be uses of the map in either of those two either. + fn visit_insert_expr_arguments(&mut self, e: &InsertExpr<'tcx>) { + let in_tail_pos = self.in_tail_pos; + let allow_insert_closure = self.allow_insert_closure; + let is_single_insert = self.is_single_insert; + walk_expr(self, e.key); + walk_expr(self, e.value); + self.in_tail_pos = in_tail_pos; + self.allow_insert_closure = allow_insert_closure; + self.is_single_insert = is_single_insert; + } } impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { @@ -425,6 +475,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { match try_parse_insert(self.cx, expr) { Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => { + self.visit_insert_expr_arguments(&insert_expr); // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api. if self.is_map_used || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key) diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 606c2ed72be..0ea53c39280 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths}; -use rustc_hir::{Local, PatKind}; +use rustc_hir::{Local, LocalSource, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{GenericArgKind, IsSuggestable}; @@ -139,7 +139,8 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) { - if !in_external_macro(cx.tcx.sess, local.span) + if matches!(local.source, LocalSource::Normal) + && !in_external_macro(cx.tcx.sess, local.span) && let PatKind::Wild = local.pat.kind && let Some(init) = local.init { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 76e75968314..b930175c4d8 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -80,6 +80,7 @@ mod as_conversions; mod asm_syntax; mod assertions_on_constants; mod assertions_on_result_states; +mod assigning_clones; mod async_yields_async; mod attrs; mod await_holding_invalid; @@ -1118,6 +1119,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv()))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); + store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 58f713d8187..18f799e875a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_copy; +use clippy_utils::usage::local_used_in; use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg}; use rustc_ast::ast; use rustc_errors::Applicability; @@ -63,8 +64,9 @@ pub(super) fn check<'tcx>( && get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some() && let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts) && let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts) - - // Source and destination must be different + && !local_used_in(cx, canonical_id, base_left) + && !local_used_in(cx, canonical_id, base_right) + // Source and destination must be different && path_to_local(base_left) != path_to_local(base_right) { Some(( diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 69f86836775..b770ad0ddb5 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -37,12 +37,7 @@ pub(super) fn check<'tcx>( } } -fn set_diagnostic<'tcx>( - diag: &mut Diag<'_, ()>, - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'tcx>, - found: FoundSigDrop, -) { +fn set_diagnostic<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { if found.lint_suggestion == LintSuggestion::MoveAndClone { // If our suggestion is to move and clone, then we want to leave it to the user to // decide how to address this lint, since it may be that cloning is inappropriate. diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index adb696ad509..8a24ccea3a1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3875,6 +3875,7 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// ### What it does /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where f is a function or closure that returns the `bool` type. /// /// ### Why is this bad? @@ -3981,6 +3982,7 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// ### What it does /// Checks for the manual creation of C strings (a string with a `NUL` byte at the end), either /// through one of the `CStr` constructor functions, or more plainly by calling `.as_ptr()` /// on a (byte) string literal with a hardcoded `\0` byte at the end. diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs index f671517c134..0879dcd9bcd 100644 --- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs @@ -42,7 +42,7 @@ pub(crate) fn check<'tcx>( match op { BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { - check_op( + let _ = check_op( cx, left, 0, @@ -50,8 +50,7 @@ pub(crate) fn check<'tcx>( peeled_right_span, needs_parenthesis(cx, expr, right), right_is_coerced_to_value, - ); - check_op( + ) || check_op( cx, right, 0, @@ -62,7 +61,7 @@ pub(crate) fn check<'tcx>( ); }, BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { - check_op( + let _ = check_op( cx, right, 0, @@ -73,7 +72,7 @@ pub(crate) fn check<'tcx>( ); }, BinOpKind::Mul => { - check_op( + let _ = check_op( cx, left, 1, @@ -81,8 +80,18 @@ pub(crate) fn check<'tcx>( peeled_right_span, needs_parenthesis(cx, expr, right), right_is_coerced_to_value, + ) || check_op( + cx, + right, + 1, + expr.span, + peeled_left_span, + Parens::Unneeded, + left_is_coerced_to_value, ); - check_op( + }, + BinOpKind::Div => { + let _ = check_op( cx, right, 1, @@ -92,17 +101,8 @@ pub(crate) fn check<'tcx>( left_is_coerced_to_value, ); }, - BinOpKind::Div => check_op( - cx, - right, - 1, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ), BinOpKind::BitAnd => { - check_op( + let _ = check_op( cx, left, -1, @@ -110,8 +110,7 @@ pub(crate) fn check<'tcx>( peeled_right_span, needs_parenthesis(cx, expr, right), right_is_coerced_to_value, - ); - check_op( + ) || check_op( cx, right, -1, @@ -201,12 +200,12 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span } } -fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) { +fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool { if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), ty::Uint(uty) => clip(cx.tcx, !0, uty), - _ => return, + _ => return false, }; if match m { 0 => v == 0, @@ -215,8 +214,10 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa _ => unreachable!(), } { span_ineffective_operation(cx, span, arg, parens, is_erased); + return true; } } + false } fn span_ineffective_operation( diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index fecc5a8578e..311cbd050a1 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -21,9 +21,8 @@ pub(super) fn check<'tcx>( // lhs op= l op r if eq_expr_value(cx, lhs, l) { lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, r); - } - // lhs op= l commutative_op r - if is_commutative(op) && eq_expr_value(cx, lhs, r) { + } else if is_commutative(op) && eq_expr_value(cx, lhs, r) { + // lhs op= l commutative_op r lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, l); } } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 1df2d5e4602..cf7f730140c 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -203,108 +203,106 @@ fn expr_return_none_or_err( } } -impl QuestionMark { - fn inside_try_block(&self) -> bool { - self.try_block_depth_stack.last() > Some(&0) - } - - /// Checks if the given expression on the given context matches the following structure: - /// - /// ```ignore - /// if option.is_none() { - /// return None; - /// } - /// ``` - /// - /// ```ignore - /// if result.is_err() { - /// return result; - /// } - /// ``` - /// - /// If it matches, it will suggest to use the question mark operator instead - fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if !self.inside_try_block() - && let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) - && !is_else_clause(cx.tcx, expr) - && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind - && let caller_ty = cx.typeck_results().expr_ty(caller) - && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then) - && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block)) - { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) - && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); - let sugg = if let Some(else_inner) = r#else { - if eq_expr_value(cx, caller, peel_blocks(else_inner)) { - format!("Some({receiver_str}?)") - } else { - return; - } +/// Checks if the given expression on the given context matches the following structure: +/// +/// ```ignore +/// if option.is_none() { +/// return None; +/// } +/// ``` +/// +/// ```ignore +/// if result.is_err() { +/// return result; +/// } +/// ``` +/// +/// If it matches, it will suggest to use the question mark operator instead +fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) + && !is_else_clause(cx.tcx, expr) + && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind + && let caller_ty = cx.typeck_results().expr_ty(caller) + && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then) + && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block)) + { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); + let sugg = if let Some(else_inner) = r#else { + if eq_expr_value(cx, caller, peel_blocks(else_inner)) { + format!("Some({receiver_str}?)") } else { - format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) - }; + return; + } + } else { + format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) + }; - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); } +} - fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if !self.inside_try_block() - && let Some(higher::IfLet { - let_pat, - let_expr, - if_then, - if_else, - .. - }) = higher::IfLet::hir(cx, expr) - && !is_else_clause(cx.tcx, expr) - && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind - && ddpos.as_opt_usize().is_none() - && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind - && let caller_ty = cx.typeck_results().expr_ty(let_expr) - && let if_block = IfBlockType::IfLet( - cx.qpath_res(path1, let_pat.hir_id), - caller_ty, - ident.name, - let_expr, - if_then, - if_else, - ) - && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) - || is_early_return(sym::Result, cx, &if_block)) - && if_else - .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))) - .filter(|e| *e) - .is_none() - { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_)); - let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, - if requires_semi { ";" } else { "" } - ); - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } +fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let Some(higher::IfLet { + let_pat, + let_expr, + if_then, + if_else, + .. + }) = higher::IfLet::hir(cx, expr) + && !is_else_clause(cx.tcx, expr) + && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind + && ddpos.as_opt_usize().is_none() + && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind + && let caller_ty = cx.typeck_results().expr_ty(let_expr) + && let if_block = IfBlockType::IfLet( + cx.qpath_res(path1, let_pat.hir_id), + caller_ty, + ident.name, + let_expr, + if_then, + if_else, + ) + && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) + || is_early_return(sym::Result, cx, &if_block)) + && if_else + .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))) + .filter(|e| *e) + .is_none() + { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); + let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_)); + let sugg = format!( + "{receiver_str}{}?{}", + if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + if requires_semi { ";" } else { "" } + ); + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); + } +} + +impl QuestionMark { + fn inside_try_block(&self) -> bool { + self.try_block_depth_stack.last() > Some(&0) } } @@ -324,15 +322,18 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { return; } - if !in_constant(cx, stmt.hir_id) { + if !self.inside_try_block() && !in_constant(cx, stmt.hir_id) { check_let_some_else_return_none(cx, stmt); } self.check_manual_let_else(cx, stmt); } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if !in_constant(cx, expr.hir_id) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) { - self.check_is_none_or_err_and_early_return(cx, expr); - self.check_if_let_some_or_err_and_early_return(cx, expr); + if !self.inside_try_block() + && !in_constant(cx, expr.hir_id) + && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) + { + check_is_none_or_err_and_early_return(cx, expr); + check_if_let_some_or_err_and_early_return(cx, expr); } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index e3f0ce2a922..f61527cc0a9 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -159,6 +159,15 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { // ^^ we only want to lint for this call (but we walk up the calls to consider both calls). // without this check, we'd end up linting twice. && !matches!(recv.kind, hir::ExprKind::Call(..)) + // Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is + // the same as the one the call is in. + // For instance, let's assume `x!()` returns a closure: + // B ---v + // x!()() + // ^- A + // The call happens in the expansion `A`, while the closure originates from the expansion `B`. + // We don't want to suggest replacing `x!()()` with `x!()`. + && recv.span.ctxt().outer_expn() == expr.span.ctxt().outer_expn() && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) && let Some((body, fn_decl, coroutine_kind, params)) = find_innermost_closure(cx, recv, call_depth) // outside macros we lint properly. Inside macros, we lint only ||() style closures. diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs index fb000cd7184..17b031d5f01 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs @@ -59,24 +59,22 @@ impl EarlyLintPass for RedundantFieldNames { } if let ExprKind::Struct(ref se) = expr.kind { for field in &se.fields { - if field.is_shorthand { - continue; - } - if let ExprKind::Path(None, path) = &field.expr.kind { - if path.segments.len() == 1 - && path.segments[0].ident == field.ident - && path.segments[0].args.is_none() - { - span_lint_and_sugg( - cx, - REDUNDANT_FIELD_NAMES, - field.span, - "redundant field names in struct initialization", - "replace it with", - field.ident.to_string(), - Applicability::MachineApplicable, - ); - } + if !field.is_shorthand + && let ExprKind::Path(None, path) = &field.expr.kind + && let [segment] = path.segments.as_slice() + && segment.args.is_none() + && segment.ident == field.ident + && field.span.eq_ctxt(field.ident.span) + { + span_lint_and_sugg( + cx, + REDUNDANT_FIELD_NAMES, + field.span, + "redundant field names in struct initialization", + "replace it with", + field.ident.to_string(), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 38fd54a0f1e..c0e4f3c368a 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -109,7 +109,6 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { sym::core => (STD_INSTEAD_OF_CORE, "std", "core"), sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"), _ => { - self.prev_span = path.span; return; }, }, @@ -117,13 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { if cx.tcx.crate_name(def_id.krate) == sym::core { (ALLOC_INSTEAD_OF_CORE, "alloc", "core") } else { - self.prev_span = path.span; return; } }, _ => return, }; - if path.span != self.prev_span { + if first_segment.ident.span != self.prev_span { span_lint_and_sugg( cx, lint, @@ -133,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { replace_with.to_string(), Applicability::MachineApplicable, ); - self.prev_span = path.span; + self.prev_span = first_segment.ident.span; } } } diff --git a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs index 9fee4c06200..1af3733ebfa 100644 --- a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs +++ b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs @@ -1,12 +1,11 @@ -use clippy_config::msrvs::Msrv; +use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::fn_has_unsatisfiable_preds; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::source::snippet; +use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{intravisit, ExprKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym::thread_local_macro; @@ -57,6 +56,31 @@ impl ThreadLocalInitializerCanBeMadeConst { impl_lint_pass!(ThreadLocalInitializerCanBeMadeConst => [THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST]); +#[inline] +fn is_thread_local_initializer( + cx: &LateContext<'_>, + fn_kind: rustc_hir::intravisit::FnKind<'_>, + span: rustc_span::Span, +) -> Option<bool> { + let macro_def_id = span.source_callee()?.macro_def_id?; + Some( + cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id) + && matches!(fn_kind, intravisit::FnKind::ItemFn(..)), + ) +} + +#[inline] +fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: &Msrv) -> bool { + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if !fn_has_unsatisfiable_preds(cx, defid) + && let mir = cx.tcx.optimized_mir(defid) + && let Ok(()) = is_min_const_fn(cx.tcx, mir, msrv) + { + return true; + } + false +} + impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst { fn check_fn( &mut self, @@ -65,31 +89,32 @@ impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst { _: &'tcx rustc_hir::FnDecl<'tcx>, body: &'tcx rustc_hir::Body<'tcx>, span: rustc_span::Span, - defid: rustc_span::def_id::LocalDefId, + local_defid: rustc_span::def_id::LocalDefId, ) { - if in_external_macro(cx.sess(), span) - && let Some(callee) = span.source_callee() - && let Some(macro_def_id) = callee.macro_def_id - && cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id) - && let intravisit::FnKind::ItemFn(..) = fn_kind - // Building MIR for `fn`s with unsatisfiable preds results in ICE. - && !fn_has_unsatisfiable_preds(cx, defid.to_def_id()) - && let mir = cx.tcx.optimized_mir(defid.to_def_id()) - && let Ok(()) = is_min_const_fn(cx.tcx, mir, &self.msrv) - // this is the `__init` function emitted by the `thread_local!` macro - // when the `const` keyword is not used. We avoid checking the `__init` directly - // as that is not a public API. - // we know that the function is const-qualifiable, so now we need only to get the - // initializer expression to span-lint it. + let defid = local_defid.to_def_id(); + if self.msrv.meets(msrvs::THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST) + && is_thread_local_initializer(cx, fn_kind, span).unwrap_or(false) + // Some implementations of `thread_local!` include an initializer fn. + // In the case of a const initializer, the init fn is also const, + // so we can skip the lint in that case. This occurs only on some + // backends due to conditional compilation: + // https://doc.rust-lang.org/src/std/sys/common/thread_local/mod.rs.html + // for details on this issue, see: + // https://github.com/rust-lang/rust-clippy/pull/12276 + && !cx.tcx.is_const_fn(defid) + && initializer_can_be_made_const(cx, defid, &self.msrv) + // we know that the function is const-qualifiable, so now + // we need only to get the initializer expression to span-lint it. && let ExprKind::Block(block, _) = body.value.kind - && let Some(ret_expr) = block.expr + && let Some(unpeeled) = block.expr + && let ret_expr = peel_blocks(unpeeled) && let initializer_snippet = snippet(cx, ret_expr.span, "thread_local! { ... }") && initializer_snippet != "thread_local! { ... }" { span_lint_and_sugg( cx, THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST, - ret_expr.span, + unpeeled.span, "initializer for `thread_local` value can be made `const`", "replace with", format!("const {{ {initializer_snippet} }}"), diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 06de7a11031..e47b14bf63b 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -592,7 +592,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | (eager_transmute::check(cx, e, arg, from_ty, to_ty)); if !linted { - transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg); + transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg, const_context); } } } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index bbecc39a813..043c9c88601 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -18,10 +18,12 @@ pub(super) fn check<'tcx>( from_ty_adjusted: bool, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, + const_context: bool, ) -> bool { use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; let mut app = Applicability::MachineApplicable; let mut sugg = match check_cast(cx, e, from_ty, to_ty) { + Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false, Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => { Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app) .as_ty(to_ty.to_string()) diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index a285f771f1b..7926738d68f 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::paths::ALLOCATOR_GLOBAL; +use clippy_utils::last_path_segment; use clippy_utils::source::snippet; -use clippy_utils::{last_path_segment, match_def_path}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, GenericArg, QPath, TyKind}; +use rustc_hir::{self as hir, GenericArg, LangItem, QPath, TyKind}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::LateContext; use rustc_middle::ty::layout::LayoutOf; @@ -50,7 +49,7 @@ pub(super) fn check<'tcx>( (None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => { if let TyKind::Path(path) = inner.kind && let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() { - match_def_path(cx, did, &ALLOCATOR_GLOBAL) + cx.tcx.lang_items().get(LangItem::GlobalAlloc) == Some(did) } else { false } diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 2f728b62754..987f28192a8 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -115,4 +115,3 @@ pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"]; pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"]; #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"]; -pub const ALLOCATOR_GLOBAL: [&str; 3] = ["alloc", "alloc", "Global"]; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index e74621a0fbb..5090d0bd98b 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -995,7 +995,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { // no adjustment needed here, as field projections are handled by the compiler ProjectionKind::Field(..) => match cmt.place.ty_before_projection(i).kind() { ty::Adt(..) | ty::Tuple(_) => { - replacement_str = ident_str_with_proj.clone(); + replacement_str.clone_from(&ident_str_with_proj); projections_handled = true; }, _ => (), diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index fb038b617df..070b62887d5 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-02-22" +channel = "nightly-2024-03-07" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index dffa854177b..30beaae34d2 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -174,8 +174,13 @@ To allow or deny a lint from the command line you can use <cyan,bold>cargo clipp You can use tool lints to allow or deny lints from your code, e.g.: <yellow,bold>#[allow(clippy::needless_lifetimes)]</> -" - ) + +<green,bold>Manifest Options:</> + <cyan,bold>--manifest-path</> <cyan><<PATH>></> Path to Cargo.toml + <cyan,bold>--frozen</> Require Cargo.lock and cache are up to date + <cyan,bold>--locked</> Require Cargo.lock is up to date + <cyan,bold>--offline</> Run without accessing the network +") } #[cfg(test)] mod tests { diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index a088896b6b0..a0c8bf9334c 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -138,6 +138,7 @@ fn base_config(test_dir: &str) -> (Config, Args) { "-Aunused", "-Ainternal_features", "-Zui-testing", + "-Zdeduplicate-diagnostics=no", "-Dwarnings", &format!("-Ldependency={}", deps_path.display()), ] diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs index 0d35a22cd9a..141c11ddb47 100644 --- a/src/tools/clippy/tests/missing-test-files.rs +++ b/src/tools/clippy/tests/missing-test-files.rs @@ -54,7 +54,7 @@ fn explore_directory(dir: &Path) -> Vec<String> { let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string(); if let Some(ext) = path.extension() { match ext.to_str().unwrap() { - "rs" | "toml" => current_file = file_prefix.clone(), + "rs" | "toml" => current_file.clone_from(&file_prefix), "stderr" | "stdout" => { if file_prefix != current_file { missing_files.push(path.to_str().unwrap().to_string()); diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs index 9b0db660c99..400bfd5d975 100644 --- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs @@ -5,6 +5,7 @@ //@normalize-stderr-test: "'rustc'" -> "'<unnamed>'" //@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>" //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" +//@normalize-stderr-test: "this compiler `.*` is outdated" -> "this compiler <version> is outdated" #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr index d8b158816c9..b84f4e87e07 100644 --- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr @@ -4,11 +4,14 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: the compiler unexpectedly panicked. this is a bug. -note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml +note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the mean time + | + = note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists + = note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml note: rustc <version> running on <target> -note: compiler flags: -Z ui-testing +note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no note: Clippy version: foo diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs index c5029bbd9a4..5a2a868ed3e 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs @@ -10,22 +10,11 @@ use rustc_hir::hir_id::HirId; use rustc_lint::{Lint, LintContext}; use rustc_middle::ty::TyCtxt; -pub fn a( - cx: impl LintContext, - lint: &'static Lint, - span: impl Into<MultiSpan>, - msg: impl Into<DiagMessage>) -{ +pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) { cx.span_lint(lint, span, msg, |_| {}); } -pub fn b( - tcx: TyCtxt<'_>, - lint: &'static Lint, - hir_id: HirId, - span: impl Into<MultiSpan>, - msg: impl Into<DiagMessage>, -) { +pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) { tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); } diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr index 1a1ad26290c..ae5d6843406 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr @@ -8,7 +8,7 @@ LL | cx.span_lint(lint, span, msg, |_| {}); = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint` - --> tests/ui-internal/disallow_span_lint.rs:24:5 + --> tests/ui-internal/disallow_span_lint.rs:18:5 | LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 87f84d8f7dd..37d69055737 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:266:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:317:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:325:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:339:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:350:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:357:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:411:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:417:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:463:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:474:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:483:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:492:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:505:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -291,13 +291,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:504:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -305,7 +305,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 5ffe73f5a2f..400fde997e9 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:266:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:317:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:325:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:339:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:350:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:357:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:411:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:417:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:463:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:474:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:483:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:492:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:502:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +287,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:505:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -299,13 +299,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:504:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -321,7 +321,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:527:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:532:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -329,7 +329,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:531:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:536:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:535:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:540:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -345,7 +345,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:541:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:546:5 | LL | unsafe {} | ^^^^^^^^^ @@ -353,7 +353,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:550:5 | LL | unsafe { | ^^^^^^^^ @@ -361,7 +361,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:552:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:557:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -369,7 +369,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:557:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:562:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -377,7 +377,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:563:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:5 | LL | unsafe {} | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 8997073c8a5..e5ef9d35fb6 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -4,7 +4,12 @@ //@[disabled] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/undocumented_unsafe_blocks/disabled #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(deref_nullptr, non_local_definitions, clippy::let_unit_value, clippy::missing_safety_doc)] +#![allow( + deref_nullptr, + non_local_definitions, + clippy::let_unit_value, + clippy::missing_safety_doc +)] #![feature(lint_reasons)] extern crate proc_macro_unsafe; diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed new file mode 100644 index 00000000000..c66e0c1f602 --- /dev/null +++ b/src/tools/clippy/tests/ui/assigning_clones.fixed @@ -0,0 +1,222 @@ +#![allow(unused)] +#![allow(clippy::redundant_clone)] +#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612 +#![allow(clippy::needless_late_init)] +#![allow(clippy::box_collection)] +#![warn(clippy::assigning_clones)] + +use std::borrow::ToOwned; +use std::ops::{Add, Deref, DerefMut}; + +// Clone +pub struct HasCloneFrom; + +impl Clone for HasCloneFrom { + fn clone(&self) -> Self { + Self + } + fn clone_from(&mut self, source: &Self) { + *self = HasCloneFrom; + } +} + +fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) { + mut_thing.clone_from(&value_thing); +} + +fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + mut_thing.clone_from(ref_thing); +} + +fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { + mut_thing.clone_from(ref_thing); +} + +fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + Clone::clone_from(mut_thing, ref_thing); +} + +fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { + Clone::clone_from(&mut mut_thing, ref_thing); +} + +fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + Clone::clone_from(mut_thing, ref_thing); +} + +fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + Clone::clone_from(mut_thing, ref_thing); +} + +fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + Clone::clone_from(mut_thing, ref_thing); +} + +fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + // These parens should be kept as necessary for a receiver + (mut_thing + &mut HasCloneFrom).clone_from(ref_thing); +} + +fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + // These parens should be removed since they are not needed in a function argument + mut_thing.clone_from(ref_thing + ref_thing); +} + +fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { + let mut a = HasCloneFrom; + for _ in 1..10 { + a.clone_from(&b); + } + a +} + +fn assign_to_late_init_mut_var(b: HasCloneFrom) { + let mut a; + a = HasCloneFrom; + a = b.clone(); +} + +fn assign_to_uninit_var(b: HasCloneFrom) { + let a; + a = b.clone(); +} + +fn assign_to_uninit_mut_var(b: HasCloneFrom) { + let mut a; + a = b.clone(); +} + +#[derive(Clone)] +pub struct HasDeriveClone; + +fn ignore_derive_clone(a: &mut HasDeriveClone, b: &HasDeriveClone) { + // Should not be linted, since the Clone impl is derived + *a = b.clone(); +} + +pub struct HasCloneImpl; + +impl Clone for HasCloneImpl { + fn clone(&self) -> Self { + Self + } +} + +fn ignore_missing_clone_from(a: &mut HasCloneImpl, b: &HasCloneImpl) { + // Should not be linted, since the Clone impl doesn't override clone_from + *a = b.clone(); +} + +struct FakeClone; + +impl FakeClone { + /// This looks just like `Clone::clone` + fn clone(&self) -> Self { + FakeClone + } +} + +fn ignore_fake_clone() { + let mut a = FakeClone; + let b = FakeClone; + // Should not be linted, since the Clone impl doesn't come from std + a = b.clone(); +} + +fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) { + // Should not be linted, since we don't know the actual clone impl + *a = b.clone(); +} + +macro_rules! clone_inside { + ($a:expr, $b: expr) => { + $a = $b.clone(); + }; +} + +fn clone_inside_macro() { + let mut a = String::new(); + let b = String::new(); + clone_inside!(a, b); +} + +// ToOwned +fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { + ref_str.clone_into(mut_string); +} + +fn owned_method_val(mut mut_string: String, ref_str: &str) { + ref_str.clone_into(&mut mut_string); +} + +struct HasDeref { + a: String, +} + +impl Deref for HasDeref { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.a + } +} + +impl DerefMut for HasDeref { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.a + } +} + +fn owned_method_box(mut_box_string: &mut Box<String>, ref_str: &str) { + ref_str.clone_into(&mut (*mut_box_string)); +} + +fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) { + ref_str.clone_into(&mut (*mut_box_string)); +} + +fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) { + ToOwned::clone_into(ref_str, mut_thing); +} + +fn owned_function_val(mut mut_thing: String, ref_str: &str) { + ToOwned::clone_into(ref_str, &mut mut_thing); +} + +struct FakeToOwned; +impl FakeToOwned { + /// This looks just like `ToOwned::to_owned` + fn to_owned(&self) -> Self { + FakeToOwned + } +} + +fn fake_to_owned() { + let mut a = FakeToOwned; + let b = FakeToOwned; + // Should not be linted, since the ToOwned impl doesn't come from std + a = b.to_owned(); +} + +fn main() {} + +/// Trait implementation to allow producing a `Thing` with a low-precedence expression. +impl Add for HasCloneFrom { + type Output = Self; + fn add(self, _: HasCloneFrom) -> Self { + self + } +} +/// Trait implementation to allow producing a `&Thing` with a low-precedence expression. +impl<'a> Add for &'a HasCloneFrom { + type Output = Self; + fn add(self, _: &'a HasCloneFrom) -> Self { + self + } +} +/// Trait implementation to allow producing a `&mut Thing` with a low-precedence expression. +impl<'a> Add for &'a mut HasCloneFrom { + type Output = Self; + fn add(self, _: &'a mut HasCloneFrom) -> Self { + self + } +} diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs new file mode 100644 index 00000000000..b9f994d3e03 --- /dev/null +++ b/src/tools/clippy/tests/ui/assigning_clones.rs @@ -0,0 +1,222 @@ +#![allow(unused)] +#![allow(clippy::redundant_clone)] +#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612 +#![allow(clippy::needless_late_init)] +#![allow(clippy::box_collection)] +#![warn(clippy::assigning_clones)] + +use std::borrow::ToOwned; +use std::ops::{Add, Deref, DerefMut}; + +// Clone +pub struct HasCloneFrom; + +impl Clone for HasCloneFrom { + fn clone(&self) -> Self { + Self + } + fn clone_from(&mut self, source: &Self) { + *self = HasCloneFrom; + } +} + +fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) { + *mut_thing = value_thing.clone(); +} + +fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + *mut_thing = ref_thing.clone(); +} + +fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { + mut_thing = ref_thing.clone(); +} + +fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + *mut_thing = Clone::clone(ref_thing); +} + +fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) { + mut_thing = Clone::clone(ref_thing); +} + +fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + *mut_thing = Clone::clone(ref_thing); +} + +fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + *mut_thing = HasCloneFrom::clone(ref_thing); +} + +fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing); +} + +fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + // These parens should be kept as necessary for a receiver + *(mut_thing + &mut HasCloneFrom) = ref_thing.clone(); +} + +fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) { + // These parens should be removed since they are not needed in a function argument + *mut_thing = (ref_thing + ref_thing).clone(); +} + +fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { + let mut a = HasCloneFrom; + for _ in 1..10 { + a = b.clone(); + } + a +} + +fn assign_to_late_init_mut_var(b: HasCloneFrom) { + let mut a; + a = HasCloneFrom; + a = b.clone(); +} + +fn assign_to_uninit_var(b: HasCloneFrom) { + let a; + a = b.clone(); +} + +fn assign_to_uninit_mut_var(b: HasCloneFrom) { + let mut a; + a = b.clone(); +} + +#[derive(Clone)] +pub struct HasDeriveClone; + +fn ignore_derive_clone(a: &mut HasDeriveClone, b: &HasDeriveClone) { + // Should not be linted, since the Clone impl is derived + *a = b.clone(); +} + +pub struct HasCloneImpl; + +impl Clone for HasCloneImpl { + fn clone(&self) -> Self { + Self + } +} + +fn ignore_missing_clone_from(a: &mut HasCloneImpl, b: &HasCloneImpl) { + // Should not be linted, since the Clone impl doesn't override clone_from + *a = b.clone(); +} + +struct FakeClone; + +impl FakeClone { + /// This looks just like `Clone::clone` + fn clone(&self) -> Self { + FakeClone + } +} + +fn ignore_fake_clone() { + let mut a = FakeClone; + let b = FakeClone; + // Should not be linted, since the Clone impl doesn't come from std + a = b.clone(); +} + +fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) { + // Should not be linted, since we don't know the actual clone impl + *a = b.clone(); +} + +macro_rules! clone_inside { + ($a:expr, $b: expr) => { + $a = $b.clone(); + }; +} + +fn clone_inside_macro() { + let mut a = String::new(); + let b = String::new(); + clone_inside!(a, b); +} + +// ToOwned +fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) { + *mut_string = ref_str.to_owned(); +} + +fn owned_method_val(mut mut_string: String, ref_str: &str) { + mut_string = ref_str.to_owned(); +} + +struct HasDeref { + a: String, +} + +impl Deref for HasDeref { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.a + } +} + +impl DerefMut for HasDeref { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.a + } +} + +fn owned_method_box(mut_box_string: &mut Box<String>, ref_str: &str) { + **mut_box_string = ref_str.to_owned(); +} + +fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) { + **mut_box_string = ref_str.to_owned(); +} + +fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) { + *mut_thing = ToOwned::to_owned(ref_str); +} + +fn owned_function_val(mut mut_thing: String, ref_str: &str) { + mut_thing = ToOwned::to_owned(ref_str); +} + +struct FakeToOwned; +impl FakeToOwned { + /// This looks just like `ToOwned::to_owned` + fn to_owned(&self) -> Self { + FakeToOwned + } +} + +fn fake_to_owned() { + let mut a = FakeToOwned; + let b = FakeToOwned; + // Should not be linted, since the ToOwned impl doesn't come from std + a = b.to_owned(); +} + +fn main() {} + +/// Trait implementation to allow producing a `Thing` with a low-precedence expression. +impl Add for HasCloneFrom { + type Output = Self; + fn add(self, _: HasCloneFrom) -> Self { + self + } +} +/// Trait implementation to allow producing a `&Thing` with a low-precedence expression. +impl<'a> Add for &'a HasCloneFrom { + type Output = Self; + fn add(self, _: &'a HasCloneFrom) -> Self { + self + } +} +/// Trait implementation to allow producing a `&mut Thing` with a low-precedence expression. +impl<'a> Add for &'a mut HasCloneFrom { + type Output = Self; + fn add(self, _: &'a mut HasCloneFrom) -> Self { + self + } +} diff --git a/src/tools/clippy/tests/ui/assigning_clones.stderr b/src/tools/clippy/tests/ui/assigning_clones.stderr new file mode 100644 index 00000000000..b76323f3606 --- /dev/null +++ b/src/tools/clippy/tests/ui/assigning_clones.stderr @@ -0,0 +1,107 @@ +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:24:5 + | +LL | *mut_thing = value_thing.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(&value_thing)` + | + = note: `-D clippy::assigning-clones` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::assigning_clones)]` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:28:5 + | +LL | *mut_thing = ref_thing.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:32:5 + | +LL | mut_thing = ref_thing.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:36:5 + | +LL | *mut_thing = Clone::clone(ref_thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:40:5 + | +LL | mut_thing = Clone::clone(ref_thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut mut_thing, ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:44:5 + | +LL | *mut_thing = Clone::clone(ref_thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:48:5 + | +LL | *mut_thing = HasCloneFrom::clone(ref_thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:52:5 + | +LL | *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:57:5 + | +LL | *(mut_thing + &mut HasCloneFrom) = ref_thing.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `(mut_thing + &mut HasCloneFrom).clone_from(ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:62:5 + | +LL | *mut_thing = (ref_thing + ref_thing).clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:68:9 + | +LL | a = b.clone(); + | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:145:5 + | +LL | *mut_string = ref_str.to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:149:5 + | +LL | mut_string = ref_str.to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:170:5 + | +LL | **mut_box_string = ref_str.to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:174:5 + | +LL | **mut_box_string = ref_str.to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:178:5 + | +LL | *mut_thing = ToOwned::to_owned(ref_str); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:182:5 + | +LL | mut_thing = ToOwned::to_owned(ref_str); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)` + +error: aborting due to 17 previous errors + diff --git a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs index b56abccbd41..e920e58d6ec 100644 --- a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs +++ b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs @@ -3,6 +3,6 @@ struct Foo(isize, isize, isize, isize); pub fn main() { let Self::anything_here_kills_it(a, b, ..) = Foo(5, 5, 5, 5); match [5, 5, 5, 5] { - [..] => { } + [..] => {}, } } diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed index aa7a95405e0..6f42487bbf4 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed @@ -153,4 +153,30 @@ pub enum MissingEqNonExhaustive3 { Bar, } +mod struct_gen { + // issue 9413 + pub trait Group { + type Element: Eq + PartialEq; + } + + pub trait Suite { + type Group: Group; + } + + #[derive(PartialEq, Eq)] + //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + pub struct Foo<C: Suite>(<C::Group as Group>::Element); + + #[derive(PartialEq, Eq)] + pub struct Bar<C: Suite>(i32, <C::Group as Group>::Element); + + // issue 9319 + #[derive(PartialEq, Eq)] + //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + pub struct Oof<T: Fn()>(T); + + #[derive(PartialEq, Eq)] + pub struct Rab<T: Fn()>(T); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs index 90ac7a7989e..24f687c6c9d 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs @@ -153,4 +153,30 @@ pub enum MissingEqNonExhaustive3 { Bar, } +mod struct_gen { + // issue 9413 + pub trait Group { + type Element: Eq + PartialEq; + } + + pub trait Suite { + type Group: Group; + } + + #[derive(PartialEq)] + //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + pub struct Foo<C: Suite>(<C::Group as Group>::Element); + + #[derive(PartialEq, Eq)] + pub struct Bar<C: Suite>(i32, <C::Group as Group>::Element); + + // issue 9319 + #[derive(PartialEq)] + //~^ ERROR: you are deriving `PartialEq` and can implement `Eq` + pub struct Oof<T: Fn()>(T); + + #[derive(PartialEq, Eq)] + pub struct Rab<T: Fn()>(T); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr index 42b9895121f..3d92112dc36 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr @@ -67,5 +67,17 @@ error: you are deriving `PartialEq` and can implement `Eq` LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` -error: aborting due to 11 previous errors +error: you are deriving `PartialEq` and can implement `Eq` + --> tests/ui/derive_partial_eq_without_eq.rs:166:14 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` + +error: you are deriving `PartialEq` and can implement `Eq` + --> tests/ui/derive_partial_eq_without_eq.rs:174:14 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` + +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index 16f7bafd44b..178d4a1aa2b 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -230,3 +230,8 @@ fn issue_11568() {} /// There is no try (`do()` or `do_not()`). fn parenthesized_word() {} + +/// `ABes` +/// OSes +/// UXes +fn plural_acronym_test() {} diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index 4058b2bad74..01edb44c64c 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -230,3 +230,8 @@ fn issue_11568() {} /// There is no try (do() or do_not()). fn parenthesized_word() {} + +/// ABes +/// OSes +/// UXes +fn plural_acronym_test() {} diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr index 7db9ff2b83b..ac876306b39 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr @@ -341,5 +341,16 @@ help: try LL | /// There is no try (do() or `do_not()`). | ~~~~~~~~~~ -error: aborting due to 31 previous errors +error: item in documentation is missing backticks + --> tests/ui/doc/doc-fixable.rs:234:5 + | +LL | /// ABes + | ^^^^ + | +help: try + | +LL | /// `ABes` + | ~~~~~~ + +error: aborting due to 32 previous errors diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.fixed b/src/tools/clippy/tests/ui/doc/issue_9473.fixed new file mode 100644 index 00000000000..276ce7620ca --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/issue_9473.fixed @@ -0,0 +1,9 @@ +#![warn(clippy::doc_markdown)] + +// Should not warn! +/// Blah blah blah <code>[FooBar]<[FooBar]></code>. +pub struct Foo(u32); + +// Should warn. +/// Blah blah blah <code>[FooBar]<[FooBar]></code>[`FooBar`]. +pub struct FooBar(u32); diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.rs b/src/tools/clippy/tests/ui/doc/issue_9473.rs new file mode 100644 index 00000000000..52527f7106d --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/issue_9473.rs @@ -0,0 +1,9 @@ +#![warn(clippy::doc_markdown)] + +// Should not warn! +/// Blah blah blah <code>[FooBar]<[FooBar]></code>. +pub struct Foo(u32); + +// Should warn. +/// Blah blah blah <code>[FooBar]<[FooBar]></code>[FooBar]. +pub struct FooBar(u32); diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.stderr b/src/tools/clippy/tests/ui/doc/issue_9473.stderr new file mode 100644 index 00000000000..35aa2884cc1 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/issue_9473.stderr @@ -0,0 +1,15 @@ +error: item in documentation is missing backticks + --> tests/ui/doc/issue_9473.rs:8:58 + | +LL | /// Blah blah blah <code>[FooBar]<[FooBar]></code>[FooBar]. + | ^^^^^^ + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]` +help: try + | +LL | /// Blah blah blah <code>[FooBar]<[FooBar]></code>[`FooBar`]. + | ~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/else_if_without_else.rs b/src/tools/clippy/tests/ui/else_if_without_else.rs index eb5e2266540..e7786f7dd27 100644 --- a/src/tools/clippy/tests/ui/else_if_without_else.rs +++ b/src/tools/clippy/tests/ui/else_if_without_else.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::all)] #![warn(clippy::else_if_without_else)] diff --git a/src/tools/clippy/tests/ui/else_if_without_else.stderr b/src/tools/clippy/tests/ui/else_if_without_else.stderr index 80355cb2dba..3bb840f39e7 100644 --- a/src/tools/clippy/tests/ui/else_if_without_else.stderr +++ b/src/tools/clippy/tests/ui/else_if_without_else.stderr @@ -1,5 +1,5 @@ error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:45:12 + --> tests/ui/else_if_without_else.rs:47:12 | LL | } else if bla2() { | ____________^ @@ -13,7 +13,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::else_if_without_else)]` error: `if` expression with an `else if`, but without a final `else` - --> tests/ui/else_if_without_else.rs:54:12 + --> tests/ui/else_if_without_else.rs:56:12 | LL | } else if bla3() { | ____________^ diff --git a/src/tools/clippy/tests/ui/empty_docs.rs b/src/tools/clippy/tests/ui/empty_docs.rs index c47a603e71b..272fab7d5ca 100644 --- a/src/tools/clippy/tests/ui/empty_docs.rs +++ b/src/tools/clippy/tests/ui/empty_docs.rs @@ -1,5 +1,7 @@ #![allow(unused)] #![warn(clippy::empty_docs)] +#![allow(clippy::mixed_attributes_style)] + mod outer { //! diff --git a/src/tools/clippy/tests/ui/empty_docs.stderr b/src/tools/clippy/tests/ui/empty_docs.stderr index 3f1d071fb13..f12aead6aa7 100644 --- a/src/tools/clippy/tests/ui/empty_docs.stderr +++ b/src/tools/clippy/tests/ui/empty_docs.stderr @@ -1,5 +1,5 @@ error: empty doc comment - --> tests/ui/empty_docs.rs:4:5 + --> tests/ui/empty_docs.rs:6:5 | LL | //! | ^^^ @@ -9,7 +9,7 @@ LL | //! = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]` error: empty doc comment - --> tests/ui/empty_docs.rs:12:5 + --> tests/ui/empty_docs.rs:14:5 | LL | /// | ^^^ @@ -17,7 +17,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:14:9 + --> tests/ui/empty_docs.rs:16:9 | LL | /// | ^^^ @@ -25,7 +25,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:25:5 + --> tests/ui/empty_docs.rs:27:5 | LL | #[doc = ""] | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:28:5 + --> tests/ui/empty_docs.rs:30:5 | LL | / #[doc = ""] LL | | #[doc = ""] @@ -42,7 +42,7 @@ LL | | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:35:5 + --> tests/ui/empty_docs.rs:37:5 | LL | /// | ^^^ @@ -50,7 +50,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:48:13 + --> tests/ui/empty_docs.rs:50:13 | LL | /*! */ | ^^^^^^ @@ -58,7 +58,7 @@ LL | /*! */ = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:56:13 + --> tests/ui/empty_docs.rs:58:13 | LL | /// | ^^^ @@ -66,7 +66,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:64:9 + --> tests/ui/empty_docs.rs:66:9 | LL | /// | ^^^ diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed index 4099fe7e139..71ec13f4610 100644 --- a/src/tools/clippy/tests/ui/entry.fixed +++ b/src/tools/clippy/tests/ui/entry.fixed @@ -165,4 +165,15 @@ pub fn issue_10331() { } } +/// Issue 11935 +/// Do not suggest using entries if the map is used inside the `insert` expression. +pub fn issue_11935() { + let mut counts: HashMap<u64, u64> = HashMap::new(); + if !counts.contains_key(&1) { + counts.insert(1, 1); + } else { + counts.insert(1, counts.get(&1).unwrap() + 1); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs index 409be0aa060..86092b7c055 100644 --- a/src/tools/clippy/tests/ui/entry.rs +++ b/src/tools/clippy/tests/ui/entry.rs @@ -169,4 +169,15 @@ pub fn issue_10331() { } } +/// Issue 11935 +/// Do not suggest using entries if the map is used inside the `insert` expression. +pub fn issue_11935() { + let mut counts: HashMap<u64, u64> = HashMap::new(); + if !counts.contains_key(&1) { + counts.insert(1, 1); + } else { + counts.insert(1, counts.get(&1).unwrap() + 1); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed index 06229a52a18..f38b34c5a7c 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed @@ -6,7 +6,7 @@ clippy::deref_addrof, clippy::unnecessary_mut_passed, dead_code, - non_local_definitions, + non_local_definitions )] use core::slice; diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_iter_loop.rs index c2bf45ab2e9..2e701ada5ac 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.rs +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.rs @@ -6,7 +6,7 @@ clippy::deref_addrof, clippy::unnecessary_mut_passed, dead_code, - non_local_definitions, + non_local_definitions )] use core::slice; diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs index 2045b1eebcd..620cffb4f04 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs @@ -2,6 +2,7 @@ //@aux-build:proc_macros.rs #![warn(clippy::field_reassign_with_default)] +#![allow(clippy::assigning_clones)] #[macro_use] extern crate proc_macro_derive; diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr index bc032834920..ae909475c6f 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr @@ -1,11 +1,11 @@ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:56:5 + --> tests/ui/field_reassign_with_default.rs:57:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:55:5 + --> tests/ui/field_reassign_with_default.rs:56:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,121 +13,121 @@ LL | let mut a: A = Default::default(); = help: to override `-D warnings` add `#[allow(clippy::field_reassign_with_default)]` error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:96:5 + --> tests/ui/field_reassign_with_default.rs:97:5 | LL | a.j = 43; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:95:5 + --> tests/ui/field_reassign_with_default.rs:96:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:101:5 + --> tests/ui/field_reassign_with_default.rs:102:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:100:5 + --> tests/ui/field_reassign_with_default.rs:101:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:107:5 + --> tests/ui/field_reassign_with_default.rs:108:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:106:5 + --> tests/ui/field_reassign_with_default.rs:107:5 | LL | let mut a = A::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:117:5 + --> tests/ui/field_reassign_with_default.rs:118:5 | LL | a.i = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:116:5 + --> tests/ui/field_reassign_with_default.rs:117:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:121:5 + --> tests/ui/field_reassign_with_default.rs:122:5 | LL | a.i = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:120:5 + --> tests/ui/field_reassign_with_default.rs:121:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:143:5 + --> tests/ui/field_reassign_with_default.rs:144:5 | LL | a.i = vec![1]; | ^^^^^^^^^^^^^^ | note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:142:5 + --> tests/ui/field_reassign_with_default.rs:143:5 | LL | let mut a: C = C::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:161:5 + --> tests/ui/field_reassign_with_default.rs:162:5 | LL | a.i = true; | ^^^^^^^^^^^ | note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:160:5 + --> tests/ui/field_reassign_with_default.rs:161:5 | LL | let mut a: Wrapper<bool> = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:164:5 + --> tests/ui/field_reassign_with_default.rs:165:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:163:5 + --> tests/ui/field_reassign_with_default.rs:164:5 | LL | let mut a: WrapperMulti<i32, i64> = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:235:13 + --> tests/ui/field_reassign_with_default.rs:236:13 | LL | f.name = name.len(); | ^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:234:13 + --> tests/ui/field_reassign_with_default.rs:235:13 | LL | let mut f = ImplDropAllCopy::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> tests/ui/field_reassign_with_default.rs:251:13 + --> tests/ui/field_reassign_with_default.rs:252:13 | LL | f.name = name.len(); | ^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments - --> tests/ui/field_reassign_with_default.rs:250:13 + --> tests/ui/field_reassign_with_default.rs:251:13 | LL | let mut f = NoDropAllCopy::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed index 660e9a21b18..b18d8560f6f 100644 --- a/src/tools/clippy/tests/ui/identity_op.fixed +++ b/src/tools/clippy/tests/ui/identity_op.fixed @@ -134,7 +134,7 @@ fn main() { //~^ ERROR: this operation has no effect f(if b { 1 } else { 2 } + 3); //~^ ERROR: this operation has no effect - + const _: i32 = { 2 * 4 } + 3; //~^ ERROR: this operation has no effect const _: i32 = { 1 + 2 * 3 } + 3; diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs index bbef531e9dc..f1f01b42447 100644 --- a/src/tools/clippy/tests/ui/identity_op.rs +++ b/src/tools/clippy/tests/ui/identity_op.rs @@ -134,7 +134,7 @@ fn main() { //~^ ERROR: this operation has no effect f(0 + if b { 1 } else { 2 } + 3); //~^ ERROR: this operation has no effect - + const _: i32 = { 2 * 4 } + 0 + 3; //~^ ERROR: this operation has no effect const _: i32 = 0 + { 1 + 2 * 3 } + 3; diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs index 2ababad7fc7..27ee2f91594 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![feature(inline_const)] #![warn(clippy::indexing_slicing)] // We also check the out_of_bounds_indexing lint here, because it lints similar things and diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr index 06a4defcb93..5f62ec9b556 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr @@ -1,5 +1,5 @@ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:14:20 + --> tests/ui/indexing_slicing_index.rs:16:20 | LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -10,19 +10,19 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error[E0080]: evaluation of `main::{constant#3}` failed - --> tests/ui/indexing_slicing_index.rs:46:14 + --> tests/ui/indexing_slicing_index.rs:48:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant encountered - --> tests/ui/indexing_slicing_index.rs:46:5 + --> tests/ui/indexing_slicing_index.rs:48:5 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:27:5 + --> tests/ui/indexing_slicing_index.rs:29:5 | LL | x[index]; | ^^^^^^^^ @@ -30,7 +30,7 @@ LL | x[index]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:30:5 + --> tests/ui/indexing_slicing_index.rs:32:5 | LL | x[4]; | ^^^^ @@ -39,13 +39,13 @@ LL | x[4]; = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:32:5 + --> tests/ui/indexing_slicing_index.rs:34:5 | LL | x[1 << 3]; | ^^^^^^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:43:14 + --> tests/ui/indexing_slicing_index.rs:45:14 | LL | const { &ARR[idx()] }; | ^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | const { &ARR[idx()] }; = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:46:14 + --> tests/ui/indexing_slicing_index.rs:48:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ @@ -63,13 +63,13 @@ LL | const { &ARR[idx4()] }; = note: the suggestion might not be applicable in constant blocks error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:53:5 + --> tests/ui/indexing_slicing_index.rs:55:5 | LL | y[4]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:56:5 + --> tests/ui/indexing_slicing_index.rs:58:5 | LL | v[0]; | ^^^^ @@ -77,7 +77,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:58:5 + --> tests/ui/indexing_slicing_index.rs:60:5 | LL | v[10]; | ^^^^^ @@ -85,7 +85,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:60:5 + --> tests/ui/indexing_slicing_index.rs:62:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -93,13 +93,13 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:68:5 + --> tests/ui/indexing_slicing_index.rs:70:5 | LL | x[N]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:71:5 + --> tests/ui/indexing_slicing_index.rs:73:5 | LL | v[N]; | ^^^^ @@ -107,7 +107,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:73:5 + --> tests/ui/indexing_slicing_index.rs:75:5 | LL | v[M]; | ^^^^ @@ -115,7 +115,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:77:13 + --> tests/ui/indexing_slicing_index.rs:79:13 | LL | let _ = x[4]; | ^^^^ diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs index bd94a3ada18..6275b6f970a 100644 --- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs +++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs @@ -73,3 +73,5 @@ fn main() { #[allow(clippy::let_underscore_untyped)] let _ = a(); } + +async fn dont_lint_async_prototype(_: u8) {} diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs index 5d94660ec89..1fb252e3f97 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.rs +++ b/src/tools/clippy/tests/ui/manual_let_else.rs @@ -1,3 +1,4 @@ +#![feature(try_blocks)] #![allow(unused_braces, unused_variables, dead_code)] #![allow( clippy::collapsible_else_if, @@ -446,3 +447,12 @@ struct U<T> { w: T, x: T, } + +fn issue12337() { + // We want to generally silence question_mark lints within try blocks, since `?` has different + // behavior to `return`, and question_mark calls into manual_let_else logic, so make sure that + // we still emit a lint for manual_let_else + let _: Option<()> = try { + let v = if let Some(v_some) = g() { v_some } else { return }; + }; +} diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr index b6433fc460c..7012c6b8891 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:27:5 + --> tests/ui/manual_let_else.rs:28:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -8,7 +8,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:30:5 + --> tests/ui/manual_let_else.rs:31:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -26,7 +26,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:37:5 + --> tests/ui/manual_let_else.rs:38:5 | LL | / let v = if let Some(v) = g() { LL | | @@ -47,25 +47,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:49:9 + --> tests/ui/manual_let_else.rs:50:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:51:9 + --> tests/ui/manual_let_else.rs:52:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:56:5 + --> tests/ui/manual_let_else.rs:57:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:60:5 + --> tests/ui/manual_let_else.rs:61:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -83,7 +83,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:68:5 + --> tests/ui/manual_let_else.rs:69:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -101,7 +101,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:76:5 + --> tests/ui/manual_let_else.rs:77:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -121,7 +121,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:85:5 + --> tests/ui/manual_let_else.rs:86:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -141,7 +141,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:94:5 + --> tests/ui/manual_let_else.rs:95:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -168,7 +168,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:110:5 + --> tests/ui/manual_let_else.rs:111:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -190,7 +190,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:121:5 + --> tests/ui/manual_let_else.rs:122:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -217,7 +217,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:137:5 + --> tests/ui/manual_let_else.rs:138:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -239,7 +239,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:148:5 + --> tests/ui/manual_let_else.rs:149:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -257,7 +257,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:156:5 + --> tests/ui/manual_let_else.rs:157:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -278,7 +278,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:166:5 + --> tests/ui/manual_let_else.rs:167:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -299,7 +299,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:176:5 + --> tests/ui/manual_let_else.rs:177:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -328,7 +328,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:194:5 + --> tests/ui/manual_let_else.rs:195:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | @@ -346,7 +346,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:202:5 + --> tests/ui/manual_let_else.rs:203:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | @@ -364,7 +364,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:212:13 + --> tests/ui/manual_let_else.rs:213:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -375,19 +375,19 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:221:5 + --> tests/ui/manual_let_else.rs:222:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:225:5 + --> tests/ui/manual_let_else.rs:226:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:230:5 + --> tests/ui/manual_let_else.rs:231:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | @@ -405,19 +405,19 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:237:5 + --> tests/ui/manual_let_else.rs:238:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:241:5 + --> tests/ui/manual_let_else.rs:242:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:245:5 + --> tests/ui/manual_let_else.rs:246:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -435,7 +435,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:253:5 + --> tests/ui/manual_let_else.rs:254:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -453,7 +453,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:261:5 + --> tests/ui/manual_let_else.rs:262:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> { LL | | @@ -471,7 +471,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:378:5 + --> tests/ui/manual_let_else.rs:379:5 | LL | / let _ = match ff { LL | | @@ -480,5 +480,11 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 30 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:456:9 + | +LL | let v = if let Some(v_some) = g() { v_some } else { return }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` + +error: aborting due to 31 previous errors diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs index 8146091a2bb..c917fa7f2d0 100644 --- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs @@ -1,5 +1,6 @@ -#![warn(clippy::needless_range_loop, clippy::manual_memcpy)] -#![allow(clippy::useless_vec)] +#![warn(clippy::manual_memcpy)] +#![allow(clippy::assigning_clones, clippy::useless_vec, clippy::needless_range_loop)] + //@no-rustfix const LOOP_OFFSET: usize = 5000; @@ -158,6 +159,59 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { //~^ ERROR: it looks like you're manually copying between slices dst[i] = src[i]; } + + // Don't trigger lint for following multi-dimensional arrays + let src = [[0; 5]; 5]; + for i in 0..4 { + dst[i] = src[i + 1][i]; + } + for i in 0..5 { + dst[i] = src[i][i]; + } + for i in 0..5 { + dst[i] = src[i][3]; + } + + let src = [0; 5]; + let mut dst = [[0; 5]; 5]; + for i in 0..5 { + dst[i][i] = src[i]; + } + + let src = [[[0; 5]; 5]; 5]; + let mut dst = [0; 5]; + for i in 0..5 { + dst[i] = src[i][i][i]; + } + for i in 0..5 { + dst[i] = src[i][i][0]; + } + for i in 0..5 { + dst[i] = src[i][0][i]; + } + for i in 0..5 { + dst[i] = src[0][i][i]; + } + for i in 0..5 { + dst[i] = src[0][i][1]; + } + for i in 0..5 { + dst[i] = src[i][0][1]; + } + + // Trigger lint + let src = [[0; 5]; 5]; + let mut dst = [0; 5]; + for i in 0..5 { + //~^ ERROR: it looks like you're manually copying between slices + dst[i] = src[0][i]; + } + + let src = [[[0; 5]; 5]; 5]; + for i in 0..5 { + //~^ ERROR: it looks like you're manually copying between slices + dst[i] = src[0][1][i]; + } } #[warn(clippy::needless_range_loop, clippy::manual_memcpy)] diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr index 55cca1fb584..803053b2db2 100644 --- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -1,5 +1,5 @@ error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:8:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:9:5 | LL | / for i in 0..src.len() { LL | | @@ -12,7 +12,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::manual_memcpy)]` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:15:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:16:5 | LL | / for i in 0..src.len() { LL | | @@ -21,7 +21,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:21:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:22:5 | LL | / for i in 0..src.len() { LL | | @@ -30,7 +30,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:27:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:28:5 | LL | / for i in 11..src.len() { LL | | @@ -39,7 +39,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:33:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:34:5 | LL | / for i in 0..dst.len() { LL | | @@ -48,7 +48,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:47:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:48:5 | LL | / for i in 10..256 { LL | | @@ -64,7 +64,7 @@ LL + dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]); | error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:60:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:61:5 | LL | / for i in 10..LOOP_OFFSET { LL | | @@ -73,7 +73,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:74:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:75:5 | LL | / for i in 0..src_vec.len() { LL | | @@ -82,7 +82,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:104:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:105:5 | LL | / for i in from..from + src.len() { LL | | @@ -91,7 +91,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:109:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:110:5 | LL | / for i in from..from + 3 { LL | | @@ -100,7 +100,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:115:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:116:5 | LL | / for i in 0..5 { LL | | @@ -109,7 +109,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:121:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:122:5 | LL | / for i in 0..0 { LL | | @@ -118,7 +118,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:145:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:146:5 | LL | / for i in 0..4 { LL | | @@ -127,7 +127,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..4]);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:151:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:152:5 | LL | / for i in 0..5 { LL | | @@ -136,7 +136,7 @@ LL | | } | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:157:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:158:5 | LL | / for i in 0..5 { LL | | @@ -145,7 +145,25 @@ LL | | } | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);` error: it looks like you're manually copying between slices - --> tests/ui/manual_memcpy/without_loop_counters.rs:165:5 + --> tests/ui/manual_memcpy/without_loop_counters.rs:205:5 + | +LL | / for i in 0..5 { +LL | | +LL | | dst[i] = src[0][i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0]);` + +error: it looks like you're manually copying between slices + --> tests/ui/manual_memcpy/without_loop_counters.rs:211:5 + | +LL | / for i in 0..5 { +LL | | +LL | | dst[i] = src[0][1][i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0][1]);` + +error: it looks like you're manually copying between slices + --> tests/ui/manual_memcpy/without_loop_counters.rs:219:5 | LL | / for i in 0..src.len() { LL | | @@ -153,5 +171,5 @@ LL | | dst[i] = src[i].clone(); LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);` -error: aborting due to 16 previous errors +error: aborting due to 18 previous errors diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed index 5540029bf6b..e359dfbb98c 100644 --- a/src/tools/clippy/tests/ui/manual_retain.fixed +++ b/src/tools/clippy/tests/ui/manual_retain.fixed @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs index cee641d9d65..931814f08b7 100644 --- a/src/tools/clippy/tests/ui/manual_retain.rs +++ b/src/tools/clippy/tests/ui/manual_retain.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr index c25c804df75..fdbbc53e4df 100644 --- a/src/tools/clippy/tests/ui/manual_retain.stderr +++ b/src/tools/clippy/tests/ui/manual_retain.stderr @@ -1,5 +1,5 @@ error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:25:5 + --> tests/ui/manual_retain.rs:27:5 | LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` @@ -8,43 +8,43 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:26:5 + --> tests/ui/manual_retain.rs:28:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:27:5 + --> tests/ui/manual_retain.rs:29:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:31:5 + --> tests/ui/manual_retain.rs:33:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:32:5 + --> tests/ui/manual_retain.rs:34:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:62:5 + --> tests/ui/manual_retain.rs:64:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:63:5 + --> tests/ui/manual_retain.rs:65:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:64:5 + --> tests/ui/manual_retain.rs:66:5 | LL | / btree_map = btree_map LL | | .into_iter() @@ -53,49 +53,49 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:89:5 + --> tests/ui/manual_retain.rs:91:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:90:5 + --> tests/ui/manual_retain.rs:92:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:91:5 + --> tests/ui/manual_retain.rs:93:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:95:5 + --> tests/ui/manual_retain.rs:97:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:96:5 + --> tests/ui/manual_retain.rs:98:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:126:5 + --> tests/ui/manual_retain.rs:128:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:127:5 + --> tests/ui/manual_retain.rs:129:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:128:5 + --> tests/ui/manual_retain.rs:130:5 | LL | / hash_map = hash_map LL | | .into_iter() @@ -104,133 +104,133 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:152:5 + --> tests/ui/manual_retain.rs:154:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:153:5 + --> tests/ui/manual_retain.rs:155:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:154:5 + --> tests/ui/manual_retain.rs:156:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:158:5 + --> tests/ui/manual_retain.rs:160:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:159:5 + --> tests/ui/manual_retain.rs:161:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:188:5 + --> tests/ui/manual_retain.rs:190:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:200:5 + --> tests/ui/manual_retain.rs:202:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:201:5 + --> tests/ui/manual_retain.rs:203:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:202:5 + --> tests/ui/manual_retain.rs:204:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:206:5 + --> tests/ui/manual_retain.rs:208:5 | LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:207:5 + --> tests/ui/manual_retain.rs:209:5 | LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:229:5 + --> tests/ui/manual_retain.rs:231:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:230:5 + --> tests/ui/manual_retain.rs:232:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:231:5 + --> tests/ui/manual_retain.rs:233:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:288:5 + --> tests/ui/manual_retain.rs:290:5 | LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:292:5 + --> tests/ui/manual_retain.rs:294:5 | LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:309:5 + --> tests/ui/manual_retain.rs:311:5 | LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:310:5 + --> tests/ui/manual_retain.rs:312:5 | LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:311:5 + --> tests/ui/manual_retain.rs:313:5 | LL | vec = vec.into_iter().filter(|&x| x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:314:5 + --> tests/ui/manual_retain.rs:316:5 | LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:315:5 + --> tests/ui/manual_retain.rs:317:5 | LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` error: this expression can be written more simply using `.retain()` - --> tests/ui/manual_retain.rs:316:5 + --> tests/ui/manual_retain.rs:318:5 | LL | vec = vec.into_iter().filter(|x| *x == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` diff --git a/src/tools/clippy/tests/ui/many_single_char_names.rs b/src/tools/clippy/tests/ui/many_single_char_names.rs index 68578340d90..2af45eaab8a 100644 --- a/src/tools/clippy/tests/ui/many_single_char_names.rs +++ b/src/tools/clippy/tests/ui/many_single_char_names.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)] #![warn(clippy::many_single_char_names)] diff --git a/src/tools/clippy/tests/ui/many_single_char_names.stderr b/src/tools/clippy/tests/ui/many_single_char_names.stderr index 131836ef7c8..3b2460b5c07 100644 --- a/src/tools/clippy/tests/ui/many_single_char_names.stderr +++ b/src/tools/clippy/tests/ui/many_single_char_names.stderr @@ -1,5 +1,5 @@ error: 5 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:5:9 + --> tests/ui/many_single_char_names.rs:7:9 | LL | let a: i32; | ^ @@ -14,7 +14,7 @@ LL | let e: i32; = help: to override `-D warnings` add `#[allow(clippy::many_single_char_names)]` error: 6 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:5:9 + --> tests/ui/many_single_char_names.rs:7:9 | LL | let a: i32; | ^ @@ -28,7 +28,7 @@ LL | let f: i32; | ^ error: 5 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:5:9 + --> tests/ui/many_single_char_names.rs:7:9 | LL | let a: i32; | ^ @@ -40,13 +40,13 @@ LL | e => panic!(), | ^ error: 8 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:34:13 + --> tests/ui/many_single_char_names.rs:36:13 | LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} | ^ ^ ^ ^ ^ ^ ^ ^ error: 8 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:38:10 + --> tests/ui/many_single_char_names.rs:40:10 | LL | let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!(); | ^ ^ ^ ^ ^ ^ ^ ^ diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs index 3917bb9e03d..2dccadd9fce 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![feature(custom_inner_attributes)] #![clippy::msrv = "invalid.version"] //~^ ERROR: `invalid.version` is not a valid Rust version diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr index cf0d08a5d21..b4cb1b5713f 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr @@ -1,35 +1,35 @@ error: `invalid.version` is not a valid Rust version - --> tests/ui/min_rust_version_invalid_attr.rs:2:1 + --> tests/ui/min_rust_version_invalid_attr.rs:4:1 | LL | #![clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `invalid.version` is not a valid Rust version - --> tests/ui/min_rust_version_invalid_attr.rs:7:1 + --> tests/ui/min_rust_version_invalid_attr.rs:9:1 | LL | #[clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `clippy::msrv` is defined multiple times - --> tests/ui/min_rust_version_invalid_attr.rs:14:5 + --> tests/ui/min_rust_version_invalid_attr.rs:16:5 | LL | #![clippy::msrv = "1.10.1"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first definition found here - --> tests/ui/min_rust_version_invalid_attr.rs:12:5 + --> tests/ui/min_rust_version_invalid_attr.rs:14:5 | LL | #![clippy::msrv = "1.40"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `clippy::msrv` is defined multiple times - --> tests/ui/min_rust_version_invalid_attr.rs:19:9 + --> tests/ui/min_rust_version_invalid_attr.rs:21:9 | LL | #![clippy::msrv = "1.0.0"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first definition found here - --> tests/ui/min_rust_version_invalid_attr.rs:18:9 + --> tests/ui/min_rust_version_invalid_attr.rs:20:9 | LL | #![clippy::msrv = "1"] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.rs b/src/tools/clippy/tests/ui/mixed_attributes_style.rs new file mode 100644 index 00000000000..ad93e3019fa --- /dev/null +++ b/src/tools/clippy/tests/ui/mixed_attributes_style.rs @@ -0,0 +1,39 @@ +#![warn(clippy::mixed_attributes_style)] + +#[allow(unused)] //~ ERROR: item has both inner and outer attributes +fn foo1() { + #![allow(unused)] +} + +#[allow(unused)] +#[allow(unused)] +fn foo2() {} + +fn foo3() { + #![allow(unused)] + #![allow(unused)] +} + +/// linux +//~^ ERROR: item has both inner and outer attributes +fn foo4() { + //! windows +} + +/// linux +/// windows +fn foo5() {} + +fn foo6() { + //! linux + //! windows +} + +#[allow(unused)] //~ ERROR: item has both inner and outer attributes +mod bar { + #![allow(unused)] +} + +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr new file mode 100644 index 00000000000..d1d5cd3f47f --- /dev/null +++ b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr @@ -0,0 +1,30 @@ +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:3:1 + | +LL | / #[allow(unused)] +LL | | fn foo1() { +LL | | #![allow(unused)] + | |_____________________^ + | + = note: `-D clippy::mixed-attributes-style` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]` + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:17:1 + | +LL | / /// linux +LL | | +LL | | fn foo4() { +LL | | //! windows + | |_______________^ + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:32:1 + | +LL | / #[allow(unused)] +LL | | mod bar { +LL | | #![allow(unused)] + | |_____________________^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs index 72a171119f3..288b003405d 100644 --- a/src/tools/clippy/tests/ui/mut_mut.rs +++ b/src/tools/clippy/tests/ui/mut_mut.rs @@ -1,4 +1,6 @@ //@aux-build:proc_macros.rs +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::mut_mut)] #![allow(unused)] #![allow( diff --git a/src/tools/clippy/tests/ui/mut_mut.stderr b/src/tools/clippy/tests/ui/mut_mut.stderr index 810c0c96743..73f2410a252 100644 --- a/src/tools/clippy/tests/ui/mut_mut.stderr +++ b/src/tools/clippy/tests/ui/mut_mut.stderr @@ -1,5 +1,5 @@ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:14:11 + --> tests/ui/mut_mut.rs:16:11 | LL | fn fun(x: &mut &mut u32) -> bool { | ^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | fn fun(x: &mut &mut u32) -> bool { = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]` error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:31:17 + --> tests/ui/mut_mut.rs:33:17 | LL | let mut x = &mut &mut 1u32; | ^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:46:25 + --> tests/ui/mut_mut.rs:48:25 | LL | let mut z = inline!(&mut $(&mut 3u32)); | ^ @@ -22,37 +22,37 @@ LL | let mut z = inline!(&mut $(&mut 3u32)); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: this expression mutably borrows a mutable reference. Consider reborrowing - --> tests/ui/mut_mut.rs:33:21 + --> tests/ui/mut_mut.rs:35:21 | LL | let mut y = &mut x; | ^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:37:32 + --> tests/ui/mut_mut.rs:39:32 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:37:16 + --> tests/ui/mut_mut.rs:39:16 | LL | let y: &mut &mut u32 = &mut &mut 2; | ^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:42:37 + --> tests/ui/mut_mut.rs:44:37 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:42:16 + --> tests/ui/mut_mut.rs:44:16 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^^^^^^ error: generally you want to avoid `&mut &mut _` if possible - --> tests/ui/mut_mut.rs:42:21 + --> tests/ui/mut_mut.rs:44:21 | LL | let y: &mut &mut &mut u32 = &mut &mut &mut 2; | ^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/no_effect_replace.rs b/src/tools/clippy/tests/ui/no_effect_replace.rs index e4fd5caae2a..2a940d87fb9 100644 --- a/src/tools/clippy/tests/ui/no_effect_replace.rs +++ b/src/tools/clippy/tests/ui/no_effect_replace.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::no_effect_replace)] fn main() { diff --git a/src/tools/clippy/tests/ui/no_effect_replace.stderr b/src/tools/clippy/tests/ui/no_effect_replace.stderr index ded86c5c5b8..ad2dcd2cc9b 100644 --- a/src/tools/clippy/tests/ui/no_effect_replace.stderr +++ b/src/tools/clippy/tests/ui/no_effect_replace.stderr @@ -1,5 +1,5 @@ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:4:13 + --> tests/ui/no_effect_replace.rs:6:13 | LL | let _ = "12345".replace('1', "1"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,43 +8,43 @@ LL | let _ = "12345".replace('1', "1"); = help: to override `-D warnings` add `#[allow(clippy::no_effect_replace)]` error: replacing text with itself - --> tests/ui/no_effect_replace.rs:7:13 + --> tests/ui/no_effect_replace.rs:9:13 | LL | let _ = "12345".replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:9:13 + --> tests/ui/no_effect_replace.rs:11:13 | LL | let _ = String::new().replace("12", "12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:12:13 + --> tests/ui/no_effect_replace.rs:14:13 | LL | let _ = "12345".replacen('1', "1", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:14:13 + --> tests/ui/no_effect_replace.rs:16:13 | LL | let _ = "12345".replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:16:13 + --> tests/ui/no_effect_replace.rs:18:13 | LL | let _ = String::new().replacen("12", "12", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:23:13 + --> tests/ui/no_effect_replace.rs:25:13 | LL | let _ = "hello".replace(&x.f(), &x.f()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: replacing text with itself - --> tests/ui/no_effect_replace.rs:27:13 + --> tests/ui/no_effect_replace.rs:29:13 | LL | let _ = "hello".replace(&y(), &y()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed index 165702b3041..7d1be412e54 100644 --- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed +++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed @@ -1,4 +1,5 @@ #![allow(clippy::clone_on_copy, unused)] +#![allow(clippy::assigning_clones)] #![no_main] // lint diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs index 3b07dd5ce62..beae05efb2f 100644 --- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs +++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs @@ -1,4 +1,5 @@ #![allow(clippy::clone_on_copy, unused)] +#![allow(clippy::assigning_clones)] #![no_main] // lint diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr index 8eff322fa2d..6bfc99d988b 100644 --- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr +++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr @@ -1,5 +1,5 @@ error: non-canonical implementation of `clone` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:9:29 + --> tests/ui/non_canonical_clone_impl.rs:10:29 | LL | fn clone(&self) -> Self { | _____________________________^ @@ -11,7 +11,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::non_canonical_clone_impl)]` error: unnecessary implementation of `clone_from` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:13:5 + --> tests/ui/non_canonical_clone_impl.rs:14:5 | LL | / fn clone_from(&mut self, source: &Self) { LL | | source.clone(); @@ -20,7 +20,7 @@ LL | | } | |_____^ help: remove it error: non-canonical implementation of `clone` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:80:29 + --> tests/ui/non_canonical_clone_impl.rs:81:29 | LL | fn clone(&self) -> Self { | _____________________________^ @@ -29,7 +29,7 @@ LL | | } | |_____^ help: change this to: `{ *self }` error: unnecessary implementation of `clone_from` on a `Copy` type - --> tests/ui/non_canonical_clone_impl.rs:84:5 + --> tests/ui/non_canonical_clone_impl.rs:85:5 | LL | / fn clone_from(&mut self, source: &Self) { LL | | source.clone(); diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index 908ef6cb2a0..38157116e91 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -1,4 +1,5 @@ //@no-rustfix: overlapping suggestions + #![feature(lint_reasons)] #![allow( unused, @@ -173,3 +174,8 @@ fn issue_5794() { if !b == !c {} //~ ERROR: this boolean expression can be simplified if !b != !c {} //~ ERROR: this boolean expression can be simplified } + +fn issue_12371(x: usize) -> bool { + // Should not warn! + !x != 0 +} diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index 954e2345266..b6af06d845a 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:18:13 + --> tests/ui/nonminimal_bool.rs:19:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -8,43 +8,43 @@ LL | let _ = !true; = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:21:13 + --> tests/ui/nonminimal_bool.rs:22:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:23:13 + --> tests/ui/nonminimal_bool.rs:24:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:25:13 + --> tests/ui/nonminimal_bool.rs:26:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:30:13 + --> tests/ui/nonminimal_bool.rs:31:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:32:13 + --> tests/ui/nonminimal_bool.rs:33:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:34:13 + --> tests/ui/nonminimal_bool.rs:35:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:43:13 + --> tests/ui/nonminimal_bool.rs:44:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:45:13 + --> tests/ui/nonminimal_bool.rs:46:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:47:13 + --> tests/ui/nonminimal_bool.rs:48:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:49:13 + --> tests/ui/nonminimal_bool.rs:50:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:51:13 + --> tests/ui/nonminimal_bool.rs:52:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,43 +109,43 @@ LL | let _ = a != b && c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:82:8 + --> tests/ui/nonminimal_bool.rs:83:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:162:8 + --> tests/ui/nonminimal_bool.rs:163:8 | LL | if !(12 == a) {} | ^^^^^^^^^^ help: try: `12 != a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:163:8 + --> tests/ui/nonminimal_bool.rs:164:8 | LL | if !(a == 12) {} | ^^^^^^^^^^ help: try: `a != 12` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:164:8 + --> tests/ui/nonminimal_bool.rs:165:8 | LL | if !(12 != a) {} | ^^^^^^^^^^ help: try: `12 == a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:165:8 + --> tests/ui/nonminimal_bool.rs:166:8 | LL | if !(a != 12) {} | ^^^^^^^^^^ help: try: `a == 12` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:169:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try: `b != true` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:169:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `b != true` @@ -154,61 +154,61 @@ LL | if !b == true {} = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:169:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:172:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `true != b` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:172:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `true != b` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:172:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:173:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `true == b` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:173:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:173:8 + --> tests/ui/nonminimal_bool.rs:174:8 | LL | if !b == !c {} | ^^^^^^^^ help: try: `b == c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:174:8 + --> tests/ui/nonminimal_bool.rs:175:8 | LL | if !b != !c {} | ^^^^^^^^ help: try: `b != c` diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed index e27c0350d49..bd4be3e5a44 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs index 040a6e920a1..4523c7385df 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr index ede88ba529c..e32c8dacd2f 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:8:13 + --> tests/ui/nonminimal_bool_methods.rs:10:13 | LL | let _ = !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` @@ -8,73 +8,73 @@ LL | let _ = !a.is_some(); = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:10:13 + --> tests/ui/nonminimal_bool_methods.rs:12:13 | LL | let _ = !a.is_none(); | ^^^^^^^^^^^^ help: try: `a.is_some()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:12:13 + --> tests/ui/nonminimal_bool_methods.rs:14:13 | LL | let _ = !b.is_err(); | ^^^^^^^^^^^ help: try: `b.is_ok()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:14:13 + --> tests/ui/nonminimal_bool_methods.rs:16:13 | LL | let _ = !b.is_ok(); | ^^^^^^^^^^ help: try: `b.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:16:13 + --> tests/ui/nonminimal_bool_methods.rs:18:13 | LL | let _ = !(a.is_some() && !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() || c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:17:13 + --> tests/ui/nonminimal_bool_methods.rs:19:13 | LL | let _ = !(a.is_some() || !c); | ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() && c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:18:26 + --> tests/ui/nonminimal_bool_methods.rs:20:26 | LL | let _ = !(!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:19:25 + --> tests/ui/nonminimal_bool_methods.rs:21:25 | LL | let _ = (!c ^ c) || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:20:23 + --> tests/ui/nonminimal_bool_methods.rs:22:23 | LL | let _ = !c ^ c || !a.is_some(); | ^^^^^^^^^^^^ help: try: `a.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:92:8 + --> tests/ui/nonminimal_bool_methods.rs:94:8 | LL | if !res.is_ok() {} | ^^^^^^^^^^^^ help: try: `res.is_err()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:93:8 + --> tests/ui/nonminimal_bool_methods.rs:95:8 | LL | if !res.is_err() {} | ^^^^^^^^^^^^^ help: try: `res.is_ok()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:96:8 + --> tests/ui/nonminimal_bool_methods.rs:98:8 | LL | if !res.is_some() {} | ^^^^^^^^^^^^^^ help: try: `res.is_none()` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool_methods.rs:97:8 + --> tests/ui/nonminimal_bool_methods.rs:99:8 | LL | if !res.is_none() {} | ^^^^^^^^^^^^^^ help: try: `res.is_some()` diff --git a/src/tools/clippy/tests/ui/option_option.rs b/src/tools/clippy/tests/ui/option_option.rs index 9bbdd3aaacc..2f6e4d76145 100644 --- a/src/tools/clippy/tests/ui/option_option.rs +++ b/src/tools/clippy/tests/ui/option_option.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![deny(clippy::option_option)] #![allow(clippy::unnecessary_wraps)] diff --git a/src/tools/clippy/tests/ui/option_option.stderr b/src/tools/clippy/tests/ui/option_option.stderr index 0cd048e400e..76cb9ae944c 100644 --- a/src/tools/clippy/tests/ui/option_option.stderr +++ b/src/tools/clippy/tests/ui/option_option.stderr @@ -1,77 +1,77 @@ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:4:10 + --> tests/ui/option_option.rs:6:10 | LL | const C: Option<Option<i32>> = None; | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui/option_option.rs:1:9 + --> tests/ui/option_option.rs:3:9 | LL | #![deny(clippy::option_option)] | ^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:6:11 + --> tests/ui/option_option.rs:8:11 | LL | static S: Option<Option<i32>> = None; | ^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:9:13 + --> tests/ui/option_option.rs:11:13 | LL | fn input(_: Option<Option<u8>>) {} | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:12:16 + --> tests/ui/option_option.rs:14:16 | LL | fn output() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:17:27 + --> tests/ui/option_option.rs:19:27 | LL | fn output_nested() -> Vec<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:23:30 + --> tests/ui/option_option.rs:25:30 | LL | fn output_nested_nested() -> Option<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:29:8 + --> tests/ui/option_option.rs:31:8 | LL | x: Option<Option<u8>>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:34:23 + --> tests/ui/option_option.rs:36:23 | LL | fn struct_fn() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:41:22 + --> tests/ui/option_option.rs:43:22 | LL | fn trait_fn() -> Option<Option<u8>>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:46:11 + --> tests/ui/option_option.rs:48:11 | LL | Tuple(Option<Option<u8>>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:48:17 + --> tests/ui/option_option.rs:50:17 | LL | Struct { x: Option<Option<u8>> }, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> tests/ui/option_option.rs:90:14 + --> tests/ui/option_option.rs:92:14 | LL | foo: Option<Option<Cow<'a, str>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed index fa15c323540..61d37b8ba3a 100644 --- a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed +++ b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::ptr_as_ptr)] diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.rs b/src/tools/clippy/tests/ui/ptr_as_ptr.rs index 7ab52e63da5..8f2068cd268 100644 --- a/src/tools/clippy/tests/ui/ptr_as_ptr.rs +++ b/src/tools/clippy/tests/ui/ptr_as_ptr.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macros.rs +//@compile-flags: -Zdeduplicate-diagnostics=yes #![warn(clippy::ptr_as_ptr)] diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr index e162f35baf5..e6cd697c7ba 100644 --- a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr +++ b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr @@ -1,5 +1,5 @@ error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:18:33 + --> tests/ui/ptr_as_ptr.rs:19:33 | LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()` @@ -8,37 +8,37 @@ LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::i = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:27:13 + --> tests/ui/ptr_as_ptr.rs:28:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:28:13 + --> tests/ui/ptr_as_ptr.rs:29:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:33:17 + --> tests/ui/ptr_as_ptr.rs:34:17 | LL | let _ = *ptr_ptr as *const i32; | ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:46:25 + --> tests/ui/ptr_as_ptr.rs:47:25 | LL | let _: *const i32 = ptr as *const _; | ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:47:23 + --> tests/ui/ptr_as_ptr.rs:48:23 | LL | let _: *mut i32 = mut_ptr as _; | ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:50:21 + --> tests/ui/ptr_as_ptr.rs:51:21 | LL | let _ = inline!($ptr as *const i32); | ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()` @@ -46,157 +46,157 @@ LL | let _ = inline!($ptr as *const i32); = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:71:13 + --> tests/ui/ptr_as_ptr.rs:72:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:72:13 + --> tests/ui/ptr_as_ptr.rs:73:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:79:9 + --> tests/ui/ptr_as_ptr.rs:80:9 | LL | ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:83:9 + --> tests/ui/ptr_as_ptr.rs:84:9 | LL | std::ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:88:9 + --> tests/ui/ptr_as_ptr.rs:89:9 | LL | ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:92:9 + --> tests/ui/ptr_as_ptr.rs:93:9 | LL | core::ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:97:9 + --> tests/ui/ptr_as_ptr.rs:98:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:101:9 + --> tests/ui/ptr_as_ptr.rs:102:9 | LL | std::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:106:9 + --> tests/ui/ptr_as_ptr.rs:107:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:110:9 + --> tests/ui/ptr_as_ptr.rs:111:9 | LL | core::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:117:9 + --> tests/ui/ptr_as_ptr.rs:118:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:121:9 + --> tests/ui/ptr_as_ptr.rs:122:9 | LL | std::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:126:9 + --> tests/ui/ptr_as_ptr.rs:127:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:130:9 + --> tests/ui/ptr_as_ptr.rs:131:9 | LL | core::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:135:9 + --> tests/ui/ptr_as_ptr.rs:136:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:139:9 + --> tests/ui/ptr_as_ptr.rs:140:9 | LL | std::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:144:9 + --> tests/ui/ptr_as_ptr.rs:145:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:148:9 + --> tests/ui/ptr_as_ptr.rs:149:9 | LL | core::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:155:9 + --> tests/ui/ptr_as_ptr.rs:156:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:159:9 + --> tests/ui/ptr_as_ptr.rs:160:9 | LL | std::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:164:9 + --> tests/ui/ptr_as_ptr.rs:165:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:168:9 + --> tests/ui/ptr_as_ptr.rs:169:9 | LL | core::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:173:9 + --> tests/ui/ptr_as_ptr.rs:174:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:177:9 + --> tests/ui/ptr_as_ptr.rs:178:9 | LL | std::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:182:9 + --> tests/ui/ptr_as_ptr.rs:183:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing its mutability - --> tests/ui/ptr_as_ptr.rs:186:9 + --> tests/ui/ptr_as_ptr.rs:187:9 | LL | core::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed index 2ef006c1419..567472a8af2 100644 --- a/src/tools/clippy/tests/ui/question_mark.fixed +++ b/src/tools/clippy/tests/ui/question_mark.fixed @@ -273,3 +273,13 @@ const fn issue9175(option: Option<()>) -> Option<()> { //stuff Some(()) } + +fn issue12337() -> Option<i32> { + let _: Option<i32> = try { + let Some(_) = Some(42) else { + return None; + }; + 123 + }; + Some(42) +} diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs index c170669823f..abf8c270de8 100644 --- a/src/tools/clippy/tests/ui/question_mark.rs +++ b/src/tools/clippy/tests/ui/question_mark.rs @@ -313,3 +313,13 @@ const fn issue9175(option: Option<()>) -> Option<()> { //stuff Some(()) } + +fn issue12337() -> Option<i32> { + let _: Option<i32> = try { + let Some(_) = Some(42) else { + return None; + }; + 123 + }; + Some(42) +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed index ce5c7f2600b..191f7719904 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed @@ -111,3 +111,20 @@ fn fp_11274() { } m!(|x| println!("{x}")); } + +// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure +// triggers the lint. +fn issue_12358() { + macro_rules! make_closure { + () => { + (|| || {}) + }; + (x) => { + make_closure!()() + }; + } + + // The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically + // different. + make_closure!(x)(); +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs index ac09390e6ea..33a3b90f9cf 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs @@ -111,3 +111,20 @@ fn fp_11274() { } m!(|x| println!("{x}")); } + +// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure +// triggers the lint. +fn issue_12358() { + macro_rules! make_closure { + () => { + (|| || {}) + }; + (x) => { + make_closure!()() + }; + } + + // The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically + // different. + make_closure!(x)(); +} diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed index c578e786426..72fc4cb7333 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.fixed +++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed @@ -20,7 +20,7 @@ struct Person { } pub struct S { - v: String, + v: usize, } fn main() { @@ -59,11 +59,22 @@ fn main() { let _ = RangeToInclusive { end }; external! { - let v = String::new(); + let v = 1; let _ = S { v: v }; } + + let v = 2; + macro_rules! internal { + ($i:ident) => { + let _ = S { v }; + let _ = S { $i: v }; + let _ = S { v: $i }; + let _ = S { $i: $i }; + }; + } + internal!(v); } fn issue_3476() { diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs index d8c2286d5ad..2617d7e7283 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.rs +++ b/src/tools/clippy/tests/ui/redundant_field_names.rs @@ -20,7 +20,7 @@ struct Person { } pub struct S { - v: String, + v: usize, } fn main() { @@ -59,11 +59,22 @@ fn main() { let _ = RangeToInclusive { end: end }; external! { - let v = String::new(); + let v = 1; let _ = S { v: v }; } + + let v = 2; + macro_rules! internal { + ($i:ident) => { + let _ = S { v: v }; + let _ = S { $i: v }; + let _ = S { v: $i }; + let _ = S { $i: $i }; + }; + } + internal!(v); } fn issue_3476() { diff --git a/src/tools/clippy/tests/ui/redundant_field_names.stderr b/src/tools/clippy/tests/ui/redundant_field_names.stderr index 53234736207..38c021fdba3 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.stderr +++ b/src/tools/clippy/tests/ui/redundant_field_names.stderr @@ -44,10 +44,21 @@ LL | let _ = RangeToInclusive { end: end }; | ^^^^^^^^ help: replace it with: `end` error: redundant field names in struct initialization - --> tests/ui/redundant_field_names.rs:88:25 + --> tests/ui/redundant_field_names.rs:71:25 + | +LL | let _ = S { v: v }; + | ^^^^ help: replace it with: `v` +... +LL | internal!(v); + | ------------ in this macro invocation + | + = note: this error originates in the macro `internal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: redundant field names in struct initialization + --> tests/ui/redundant_field_names.rs:99:25 | LL | let _ = RangeFrom { start: start }; | ^^^^^^^^^^^^ help: replace it with: `start` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed index bc055215708..aebf8712dd9 100644 --- a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed +++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed @@ -1,2 +1,4 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #[clippy::cognitive_complexity = "1"] fn main() {} diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs index fdb425363e8..6c18151195f 100644 --- a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs +++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs @@ -1,2 +1,4 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #[clippy::cyclomatic_complexity = "1"] fn main() {} diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr index f9108d169c7..fb51313dab6 100644 --- a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr +++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr @@ -1,5 +1,5 @@ error: usage of deprecated attribute - --> tests/ui/renamed_builtin_attr.rs:1:11 + --> tests/ui/renamed_builtin_attr.rs:3:11 | LL | #[clippy::cyclomatic_complexity = "1"] | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `cognitive_complexity` diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed index 0a49be2dc4f..6df64eb4053 100644 --- a/src/tools/clippy/tests/ui/single_match.fixed +++ b/src/tools/clippy/tests/ui/single_match.fixed @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::single_match)] #![allow( unused, diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs index 4e35d265acb..4f005f4e04f 100644 --- a/src/tools/clippy/tests/ui/single_match.rs +++ b/src/tools/clippy/tests/ui/single_match.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::single_match)] #![allow( unused, diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr index 40af38879ae..651d0b4911d 100644 --- a/src/tools/clippy/tests/ui/single_match.stderr +++ b/src/tools/clippy/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:14:5 + --> tests/ui/single_match.rs:16:5 | LL | / match x { LL | | Some(y) => { @@ -19,7 +19,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:22:5 + --> tests/ui/single_match.rs:24:5 | LL | / match x { LL | | // Note the missing block braces. @@ -31,7 +31,7 @@ LL | | } | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:31:5 + --> tests/ui/single_match.rs:33:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:60:5 + --> tests/ui/single_match.rs:62:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:65:5 + --> tests/ui/single_match.rs:67:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:72:5 + --> tests/ui/single_match.rs:74:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -67,7 +67,7 @@ LL | | }; | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:93:5 + --> tests/ui/single_match.rs:95:5 | LL | / match x { LL | | "test" => println!(), @@ -76,7 +76,7 @@ LL | | } | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:106:5 + --> tests/ui/single_match.rs:108:5 | LL | / match x { LL | | Foo::A => println!(), @@ -85,7 +85,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:112:5 + --> tests/ui/single_match.rs:114:5 | LL | / match x { LL | | FOO_C => println!(), @@ -94,7 +94,7 @@ LL | | } | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:117:5 + --> tests/ui/single_match.rs:119:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -103,7 +103,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:123:5 + --> tests/ui/single_match.rs:125:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -112,7 +112,7 @@ LL | | } | |_____^ help: try: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:140:5 + --> tests/ui/single_match.rs:142:5 | LL | / match x { LL | | Bar::A => println!(), @@ -121,7 +121,7 @@ LL | | } | |_____^ help: try: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:148:5 + --> tests/ui/single_match.rs:150:5 | LL | / match x { LL | | None => println!(), @@ -130,7 +130,7 @@ LL | | }; | |_____^ help: try: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:170:5 + --> tests/ui/single_match.rs:172:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -139,7 +139,7 @@ LL | | } | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:176:5 + --> tests/ui/single_match.rs:178:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -148,7 +148,7 @@ LL | | } | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:182:5 + --> tests/ui/single_match.rs:184:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -157,7 +157,7 @@ LL | | } | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:254:5 + --> tests/ui/single_match.rs:256:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -177,7 +177,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:262:5 + --> tests/ui/single_match.rs:264:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed index f3b1de3b44f..2970f5485fa 100644 --- a/src/tools/clippy/tests/ui/single_match_else.fixed +++ b/src/tools/clippy/tests/ui/single_match_else.fixed @@ -1,4 +1,6 @@ //@aux-build: proc_macros.rs +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs index ddee2e42ec2..26974b2a48a 100644 --- a/src/tools/clippy/tests/ui/single_match_else.rs +++ b/src/tools/clippy/tests/ui/single_match_else.rs @@ -1,4 +1,6 @@ //@aux-build: proc_macros.rs +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] extern crate proc_macros; diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr index 63c733e9a7a..48c74c0caea 100644 --- a/src/tools/clippy/tests/ui/single_match_else.stderr +++ b/src/tools/clippy/tests/ui/single_match_else.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:16:13 + --> tests/ui/single_match_else.rs:18:13 | LL | let _ = match ExprNode::Butterflies { | _____________^ @@ -22,7 +22,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:81:5 + --> tests/ui/single_match_else.rs:83:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -42,7 +42,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:90:5 + --> tests/ui/single_match_else.rs:92:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -62,7 +62,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:100:5 + --> tests/ui/single_match_else.rs:102:5 | LL | / match Result::<i32, Infallible>::Ok(1) { LL | | Ok(a) => println!("${:?}", a), @@ -82,7 +82,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:109:5 + --> tests/ui/single_match_else.rs:111:5 | LL | / match Cow::from("moo") { LL | | Cow::Owned(a) => println!("${:?}", a), @@ -102,7 +102,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:119:5 + --> tests/ui/single_match_else.rs:121:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -125,7 +125,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:130:5 + --> tests/ui/single_match_else.rs:132:5 | LL | / match bar { LL | | Some(v) => { @@ -149,7 +149,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:142:5 + --> tests/ui/single_match_else.rs:144:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -173,7 +173,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:154:5 + --> tests/ui/single_match_else.rs:156:5 | LL | / match bar { LL | | #[rustfmt::skip] diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed index a7555704fbe..0a734a65d29 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed +++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed @@ -1,4 +1,5 @@ //@aux-build:proc_macro_derive.rs + #![warn(clippy::std_instead_of_core)] #![allow(unused_imports)] @@ -16,12 +17,20 @@ fn std_instead_of_core() { use ::core::hash::Hash; //~^ ERROR: used import from `std` instead of `core` // Don't lint on `env` macro - use std::env; + use core::env; // Multiple imports use core::fmt::{Debug, Result}; //~^ ERROR: used import from `std` instead of `core` + // Multiple imports multiline + #[rustfmt::skip] + use core::{ + //~^ ERROR: used import from `std` instead of `core` + fmt::Write as _, + ptr::read_unaligned, + }; + // Function calls let ptr = core::ptr::null::<u32>(); //~^ ERROR: used import from `std` instead of `core` diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs index af7f3399f49..c12c459c7eb 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.rs +++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macro_derive.rs + #![warn(clippy::std_instead_of_core)] #![allow(unused_imports)] @@ -22,6 +23,14 @@ fn std_instead_of_core() { use std::fmt::{Debug, Result}; //~^ ERROR: used import from `std` instead of `core` + // Multiple imports multiline + #[rustfmt::skip] + use std::{ + //~^ ERROR: used import from `std` instead of `core` + fmt::Write as _, + ptr::read_unaligned, + }; + // Function calls let ptr = std::ptr::null::<u32>(); //~^ ERROR: used import from `std` instead of `core` diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr index 30dd49dc268..ee42b474a32 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr +++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:13:9 + --> tests/ui/std_instead_of_core.rs:14:9 | LL | use std::hash::Hasher; | ^^^ help: consider importing the item from `core`: `core` @@ -8,49 +8,61 @@ LL | use std::hash::Hasher; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:16:11 + --> tests/ui/std_instead_of_core.rs:17:11 | LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:22:9 + --> tests/ui/std_instead_of_core.rs:20:9 + | +LL | use std::env; + | ^^^ help: consider importing the item from `core`: `core` + +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core.rs:23:9 | LL | use std::fmt::{Debug, Result}; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:26:15 + --> tests/ui/std_instead_of_core.rs:28:9 + | +LL | use std::{ + | ^^^ help: consider importing the item from `core`: `core` + +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core.rs:35:15 | LL | let ptr = std::ptr::null::<u32>(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:28:21 + --> tests/ui/std_instead_of_core.rs:37:21 | LL | let ptr_mut = ::std::ptr::null_mut::<usize>(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:32:16 + --> tests/ui/std_instead_of_core.rs:41:16 | LL | let cell = std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:34:27 + --> tests/ui/std_instead_of_core.rs:43:27 | LL | let cell_absolute = ::std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:43:9 + --> tests/ui/std_instead_of_core.rs:52:9 | LL | use std::iter::Iterator; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:50:9 + --> tests/ui/std_instead_of_core.rs:59:9 | LL | use std::vec; | ^^^ help: consider importing the item from `alloc`: `alloc` @@ -59,13 +71,13 @@ LL | use std::vec; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:52:9 + --> tests/ui/std_instead_of_core.rs:61:9 | LL | use std::vec::Vec; | ^^^ help: consider importing the item from `alloc`: `alloc` error: used import from `alloc` instead of `core` - --> tests/ui/std_instead_of_core.rs:58:9 + --> tests/ui/std_instead_of_core.rs:67:9 | LL | use alloc::slice::from_ref; | ^^^^^ help: consider importing the item from `core`: `core` @@ -73,5 +85,5 @@ LL | use alloc::slice::from_ref; = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]` -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed index 9d9732307c8..60fde6e22cb 100644 --- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::suspicious_operation_groupings)] #![allow(dead_code, unused_parens, clippy::eq_op)] diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs index 201b8e657f4..ce37148a853 100644 --- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::suspicious_operation_groupings)] #![allow(dead_code, unused_parens, clippy::eq_op)] diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr index 9d1d8a1f34f..7cb066d57e7 100644 --- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr +++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr @@ -1,5 +1,5 @@ error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:15:9 + --> tests/ui/suspicious_operation_groupings.rs:17:9 | LL | self.x == other.y && self.y == other.y && self.z == other.z | ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x` @@ -8,151 +8,151 @@ LL | self.x == other.y && self.y == other.y && self.z == other.z = help: to override `-D warnings` add `#[allow(clippy::suspicious_operation_groupings)]` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:28:20 + --> tests/ui/suspicious_operation_groupings.rs:30:20 | LL | s1.a < s2.a && s1.a < s2.b | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:76:33 + --> tests/ui/suspicious_operation_groupings.rs:78:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:81:19 + --> tests/ui/suspicious_operation_groupings.rs:83:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:81:19 + --> tests/ui/suspicious_operation_groupings.rs:83:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:86:19 + --> tests/ui/suspicious_operation_groupings.rs:88:19 | LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:91:19 + --> tests/ui/suspicious_operation_groupings.rs:93:19 | LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:96:5 + --> tests/ui/suspicious_operation_groupings.rs:98:5 | LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:101:33 + --> tests/ui/suspicious_operation_groupings.rs:103:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:114:20 + --> tests/ui/suspicious_operation_groupings.rs:116:20 | LL | (s1.a * s2.a + s1.b * s1.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:119:34 + --> tests/ui/suspicious_operation_groupings.rs:121:34 | LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:124:38 + --> tests/ui/suspicious_operation_groupings.rs:126:38 | LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:129:39 + --> tests/ui/suspicious_operation_groupings.rs:131:39 | LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:134:42 + --> tests/ui/suspicious_operation_groupings.rs:136:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:134:42 + --> tests/ui/suspicious_operation_groupings.rs:136:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:139:40 + --> tests/ui/suspicious_operation_groupings.rs:141:40 | LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:144:40 + --> tests/ui/suspicious_operation_groupings.rs:146:40 | LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:149:20 + --> tests/ui/suspicious_operation_groupings.rs:151:20 | LL | (s1.a * s2.a + s2.b * s2.b) / 2 | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:154:35 + --> tests/ui/suspicious_operation_groupings.rs:156:35 | LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:159:29 + --> tests/ui/suspicious_operation_groupings.rs:161:29 | LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:164:17 + --> tests/ui/suspicious_operation_groupings.rs:166:17 | LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:173:77 + --> tests/ui/suspicious_operation_groupings.rs:175:77 | LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:187:25 + --> tests/ui/suspicious_operation_groupings.rs:189:25 | LL | s1.a <= s2.a && s1.a <= s2.b | ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:193:23 + --> tests/ui/suspicious_operation_groupings.rs:195:23 | LL | if s1.a < s2.a && s1.a < s2.b { | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:200:48 + --> tests/ui/suspicious_operation_groupings.rs:202:48 | LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) | ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:205:27 + --> tests/ui/suspicious_operation_groupings.rs:207:27 | LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) | ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b` diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed index bbde25b0a88..a6ed59d49c5 100644 --- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed +++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed @@ -27,4 +27,18 @@ fn main() { } //~^^^^ ERROR: initializer for `thread_local` value can be made `const` //~^^^ ERROR: initializer for `thread_local` value can be made `const` + + thread_local! { + static PEEL_ME: i32 = const { 1 }; + //~^ ERROR: initializer for `thread_local` value can be made `const` + static PEEL_ME_MANY: i32 = const { { let x = 1; x * x } }; + //~^ ERROR: initializer for `thread_local` value can be made `const` + } +} + +#[clippy::msrv = "1.58"] +fn f() { + thread_local! { + static TLS: i32 = 1; + } } diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs index 3d7aacf2f09..3f0159c5806 100644 --- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs +++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs @@ -27,4 +27,18 @@ fn main() { } //~^^^^ ERROR: initializer for `thread_local` value can be made `const` //~^^^ ERROR: initializer for `thread_local` value can be made `const` + + thread_local! { + static PEEL_ME: i32 = { 1 }; + //~^ ERROR: initializer for `thread_local` value can be made `const` + static PEEL_ME_MANY: i32 = { let x = 1; x * x }; + //~^ ERROR: initializer for `thread_local` value can be made `const` + } +} + +#[clippy::msrv = "1.58"] +fn f() { + thread_local! { + static TLS: i32 = 1; + } } diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr index 9ee52fbbb31..b4f8bd822b0 100644 --- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr +++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr @@ -25,5 +25,17 @@ error: initializer for `thread_local` value can be made `const` LL | static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }` -error: aborting due to 4 previous errors +error: initializer for `thread_local` value can be made `const` + --> tests/ui/thread_local_initializer_can_be_made_const.rs:32:31 + | +LL | static PEEL_ME: i32 = { 1 }; + | ^^^^^ help: replace with: `const { 1 }` + +error: initializer for `thread_local` value can be made `const` + --> tests/ui/thread_local_initializer_can_be_made_const.rs:34:36 + | +LL | static PEEL_ME_MANY: i32 = { let x = 1; x * x }; + | ^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { { let x = 1; x * x } }` + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 08b8e786611..2365695d691 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -82,3 +82,10 @@ fn issue_10449() { let _x: u8 = unsafe { *(f as *const u8) }; } + +// Pointers cannot be cast to integers in const contexts +const fn issue_12402<P>(ptr: *const P) { + unsafe { transmute::<*const i32, usize>(&42i32) }; + unsafe { transmute::<fn(*const P), usize>(issue_12402) }; + let _ = unsafe { transmute::<_, usize>(ptr) }; +} diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 92eb765e5f9..cd1607b4c19 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -82,3 +82,10 @@ fn issue_10449() { let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) }; } + +// Pointers cannot be cast to integers in const contexts +const fn issue_12402<P>(ptr: *const P) { + unsafe { transmute::<*const i32, usize>(&42i32) }; + unsafe { transmute::<fn(*const P), usize>(issue_12402) }; + let _ = unsafe { transmute::<_, usize>(ptr) }; +} diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs index be28ee2da0c..b057dc4e89f 100644 --- a/src/tools/clippy/tests/ui/type_complexity.rs +++ b/src/tools/clippy/tests/ui/type_complexity.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #![warn(clippy::all)] #![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)] #![feature(associated_type_defaults)] diff --git a/src/tools/clippy/tests/ui/type_complexity.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr index 9e27899e4f9..bfbab8647e8 100644 --- a/src/tools/clippy/tests/ui/type_complexity.stderr +++ b/src/tools/clippy/tests/ui/type_complexity.stderr @@ -1,5 +1,5 @@ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:7:12 + --> tests/ui/type_complexity.rs:9:12 | LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,85 +8,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]` error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:10:12 + --> tests/ui/type_complexity.rs:12:12 | LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:14:8 + --> tests/ui/type_complexity.rs:16:8 | LL | f: Vec<Vec<Box<(u32, u32, u32, u32)>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:18:11 + --> tests/ui/type_complexity.rs:20:11 | LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:22:11 + --> tests/ui/type_complexity.rs:24:11 | LL | Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:24:17 + --> tests/ui/type_complexity.rs:26:17 | LL | Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:29:14 + --> tests/ui/type_complexity.rs:31:14 | LL | const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0)))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:31:30 + --> tests/ui/type_complexity.rs:33:30 | LL | fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:36:14 + --> tests/ui/type_complexity.rs:38:14 | LL | const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:38:14 + --> tests/ui/type_complexity.rs:40:14 | LL | type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:40:25 + --> tests/ui/type_complexity.rs:42:25 | LL | fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:42:29 + --> tests/ui/type_complexity.rs:44:29 | LL | fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:55:15 + --> tests/ui/type_complexity.rs:57:15 | LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:60:14 + --> tests/ui/type_complexity.rs:62:14 | LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: very complex type used. Consider factoring parts into `type` definitions - --> tests/ui/type_complexity.rs:64:13 + --> tests/ui/type_complexity.rs:66:13 | LL | let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unknown_attribute.rs b/src/tools/clippy/tests/ui/unknown_attribute.rs index 932f284d5b7..3241742b5d4 100644 --- a/src/tools/clippy/tests/ui/unknown_attribute.rs +++ b/src/tools/clippy/tests/ui/unknown_attribute.rs @@ -1,3 +1,5 @@ +//@compile-flags: -Zdeduplicate-diagnostics=yes + #[clippy::unknown] //~^ ERROR: usage of unknown attribute #[clippy::cognitive_complexity = "1"] diff --git a/src/tools/clippy/tests/ui/unknown_attribute.stderr b/src/tools/clippy/tests/ui/unknown_attribute.stderr index d1f8eeb51ae..b306abe0a9d 100644 --- a/src/tools/clippy/tests/ui/unknown_attribute.stderr +++ b/src/tools/clippy/tests/ui/unknown_attribute.stderr @@ -1,5 +1,5 @@ error: usage of unknown attribute - --> tests/ui/unknown_attribute.rs:1:11 + --> tests/ui/unknown_attribute.rs:3:11 | LL | #[clippy::unknown] | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed index f52d3250339..288541362cd 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed @@ -221,4 +221,10 @@ mod fixable { fn issue_9603() { let _: f32 = -0x400 as f32; } + + // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as + // `*x.pow(2)` which tries to dereference the return value rather than `x`. + fn issue_11968(x: &usize) -> usize { + { *x }.pow(2) + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index dfd8b454e6c..eef3a42e351 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -221,4 +221,10 @@ mod fixable { fn issue_9603() { let _: f32 = -0x400 as f32; } + + // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as + // `*x.pow(2)` which tries to dereference the return value rather than `x`. + fn issue_11968(x: &usize) -> usize { + (*x as usize).pow(2) + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr index 935bb71da32..80fd5c13d81 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr @@ -241,5 +241,11 @@ error: casting to the same type is unnecessary (`f32` -> `f32`) LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()` -error: aborting due to 40 previous errors +error: casting to the same type is unnecessary (`usize` -> `usize`) + --> tests/ui/unnecessary_cast.rs:228:9 + | +LL | (*x as usize).pow(2) + | ^^^^^^^^^^^^^ help: try: `{ *x }` + +error: aborting due to 41 previous errors diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 8c50bcd5b61..06d8f099c33 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -451,6 +451,15 @@ impl Config { self.target_cfg().panic == PanicStrategy::Unwind } + pub fn has_threads(&self) -> bool { + // Wasm targets don't have threads unless `-threads` is in the target + // name, such as `wasm32-wasip1-threads`. + if self.target.starts_with("wasm") { + return self.target.contains("threads"); + } + true + } + pub fn has_asm_support(&self) -> bool { static ASM_SUPPORTED_ARCHS: &[&str] = &[ "x86", "x86_64", "arm", "aarch64", "riscv32", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 6de445a5783..f15761354f7 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -787,6 +787,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-shadow-call-stack", "needs-sanitizer-support", "needs-sanitizer-thread", + "needs-threads", "needs-unwind", "needs-xray", "no-prefer-dynamic", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 39786588150..d7c74038aea 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -85,6 +85,11 @@ pub(super) fn handle_needs( ignore_reason: "ignored when running the resulting test binaries is disabled", }, Need { + name: "needs-threads", + condition: config.has_threads(), + ignore_reason: "ignored on targets without threading support", + }, + Need { name: "needs-unwind", condition: config.can_unwind(), ignore_reason: "ignored on targets without unwinding support", diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index eff76a38d2e..815ac3839df 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -592,3 +592,23 @@ fn ignore_mode() { assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}"))); } } + +#[test] +fn threads_support() { + let threads = [ + ("x86_64-unknown-linux-gnu", true), + ("aarch64-apple-darwin", true), + ("wasm32-unknown-unknown", false), + ("wasm64-unknown-unknown", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1", false), + #[cfg(not(bootstrap))] + ("wasm32-wasip1-threads", true), + ("wasm32-wasi-preview1-threads", true), + ]; + for (target, has_threads) in threads { + let config = cfg().target(target).build(); + assert_eq!(config.has_threads(), has_threads); + assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads) + } +} diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index bfce11a730e..a54e33ae528 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -bfe762e0ed2e95041cc12c02c5565c4368f2cc9f +79d246112dc95bbd67848f7546f3fd1aca516b82 diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 8341fd7648b..805c0580b2f 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -890,7 +890,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { instance, start_abi, &[*func_arg], - Some(&ret_place.into()), + Some(&ret_place), StackPopCleanup::Root { cleanup: true }, )?; diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 4e080f0cc3b..f7edbdb9c5e 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -391,7 +391,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( argv, Scalar::from_u8(sigpipe).into(), ], - Some(&ret_place.into()), + Some(&ret_place), StackPopCleanup::Root { cleanup: true }, )?; } @@ -400,7 +400,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( entry_instance, Abi::Rust, &[argc.into(), argv], - Some(&ret_place.into()), + Some(&ret_place), StackPopCleanup::Root { cleanup: true }, )?; } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index ddefecca597..5e9de3ffb80 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -383,7 +383,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { f: ty::Instance<'tcx>, caller_abi: Abi, args: &[Immediate<Provenance>], - dest: Option<&PlaceTy<'tcx, Provenance>>, + dest: Option<&MPlaceTy<'tcx, Provenance>>, stack_pop: StackPopCleanup, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -401,7 +401,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mir = this.load_mir(f.def, None)?; let dest = match dest { Some(dest) => dest.clone(), - None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?).into(), + None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?), }; this.push_stack_frame(f, mir, &dest, stack_pop)?; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index f226354200f..490fa6f5535 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -945,7 +945,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { instance: ty::Instance<'tcx>, abi: Abi, args: &[FnArg<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -972,7 +972,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn_val: DynSym, abi: Abi, args: &[FnArg<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -985,7 +985,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &mut MiriInterpCx<'mir, 'tcx>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 48dafc40c62..abfa7143a73 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -12,7 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let [flags] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -32,7 +32,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx; @@ -145,7 +145,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let [ptr, flags] = this.check_shim(abi, Abi::Rust, link_name, args)?; @@ -174,7 +174,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `lo.col` is 0-based - add 1 to make it 1-based for the caller. let colno: u32 = u32::try_from(lo.col.0.saturating_add(1)).unwrap_or(0); - let dest = this.force_allocation(dest)?; if let ty::Adt(adt, _) = dest.layout.ty.kind() { if !adt.repr().c() { throw_ub_format!( @@ -191,29 +190,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let filename_alloc = this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut)?; - this.write_immediate(name_alloc.to_ref(this), &this.project_field(&dest, 0)?)?; - this.write_immediate(filename_alloc.to_ref(this), &this.project_field(&dest, 1)?)?; + this.write_immediate(name_alloc.to_ref(this), &this.project_field(dest, 0)?)?; + this.write_immediate(filename_alloc.to_ref(this), &this.project_field(dest, 1)?)?; } 1 => { this.write_scalar( Scalar::from_target_usize(name.len().try_into().unwrap(), this), - &this.project_field(&dest, 0)?, + &this.project_field(dest, 0)?, )?; this.write_scalar( Scalar::from_target_usize(filename.len().try_into().unwrap(), this), - &this.project_field(&dest, 1)?, + &this.project_field(dest, 1)?, )?; } _ => throw_unsup_format!("unknown `miri_resolve_frame` flags {}", flags), } - this.write_scalar(Scalar::from_u32(lineno), &this.project_field(&dest, 2)?)?; - this.write_scalar(Scalar::from_u32(colno), &this.project_field(&dest, 3)?)?; + this.write_scalar(Scalar::from_u32(lineno), &this.project_field(dest, 2)?)?; + this.write_scalar(Scalar::from_u32(colno), &this.project_field(dest, 3)?)?; // Support a 4-field struct for now - this is deprecated // and slated for removal. if num_fields == 5 { - this.write_pointer(fn_ptr, &this.project_field(&dest, 4)?)?; + this.write_pointer(fn_ptr, &this.project_field(dest, 4)?)?; } Ok(()) diff --git a/src/tools/miri/src/shims/ffi_support.rs b/src/tools/miri/src/shims/ffi_support.rs index e628c44a867..6da119e5fa8 100644 --- a/src/tools/miri/src/shims/ffi_support.rs +++ b/src/tools/miri/src/shims/ffi_support.rs @@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn call_external_c_and_store_return<'a>( &mut self, link_name: Symbol, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ptr: CodePtr, libffi_args: Vec<libffi::high::Arg<'a>>, ) -> InterpResult<'tcx, ()> { @@ -205,7 +205,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn call_external_c_fct( &mut self, link_name: Symbol, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, args: &[OpTy<'tcx, Provenance>], ) -> InterpResult<'tcx, bool> { // Get the pointer to the function in the shared object file if it exists. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 4ae607e98da..a25d377f3a7 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -57,7 +57,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -123,7 +123,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Second: functions that return immediately. match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { EmulateForeignItemResult::NeedsJumping => { - trace!("{:?}", this.dump_place(dest)); + trace!("{:?}", this.dump_place(&dest.clone().into())); this.go_to_block(ret); } EmulateForeignItemResult::AlreadyJumped => (), @@ -149,7 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { sym: DynSym, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -401,7 +401,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); @@ -1085,7 +1085,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 4d7f6a6b4e0..865886a7fc1 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -18,7 +18,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, intrinsic_name: &str, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -124,7 +124,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_load( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic: AtomicReadOrd, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -181,7 +181,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_rmw_op( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic_op: AtomicOp, atomic: AtomicRwOrd, ) -> InterpResult<'tcx> { @@ -223,7 +223,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_exchange( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, atomic: AtomicRwOrd, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -240,7 +240,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange_impl( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, can_fail_spuriously: bool, @@ -269,7 +269,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, ) -> InterpResult<'tcx> { @@ -279,7 +279,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn atomic_compare_exchange_weak( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, success: AtomicRwOrd, fail: AtomicReadOrd, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index d4905c22a6a..b388f70bef2 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -61,7 +61,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // The rest jumps to `ret` immediately. this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?; - trace!("{:?}", this.dump_place(dest)); + trace!("{:?}", this.dump_place(&dest.clone().into())); this.go_to_block(ret); Ok(()) } @@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index bb18fba5c98..ddddcdcebd2 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); match intrinsic_name { @@ -40,7 +40,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -167,7 +167,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -255,7 +255,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (a, a_len) = this.operand_to_simd(a)?; let (b, b_len) = this.operand_to_simd(b)?; let (c, c_len) = this.operand_to_simd(c)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, a_len); assert_eq!(dest_len, b_len); @@ -390,7 +390,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (mask, mask_len) = this.operand_to_simd(mask)?; let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); assert_eq!(dest_len, yes_len); @@ -411,7 +411,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [mask, yes, no] = check_arg_count(args)?; let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; let bitmask_len = dest_len.next_multiple_of(8); // The mask must be an integer or an array. @@ -487,7 +487,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -545,7 +545,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; let index = generic_args[2] .expect_const() @@ -582,7 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right, index] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // `index` is an array, not a SIMD type let ty::Array(_, index_len) = index.layout.ty.kind() else { @@ -623,7 +623,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (passthru, passthru_len) = this.operand_to_simd(passthru)?; let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?; let (mask, mask_len) = this.operand_to_simd(mask)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, passthru_len); assert_eq!(dest_len, ptrs_len); @@ -669,7 +669,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (mask, mask_len) = this.operand_to_simd(mask)?; let ptr = this.read_pointer(ptr)?; let (default, default_len) = this.operand_to_simd(default)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); assert_eq!(dest_len, default_len); diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index 65b5838cd14..34b6481dd38 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -28,7 +28,7 @@ pub struct CatchUnwindData<'tcx> { /// The `data` argument for that callback. data: Scalar<Provenance>, /// The return place from the original call to `try`. - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, /// The return block from the original call to `try`. ret: mir::BasicBlock, } @@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn handle_catch_unwind( &mut self, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ret: mir::BasicBlock, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index b5cd18396a2..4ceda809350 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -44,7 +44,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 64094ac307d..6814e0d4283 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index b9215129674..d13ada0f4cf 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); @@ -228,7 +228,7 @@ fn getrandom<'tcx>( ptr: &OpTy<'tcx, Provenance>, len: &OpTy<'tcx, Provenance>, flags: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 66105391c47..ed27066aa6a 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -8,7 +8,7 @@ use crate::*; pub fn futex<'tcx>( this: &mut MiriInterpCx<'_, 'tcx>, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { // The amount of arguments used depends on the type of futex operation. // The full futex syscall takes six arguments (excluding the syscall @@ -179,7 +179,7 @@ pub fn futex<'tcx>( struct Callback<'tcx> { thread: ThreadId, addr_usize: u64, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index ecc07e28a29..3af01eb44d8 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 054e9719b34..dd301f9ee6d 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -843,7 +843,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { cond_op: &OpTy<'tcx, Provenance>, mutex_op: &OpTy<'tcx, Provenance>, abstime_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -883,7 +883,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { active_thread: ThreadId, mutex_id: MutexId, id: CondvarId, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index f56ea06dbe3..9e0baf86cbc 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -27,7 +27,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 1ce385aaaba..5edc18af482 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let id = this.init_once_get_id(init_once_op)?; let flags = this.read_scalar(flags_op)?.to_u32()?; - let pending_place = this.deref_pointer(pending_op)?.into(); + let pending_place = this.deref_pointer(pending_op)?; let context = this.read_pointer(context_op)?; if flags != 0 { @@ -201,7 +201,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // When we are woken up, set the `pending` flag accordingly. struct Callback<'tcx> { init_once_id: InitOnceId, - pending_place: PlaceTy<'tcx, Provenance>, + pending_place: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { @@ -290,7 +290,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { compare_op: &OpTy<'tcx, Provenance>, size_op: &OpTy<'tcx, Provenance>, timeout_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -334,7 +334,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { struct Callback<'tcx> { thread: ThreadId, addr: u64, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { @@ -406,7 +406,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { lock_op: &OpTy<'tcx, Provenance>, timeout_op: &OpTy<'tcx, Provenance>, flags_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar<Provenance>> { let this = self.eval_context_mut(); @@ -453,7 +453,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { condvar_id: CondvarId, lock_id: RwLockId, mode: RwLockMode, - dest: PlaceTy<'tcx, Provenance>, + dest: MPlaceTy<'tcx, Provenance>, } impl<'tcx> VisitProvenance for Callback<'tcx> { diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index fb0b7015127..6c090d877ea 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "aes")?; @@ -138,7 +138,7 @@ fn aes_round<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, state: &OpTy<'tcx, Provenance>, key: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, f: impl Fn(u128, u128) -> u128, ) -> InterpResult<'tcx, ()> { assert_eq!(dest.layout.size, state.layout.size); diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 65de1607595..23c78647b9c 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -21,7 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx")?; @@ -164,7 +164,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (data, data_len) = this.operand_to_simd(data)?; let (control, control_len) = this.operand_to_simd(control)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, data_len); assert_eq!(dest_len, control_len); @@ -199,7 +199,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (data, data_len) = this.operand_to_simd(data)?; let (control, control_len) = this.operand_to_simd(control)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, data_len); assert_eq!(dest_len, control_len); @@ -354,10 +354,10 @@ fn mask_load<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, ptr: &OpTy<'tcx, Provenance>, mask: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (mask, mask_len) = this.operand_to_simd(mask)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, mask_len); diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 9cfee20014f..7cd397625dc 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. @@ -286,11 +286,11 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>( which: FloatBinOp, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -317,11 +317,11 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( which: FloatBinOp, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -414,10 +414,10 @@ fn unary_op_ss<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, which: FloatUnaryOp, op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -437,10 +437,10 @@ fn unary_op_ps<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, which: FloatUnaryOp, op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -462,11 +462,11 @@ fn round_first<'tcx, F: rustc_apfloat::Float>( left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, rounding: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -492,10 +492,10 @@ fn round_all<'tcx, F: rustc_apfloat::Float>( this: &mut crate::MiriInterpCx<'_, 'tcx>, op: &OpTy<'tcx, Provenance>, rounding: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -544,10 +544,10 @@ fn convert_float_to_int<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, op: &OpTy<'tcx, Provenance>, rnd: rustc_apfloat::Round, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // Output must be *signed* integers. assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_))); @@ -587,7 +587,7 @@ fn split_simd_to_128bit_chunks<'tcx>( this: &mut crate::MiriInterpCx<'_, 'tcx>, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult< 'tcx, (u64, u64, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>), @@ -597,7 +597,7 @@ fn split_simd_to_128bit_chunks<'tcx>( let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -636,7 +636,7 @@ fn horizontal_bin_op<'tcx>( saturating: bool, left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (num_chunks, items_per_chunk, left, right, dest) = split_simd_to_128bit_chunks(this, left, right, dest)?; @@ -684,7 +684,7 @@ fn conditional_dot_product<'tcx>( left: &OpTy<'tcx, Provenance>, right: &OpTy<'tcx, Provenance>, imm: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { let (num_chunks, items_per_chunk, left, right, dest) = split_simd_to_128bit_chunks(this, left, right, dest)?; diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index da0db92738f..b8c0dfb1c7f 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -19,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse")?; @@ -198,7 +198,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (left, left_len) = this.operand_to_simd(left)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index b34b93e3739..18ff5d809e3 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -17,7 +17,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse2")?; @@ -46,7 +46,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); @@ -85,7 +85,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are u8x16, dest is u64x2 assert_eq!(left_len, right_len); @@ -122,7 +122,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -223,7 +223,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -306,7 +306,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i16x8, dest is i8x16 assert_eq!(left_len, 8); @@ -337,7 +337,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i16x8, dest is u8x16 assert_eq!(left_len, 8); @@ -367,7 +367,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // left and right are i32x4, dest is i16x8 assert_eq!(left_len, 4); @@ -430,7 +430,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -449,7 +449,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, op_len); @@ -563,7 +563,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, _) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 99a7a4f2f88..5ac30dca79a 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse3")?; diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 32b1fe43c58..16a82eed99b 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -14,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; @@ -34,7 +34,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -70,7 +70,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len, left_len.checked_mul(2).unwrap()); @@ -142,7 +142,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; // Find minimum let mut min_value = u16::MAX; @@ -178,7 +178,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(left_len, dest_len.checked_mul(2).unwrap()); diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 724150fd2fe..dd5d064b20f 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: link_name: Symbol, abi: Abi, args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, + dest: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; @@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(op_len, dest_len); @@ -52,7 +52,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -102,7 +102,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(left_len, right_len); assert_eq!(dest_len.checked_mul(2).unwrap(), left_len); @@ -138,7 +138,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); @@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let (left, left_len) = this.operand_to_simd(left)?; let (right, right_len) = this.operand_to_simd(right)?; - let (dest, dest_len) = this.place_to_simd(dest)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 9f467724565..db0768848fd 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -81,8 +81,10 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> // Add a test env var to do environment communication tests. program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); + // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). - program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into()))); + let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into()); + program.envs.push(("MIRI_TEMP".into(), Some(miri_temp))); let mut config = Config { target: Some(target.to_owned()), diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 6ba39c1f563..304a178dc34 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -1,6 +1,10 @@ //@ignore-target-windows: File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation +// If this test is failing for you locally, you can try +// 1. Deleting the files `/tmp/miri_*` +// 2. Setting `MIRI_TEMP` or `TMPDIR` to a different directory, without the `miri_*` files + #![feature(io_error_more)] #![feature(io_error_uncategorized)] diff --git a/src/tools/opt-dist/src/utils/artifact_size.rs b/src/tools/opt-dist/src/utils/artifact_size.rs index eb1f6bcf21d..b6c453fb40b 100644 --- a/src/tools/opt-dist/src/utils/artifact_size.rs +++ b/src/tools/opt-dist/src/utils/artifact_size.rs @@ -16,7 +16,7 @@ pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> { let root = env.build_artifacts().join("stage2"); let mut files = get_files_from_dir(&root.join("bin"), None)?; - files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?); + files.extend(get_files_from_dir(&root.join("lib"), None)?); files.sort_unstable(); let items: Vec<_> = files diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index b4540f14627..b4ccddda0d8 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -190,7 +190,11 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { let blessed_issues_path = tidy_src.join("issues_blessed.txt"); let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap(); blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap(); - for filename in allowed_issue_names.difference(&remaining_issue_names) { + // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing. + for filename in allowed_issue_names + .difference(&remaining_issue_names) + .map(|s| s.replace(std::path::MAIN_SEPARATOR_STR, "/")) + { write!(blessed_issues_txt, "\"{filename}\",\n").unwrap(); } write!(blessed_issues_txt, "]\n").unwrap(); diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs index 63b07ee4d1a..6415aee6fae 100644 --- a/tests/assembly/targets/targets-pe.rs +++ b/tests/assembly/targets/targets-pe.rs @@ -12,6 +12,9 @@ //@ revisions: aarch64_uwp_windows_msvc //@ [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc //@ [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64 +//@ revisions: arm64ec_pc_windows_msvc +//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc +//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64 //@ revisions: avr_unknown_gnu_atmega328 //@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 //@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr diff --git a/tests/codegen/cffi/c-variadic.rs b/tests/codegen/cffi/c-variadic.rs index 74aed36a8a1..914d1623ed2 100644 --- a/tests/codegen/cffi/c-variadic.rs +++ b/tests/codegen/cffi/c-variadic.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32-bare compiled with panic=abort by default +//@ needs-unwind //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 // diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs new file mode 100644 index 00000000000..f0157e5a106 --- /dev/null +++ b/tests/codegen/dst-offset.rs @@ -0,0 +1,84 @@ +//! This file tests that we correctly generate GEP instructions for DST +//! field offsets. +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 + +#![crate_type = "lib"] + +#![feature(extern_types)] + +use std::ptr::addr_of; + +// Hack to get the correct type for usize +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) +#[no_mangle] +pub fn helper(_: usize) { +} + +struct Dst<T: ?Sized> { + x: u32, + y: u8, + z: T, +} + +// CHECK: @dst_dyn_trait_offset(ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]]) +#[no_mangle] +pub fn dst_dyn_trait_offset(s: &Dst<dyn Drop>) -> &dyn Drop { +// The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable. + +// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[SIZE_PTR]] +// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[ALIGN_PTR]] + +// CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]] +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +// CHECK-LABEL: @dst_slice_offset +#[no_mangle] +pub fn dst_slice_offset(s: &Dst<[u16]>) -> &[u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +#[repr(packed)] +struct PackedDstSlice { + x: u32, + y: u8, + z: [u16], +} + +// CHECK-LABEL: @packed_dst_slice_offset +#[no_mangle] +pub fn packed_dst_slice_offset(s: &PackedDstSlice) -> *const [u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + addr_of!(s.z) +} + +extern { + pub type Extern; +} + +// CHECK-LABEL: @dst_extern +#[no_mangle] +pub fn dst_extern(s: &Dst<Extern>) -> &Extern { +// Computing the alignment of an extern type is currently unsupported and just panics. + +// CHECK: call void @{{.+}}panic + &s.z +} diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index 65d9cf39c4c..b623d492d9d 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -13,7 +13,7 @@ pub fn helper(_: usize) { // CHECK-LABEL: @scalar_layout #[no_mangle] pub fn scalar_layout(s: &(u64, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8 let x = &s.1; witness(&x); // keep variable in an alloca } @@ -22,7 +22,7 @@ pub fn scalar_layout(s: &(u64, ())) { // CHECK-LABEL: @scalarpair_layout #[no_mangle] pub fn scalarpair_layout(s: &(u64, u32, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12 let x = &s.2; witness(&x); // keep variable in an alloca } @@ -34,7 +34,7 @@ pub struct U64x4(u64, u64, u64, u64); // CHECK-LABEL: @vector_layout #[no_mangle] pub fn vector_layout(s: &(U64x4, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32 let x = &s.1; witness(&x); // keep variable in an alloca } diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs index 16e2c7d60b8..9f7d6db5d26 100644 --- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs +++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs @@ -12,7 +12,7 @@ struct DefaultAllocator; // `<DefaultAllocator as Allocator>::Buffer` to be ambiguous, // which caused an ICE with `-Znormalize-docs`. impl<T> Allocator for DefaultAllocator { - //~^ ERROR: type annotations needed + //~^ ERROR: the type parameter `T` is not constrained type Buffer = (); } diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr index 01034018e22..55ab144b924 100644 --- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr +++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr @@ -1,9 +1,9 @@ -error[E0282]: type annotations needed - --> $DIR/not-wf-ambiguous-normalization.rs:14:23 +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/not-wf-ambiguous-normalization.rs:14:6 | LL | impl<T> Allocator for DefaultAllocator { - | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^ unconstrained type parameter error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index a4f60ea2684..3ee4542810c 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -39,7 +39,7 @@ //@ revisions: loongarch64 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch -//@[loongarch64] min-llvm-version: 17 +//@[loongarch64] min-llvm-version: 18 //@ revisions: wasm //@[wasm] compile-flags: --target wasm32-unknown-unknown //@[wasm] needs-llvm-components: webassembly diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs index 80c492e3022..c021bc22348 100644 --- a/tests/ui/abi/extern/extern-call-deep2.rs +++ b/tests/ui/abi/extern/extern-call-deep2.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs index 873f5d2e774..7edf8975ad8 100644 --- a/tests/ui/abi/extern/extern-call-scrub.rs +++ b/tests/ui/abi/extern/extern-call-scrub.rs @@ -4,7 +4,7 @@ // make sure the stack pointers are maintained properly in both // directions -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs index 7f847d55721..42d8d7b1d25 100644 --- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs +++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(rustc_private)] diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 2a308f83731..03d72f2ae2c 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -1,11 +1,8 @@ -error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified +error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified --> $DIR/overlaping-bound-suggestion.rs:7:13 | LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | associated types `Item`, `IntoIter` must be specified - | associated types `Item`, `IntoIter` must be specified + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>` error[E0223]: ambiguous associated type --> $DIR/overlaping-bound-suggestion.rs:7:13 diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs index 3df3f68ab1e..d7fc5d122c3 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.rs +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,8 +11,8 @@ where } impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T { - //~^ type mismatch resolving `<T as Deref>::Target == T` type Item = T; + //~^ type mismatch resolving `<T as Deref>::Target == T` } pub fn main() { diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index 65221718ee6..b871bb51ae3 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,10 +1,10 @@ error[E0271]: type mismatch resolving `<T as Deref>::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:33 + --> $DIR/hr-associated-type-projection-1.rs:14:17 | LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T { - | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | expected this type parameter + | - expected this type parameter +LL | type Item = T; + | ^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `<T as Deref>::Target` diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index acf6bb2810c..f1c8f83e30c 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,23 +1,4 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 - | -LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable` - | -note: required for `<Col as Expression>::SqlType` to implement `IntoNullable` - --> $DIR/issue-38821.rs:9:18 - | -LL | impl<T: NotNull> IntoNullable for T { - | ------- ^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting the associated type - | -LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, - | +++++++++++++++++++++++++++++++++++++++ - -error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:40:1 | LL | pub enum ColumnInsertValue<Col, Expr> where @@ -142,6 +123,25 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting the associated type + | +LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, + | +++++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied + --> $DIR/issue-38821.rs:23:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable` + | +note: required for `<Col as Expression>::SqlType` to implement `IntoNullable` + --> $DIR/issue-38821.rs:9:18 + | +LL | impl<T: NotNull> IntoNullable for T { + | ------- ^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type diff --git a/tests/ui/box/unit/unique-send-2.rs b/tests/ui/box/unit/unique-send-2.rs index 20474fee4d8..d3cbeefab37 100644 --- a/tests/ui/box/unit/unique-send-2.rs +++ b/tests/ui/box/unit/unique-send-2.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 93333e5ef2a..007f9de0331 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 186 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 187 more = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 86df829fe72..cf18503b74b 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -118,7 +118,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -154,7 +154,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/codegen/init-large-type.rs b/tests/ui/codegen/init-large-type.rs index 34b40693ab1..b9fc6612e16 100644 --- a/tests/ui/codegen/init-large-type.rs +++ b/tests/ui/codegen/init-large-type.rs @@ -7,8 +7,7 @@ // optimisation. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support - +//@ needs-threads #![feature(intrinsics)] use std::{mem, thread}; diff --git a/tests/ui/codegen/issue-28950.rs b/tests/ui/codegen/issue-28950.rs index 8e55172af6d..0a706c588d5 100644 --- a/tests/ui/codegen/issue-28950.rs +++ b/tests/ui/codegen/issue-28950.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads +//@ needs-threads //@ compile-flags: -O // Tests that the `vec!` macro does not overflow the stack when it is diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index b1bb75bfe51..48843f7cd18 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -10,17 +10,6 @@ LL | impl TheTrait<usize> for isize {} | = note: define and implement a trait or new type instead -error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/coherence-orphan.rs:20:1 - | -LL | impl !Send for Vec<isize> {} - | ^^^^^^^^^^^^^^^---------- - | | | - | | `Vec` is not defined in the current crate - | impl doesn't use only types from inside the current crate - | - = note: define and implement a trait or new type instead - error[E0046]: not all trait items implemented, missing: `the_fn` --> $DIR/coherence-orphan.rs:10:1 | @@ -45,6 +34,17 @@ LL | impl TheTrait<isize> for TheType {} | = help: implement the missing item: `fn the_fn(&self) { todo!() }` +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-orphan.rs:20:1 + | +LL | impl !Send for Vec<isize> {} + | ^^^^^^^^^^^^^^^---------- + | | | + | | `Vec` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + error: aborting due to 5 previous errors Some errors have detailed explanations: E0046, E0117. diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr index ca9eb801dfc..dc20af77310 100644 --- a/tests/ui/const-generics/issues/issue-68366.full.stderr +++ b/tests/ui/const-generics/issues/issue-68366.full.stderr @@ -1,5 +1,14 @@ +error: `Option<usize>` is forbidden as the type of a const generic parameter + --> $DIR/issue-68366.rs:9:25 + | +LL | struct Collatz<const N: Option<usize>>; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:7 + --> $DIR/issue-68366.rs:12:7 | LL | impl <const N: usize> Collatz<{Some(N)}> {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -8,7 +17,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:6 + --> $DIR/issue-68366.rs:19:6 | LL | impl<const N: usize> Foo {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -16,6 +25,17 @@ LL | impl<const N: usize> Foo {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error: overly complex generic constant + --> $DIR/issue-68366.rs:12:31 + | +LL | impl <const N: usize> Collatz<{Some(N)}> {} + | ^-------^ + | | + | struct/enum construction is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr index ecf24a356de..78e49f46e1a 100644 --- a/tests/ui/const-generics/issues/issue-68366.min.stderr +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/issue-68366.rs:11:37 + --> $DIR/issue-68366.rs:12:37 | LL | impl <const N: usize> Collatz<{Some(N)}> {} | ^ cannot perform const operation using `N` @@ -7,8 +7,17 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {} = help: const parameters may only be used as standalone arguments, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +error: `Option<usize>` is forbidden as the type of a const generic parameter + --> $DIR/issue-68366.rs:9:25 + | +LL | struct Collatz<const N: Option<usize>>; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:7 + --> $DIR/issue-68366.rs:12:7 | LL | impl <const N: usize> Collatz<{Some(N)}> {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -17,7 +26,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {} = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:6 + --> $DIR/issue-68366.rs:19:6 | LL | impl<const N: usize> Foo {} | ^^^^^^^^^^^^^^ unconstrained const parameter @@ -25,6 +34,6 @@ LL | impl<const N: usize> Foo {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs index d3e57a021a6..d9d5e21857b 100644 --- a/tests/ui/const-generics/issues/issue-68366.rs +++ b/tests/ui/const-generics/issues/issue-68366.rs @@ -7,10 +7,12 @@ #![cfg_attr(full, allow(incomplete_features))] struct Collatz<const N: Option<usize>>; +//~^ ERROR: `Option<usize>` is forbidden impl <const N: usize> Collatz<{Some(N)}> {} //~^ ERROR the const parameter //[min]~^^ generic parameters may not be used in const operations +//[full]~^^^ ERROR overly complex struct Foo; diff --git a/tests/ui/coroutine/smoke.rs b/tests/ui/coroutine/smoke.rs index 0ed56982c9b..17d98a52a1c 100644 --- a/tests/ui/coroutine/smoke.rs +++ b/tests/ui/coroutine/smoke.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -//@ ignore-emscripten no threads support +//@ needs-threads //@ compile-flags: --test #![feature(coroutines, coroutine_trait)] diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr index 70bcae1e0ed..3eb6c2946d3 100644 --- a/tests/ui/crate-loading/missing-std.stderr +++ b/tests/ui/crate-loading/missing-std.stderr @@ -8,8 +8,6 @@ LL | extern crate core; = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/cross-crate/cci_capture_clause.rs b/tests/ui/cross-crate/cci_capture_clause.rs index 99736ad185d..73e1020d7cf 100644 --- a/tests/ui/cross-crate/cci_capture_clause.rs +++ b/tests/ui/cross-crate/cci_capture_clause.rs @@ -5,7 +5,7 @@ // that use capture clauses. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads extern crate cci_capture_clause; diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs index 2bc58aea8fc..014ec46f1b9 100644 --- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs +++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass //@ aux-build:proc-macro-helper.rs diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs deleted file mode 100644 index b08e291621f..00000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[diagnostic::non_existing_attribute] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -pub trait Bar { -} - -#[diagnostic::non_existing_attribute(with_option = "foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -struct Foo; - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr deleted file mode 100644 index 38424c13d86..00000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:1:3 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^ - | - = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:7:3 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:1:15 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:7:15 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors; 2 warnings emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs index 95465701bf8..f6957b1448d 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass #[diagnostic::non_existing_attribute] //~^WARN unknown diagnostic attribute diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr index 753077b365e..c073ec9b103 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr @@ -1,5 +1,5 @@ warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:3:15 + --> $DIR/non_existing_attributes_accepted.rs:2:15 | LL | #[diagnostic::non_existing_attribute] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:8:15 + --> $DIR/non_existing_attributes_accepted.rs:7:15 | LL | #[diagnostic::non_existing_attribute(with_option = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs index 884bab2800a..512ef6330e5 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "Message", note = "Note", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs index eb985c062f3..30a85ff2199 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( on(_Self = "&str"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr index 75a701f0b5f..e34b917f67e 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1 | LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | on(_Self = "&str"), = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | parent_label = "in this scope", = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | append_const_msg = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = help: only `message`, `note` and `label` are allowed as options warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -128,7 +128,7 @@ LL | on(_Self = "&str"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -137,7 +137,7 @@ LL | parent_label = "in this scope", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -146,7 +146,7 @@ LL | append_const_msg = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: trait has `()` and `i32` as params - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15 | LL | takes_foo(()); | --------- ^^ trait has `()` and `i32` as params @@ -156,18 +156,18 @@ LL | takes_foo(()); = help: the trait `Foo<i32>` is not implemented for `()` = note: trait has `()` and `i32` as params help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1 | LL | trait Foo<T> {} | ^^^^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22 | LL | fn takes_foo(_: impl Foo<i32>) {} | ^^^^^^^^ required by this bound in `takes_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `(): Bar` is not satisfied - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 | LL | takes_bar(()); | --------- ^^ the trait `Bar` is not implemented for `()` @@ -185,13 +185,13 @@ LL | takes_bar(()); | = help: the trait `Bar` is implemented for `i32` note: required by a bound in `takes_bar` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -227,7 +227,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -245,7 +245,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,7 +254,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -272,7 +272,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -281,7 +281,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 | LL | takes_baz(()); | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} @@ -290,12 +290,12 @@ LL | takes_baz(()); | = help: the trait `Baz` is not implemented for `()` help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `takes_baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 | LL | fn takes_baz(_: impl Baz) {} | ^^^ required by this bound in `takes_baz` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 12fe988170a..b4234066bb1 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(unsupported = "foo")] //~^WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index 11263580b15..dc0c1948236 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 | LL | #[diagnostic::on_unimplemented(message = "Baz")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32 | LL | #[diagnostic::on_unimplemented = "boom"] | ^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"] = help: only `message`, `note` and `label` are allowed as options warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14 | LL | take_foo(1_i32); | -------- ^^^^^ the trait `Foo` is not implemented for `i32` @@ -72,18 +72,18 @@ LL | take_foo(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `take_foo` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21 | LL | fn take_foo(_: impl Foo) {} | ^^^ required by this bound in `take_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 | LL | take_baz(1_i32); | -------- ^^^^^ the trait `Baz` is not implemented for `i32` @@ -100,18 +100,18 @@ LL | take_baz(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `take_baz` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21 | LL | fn take_baz(_: impl Baz) {} | ^^^ required by this bound in `take_baz` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15 | LL | take_boom(1_i32); | --------- ^^^^^ the trait `Boom` is not implemented for `i32` @@ -128,18 +128,18 @@ LL | take_boom(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1 | LL | trait Boom {} | ^^^^^^^^^^ note: required by a bound in `take_boom` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22 | LL | fn take_boom(_: impl Boom) {} | ^^^^ required by this bound in `take_boom` warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Whatever` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19 | LL | take_whatever(1_i32); | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` @@ -156,18 +156,18 @@ LL | take_whatever(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1 | LL | trait Whatever {} | ^^^^^^^^^^^^^^ note: required by a bound in `take_whatever` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26 | LL | fn take_whatever(_: impl Whatever) {} | ^^^^^^^^ required by this bound in `take_whatever` warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {DoesNotExist} - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15 | LL | take_test(()); | --------- ^^ the trait `Test` is not implemented for `()` @@ -184,12 +184,12 @@ LL | take_test(()); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1 | LL | trait Test {} | ^^^^^^^^^^ note: required by a bound in `take_test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 | LL | fn take_test(_: impl Test) {} | ^^^^ required by this bound in `take_test` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs deleted file mode 100644 index 609a840c118..00000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[diagnostic::on_unimplemented(message = "Foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -pub trait Bar { -} - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr deleted file mode 100644 index 719322fa0f5..00000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_on_unimplemented.rs:1:3 - | -LL | #[diagnostic::on_unimplemented(message = "Foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information - = help: add `#![feature(diagnostic_namespace)]` 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/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs index 0893f29c4a3..5b25fb234bc 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( if(Self = "()"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr index e00846da77b..56d125e20e5 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr @@ -1,5 +1,5 @@ warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -8,7 +8,7 @@ LL | if(Self = "()"), = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -17,7 +17,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] | ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -26,7 +26,7 @@ LL | if(Self = "()"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -37,7 +37,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: custom message - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15 | LL | takes_foo(()); | --------- ^^ fallback label @@ -48,12 +48,12 @@ LL | takes_foo(()); = note: custom note = note: fallback note help: this trait has no implementations, consider adding one - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs index 34cdb99c754..a5982f6492c 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr index c72321d4617..93a0d0b3f41 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/multiple_notes.rs:14:15 + --> $DIR/multiple_notes.rs:12:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -10,18 +10,18 @@ LL | takes_foo(()); = note: Baz = note: Boom help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:4:1 + --> $DIR/multiple_notes.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/multiple_notes.rs:10:22 + --> $DIR/multiple_notes.rs:8:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` error[E0277]: Bar - --> $DIR/multiple_notes.rs:16:15 + --> $DIR/multiple_notes.rs:14:15 | LL | takes_bar(()); | --------- ^^ Foo @@ -32,12 +32,12 @@ LL | takes_bar(()); = note: Baz = note: Baz2 help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:8:1 + --> $DIR/multiple_notes.rs:6:1 | LL | trait Bar {} | ^^^^^^^^^ note: required by a bound in `takes_bar` - --> $DIR/multiple_notes.rs:11:22 + --> $DIR/multiple_notes.rs:9:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs index 797edbc9ec5..7ca03127759 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr index de57f7044bf..6b17f40c6dd 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/on_unimplemented_simple.rs:9:15 + --> $DIR/on_unimplemented_simple.rs:7:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -9,12 +9,12 @@ LL | takes_foo(()); = help: the trait `Foo` is not implemented for `()` = note: Baz help: this trait has no implementations, consider adding one - --> $DIR/on_unimplemented_simple.rs:4:1 + --> $DIR/on_unimplemented_simple.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/on_unimplemented_simple.rs:6:22 + --> $DIR/on_unimplemented_simple.rs:4:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs index a7becd2f88f..8c0b8150417 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "first message", label = "first label", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr index d30754dcf10..43ab6bf25a1 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr @@ -1,5 +1,5 @@ warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -10,7 +10,7 @@ LL | message = "second message", = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -19,7 +19,7 @@ LL | label = "second label", | ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -30,7 +30,7 @@ LL | message = "second message", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -41,7 +41,7 @@ LL | label = "second label", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: first message - --> $DIR/report_warning_on_duplicated_options.rs:23:15 + --> $DIR/report_warning_on_duplicated_options.rs:21:15 | LL | takes_foo(()); | --------- ^^ first label @@ -52,12 +52,12 @@ LL | takes_foo(()); = note: custom note = note: second note help: this trait has no implementations, consider adding one - --> $DIR/report_warning_on_duplicated_options.rs:17:1 + --> $DIR/report_warning_on_duplicated_options.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/report_warning_on_duplicated_options.rs:20:22 + --> $DIR/report_warning_on_duplicated_options.rs:18:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/requires_path.rs b/tests/ui/diagnostic_namespace/requires_path.rs index e8d6ca73ad0..4f3a1319caf 100644 --- a/tests/ui/diagnostic_namespace/requires_path.rs +++ b/tests/ui/diagnostic_namespace/requires_path.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic] //~^ERROR cannot find attribute `diagnostic` in this scope pub struct Bar; diff --git a/tests/ui/diagnostic_namespace/requires_path.stderr b/tests/ui/diagnostic_namespace/requires_path.stderr index 5d07d3a22d5..e02aacac8c1 100644 --- a/tests/ui/diagnostic_namespace/requires_path.stderr +++ b/tests/ui/diagnostic_namespace/requires_path.stderr @@ -1,5 +1,5 @@ error: cannot find attribute `diagnostic` in this scope - --> $DIR/requires_path.rs:3:3 + --> $DIR/requires_path.rs:1:3 | LL | #[diagnostic] | ^^^^^^^^^^ diff --git a/tests/ui/duplicate/duplicate-type-parameter.rs b/tests/ui/duplicate/duplicate-type-parameter.rs index 2751b3c8dc0..c2064b423f1 100644 --- a/tests/ui/duplicate/duplicate-type-parameter.rs +++ b/tests/ui/duplicate/duplicate-type-parameter.rs @@ -23,7 +23,6 @@ trait Qux<T,T> {} impl<T,T> Qux<T,T> for Option<T> {} //~^ ERROR the name `T` is already used -//~^^ ERROR the type parameter `T` is not constrained fn main() { } diff --git a/tests/ui/duplicate/duplicate-type-parameter.stderr b/tests/ui/duplicate/duplicate-type-parameter.stderr index 628f898d5c8..f23f2460a8a 100644 --- a/tests/ui/duplicate/duplicate-type-parameter.stderr +++ b/tests/ui/duplicate/duplicate-type-parameter.stderr @@ -54,13 +54,6 @@ LL | impl<T,T> Qux<T,T> for Option<T> {} | | | first use of `T` -error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/duplicate-type-parameter.rs:24:8 - | -LL | impl<T,T> Qux<T,T> for Option<T> {} - | ^ unconstrained type parameter - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0207, E0403. -For more information about an error, try `rustc --explain E0207`. +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 77f351b28ef..71eec4c16fd 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -1,3 +1,11 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/E0374.rs:4:12 + | +LL | struct Foo<T: ?Sized> { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0374.rs:8:1 | @@ -7,14 +15,6 @@ LL | | where T: CoerceUnsized<U> {} | = note: expected a single field to be coerced, none found -error[E0392]: type parameter `T` is never used - --> $DIR/E0374.rs:4:12 - | -LL | struct Foo<T: ?Sized> { - | ^ unused type parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - error: aborting due to 2 previous errors Some errors have detailed explanations: E0374, E0392. diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index d5340022d68..af720bd40e7 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -1,12 +1,3 @@ -error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions - --> $DIR/E0375.rs:10:12 - | -LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions - | - = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced - = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) - error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/E0375.rs:6:8 | @@ -32,6 +23,15 @@ help: the `Box` type always has a statically known size and allocates its conten LL | b: Box<T>, | ++++ + +error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions + --> $DIR/E0375.rs:10:12 + | +LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions + | + = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) + error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0375. diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr index b80e3e798bd..d8005065238 100644 --- a/tests/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr @@ -4,6 +4,91 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self LL | impl<'b, T, U> AsRef2 for Foo<T> | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0309]: the parameter type `U` may not live long enough + --> $DIR/issue-87735.rs:34:21 + | +LL | type Output<'a> = FooRef<'a, U> where Self: 'a; + | -- ^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds... + | | + | the parameter type `U` must be valid for the lifetime `'a` as defined here... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:23:22 + | +LL | struct FooRef<'a, U>(&'a [U]); + | ^^^^^^^ +help: consider adding an explicit lifetime bound + | +LL | type Output<'a> = FooRef<'a, U> where Self: 'a, U: 'a; + | +++++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-87735.rs:31:15 + | +LL | impl<'b, T, U> AsRef2 for Foo<T> + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... +... +LL | T: AsRef2<Output<'b> = &'b [U]>, + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:7:31 + | +LL | type Output<'a> where Self: 'a; + | ^^ +help: consider adding an explicit lifetime bound + | +LL | T: AsRef2<Output<'b> = &'b [U]> + 'b, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-87735.rs:36:31 + | +LL | impl<'b, T, U> AsRef2 for Foo<T> + | -- the parameter type `T` must be valid for the lifetime `'b` as defined here... +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/issue-87735.rs:7:31 + | +LL | type Output<'a> where Self: 'a; + | ^^ +help: consider adding an explicit lifetime bound + | +LL | T: AsRef2<Output<'b> = &'b [U]> + 'b, + | ++++ + +error: lifetime may not live long enough + --> $DIR/issue-87735.rs:37:5 + | +LL | impl<'b, T, U> AsRef2 for Foo<T> + | -- lifetime `'b` defined here +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | -- lifetime `'a` defined here +LL | FooRef(self.0.as_ref2()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-87735.rs:37:12 + | +LL | impl<'b, T, U> AsRef2 for Foo<T> + | -- lifetime `'b` defined here +... +LL | fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + | -- lifetime `'a` defined here +LL | FooRef(self.0.as_ref2()) + | ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +help: `'b` and `'a` must be the same: replace one with the other + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0309. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr index ba87ac9185d..5da3e3ff64a 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88526.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr @@ -4,6 +4,20 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self LL | impl<'q, Q, I, F> A for TestB<Q, F> | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0309]: the parameter type `F` may not live long enough + --> $DIR/issue-88526.rs:16:18 + | +LL | type I<'a> = &'a F; + | -- ^^^^^ ...so that the reference type `&'a F` does not outlive the data it points at + | | + | the parameter type `F` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | type I<'a> = &'a F where F: 'a; + | +++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0309. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/hashmap/hashmap-memory.rs b/tests/ui/hashmap/hashmap-memory.rs index 0b1e09f5344..6db5d2e7bef 100644 --- a/tests/ui/hashmap/hashmap-memory.rs +++ b/tests/ui/hashmap/hashmap-memory.rs @@ -4,7 +4,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unused_mut)] -//@ ignore-emscripten No support for threads +//@ needs-threads /** A somewhat reduced test case to expose some Valgrind issues. diff --git a/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs new file mode 100644 index 00000000000..882497d1015 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs @@ -0,0 +1,18 @@ +//@ check-pass + +// Check that we don't hit a query cycle when: +// 1. Computing generics_of, which requires... +// 2. Calling resolve_bound_vars, which requires... +// 3. Calling associated_items, which requires... +// 4. Calling associated_type_for_impl_trait_in_trait, which requires... +// 5. Computing generics_of, which cycles. + +pub trait Foo<'a> { + type Assoc; + + fn demo<T>(other: T) -> impl Foo<'a, Assoc = Self::Assoc> + where + T: Foo<'a, Assoc = ()>; +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-87340.rs b/tests/ui/impl-trait/issues/issue-87340.rs index 705a4addcb7..b1baaaa6ba5 100644 --- a/tests/ui/impl-trait/issues/issue-87340.rs +++ b/tests/ui/impl-trait/issues/issue-87340.rs @@ -9,6 +9,8 @@ impl<T> X for () { //~^ ERROR `T` is not constrained by the impl trait, self type, or predicates type I = impl Sized; fn f() -> Self::I {} + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr index 8513cb2881e..1be4087be42 100644 --- a/tests/ui/impl-trait/issues/issue-87340.stderr +++ b/tests/ui/impl-trait/issues/issue-87340.stderr @@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<T> X for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-87340.rs:11:23 + | +LL | fn f() -> Self::I {} + | ^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/issue-87340.rs:11:15 + | +LL | fn f() -> Self::I {} + | ^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index c4bdd484fdb..e82f33ad6bc 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -361,14 +361,6 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887> -error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:239:1 - | -LL | impl <T = impl Debug> T {} - | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type - | - = note: either implement a trait on it or create a newtype to wrap it instead - error[E0283]: type annotations needed --> $DIR/where-allowed.rs:46:57 | @@ -389,6 +381,14 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani - impl<Args, F, A> Fn<Args> for Box<F, A> where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized; +error[E0118]: no nominal type found for inherent implementation + --> $DIR/where-allowed.rs:239:1 + | +LL | impl <T = impl Debug> T {} + | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + error[E0599]: no function or associated item named `into_vec` found for slice `[_]` in the current scope --> $DIR/where-allowed.rs:81:5 | diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index 93215326c2f..af427cb5f3e 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -1,3 +1,25 @@ +error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:27:1 + | +LL | impl<T> Foo<T> for [isize;0] { + | ---------------------------- first implementation here +... +LL | impl<T,U> Foo<T> for U { + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` + +error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) +note: required for `([isize; 0], _)` to implement `Bar` + --> $DIR/impl-unused-tps.rs:31:11 + | +LL | impl<T,U> Bar for T { + | - ^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 126 redundant requirements hidden + = note: required for `([isize; 0], _)` to implement `Bar` + error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates --> $DIR/impl-unused-tps.rs:15:8 | @@ -28,28 +50,6 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self LL | impl<T,U,V> Foo<T> for T | ^ unconstrained type parameter -error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:27:1 - | -LL | impl<T> Foo<T> for [isize;0] { - | ---------------------------- first implementation here -... -LL | impl<T,U> Foo<T> for U { - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` - -error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) -note: required for `([isize; 0], _)` to implement `Bar` - --> $DIR/impl-unused-tps.rs:31:11 - | -LL | impl<T,U> Bar for T { - | - ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 126 redundant requirements hidden - = note: required for `([isize; 0], _)` to implement `Bar` - error: aborting due to 7 previous errors Some errors have detailed explanations: E0119, E0207, E0275. diff --git a/tests/ui/imports/auxiliary/aux-issue-121915.rs b/tests/ui/imports/auxiliary/aux-issue-121915.rs new file mode 100644 index 00000000000..7f9f5bda79f --- /dev/null +++ b/tests/ui/imports/auxiliary/aux-issue-121915.rs @@ -0,0 +1 @@ +pub fn item() {} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs new file mode 100644 index 00000000000..d41d190bb58 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --extern aux_issue_121915 --edition 2015 +//@ aux-build: aux-issue-121915.rs + +extern crate aux_issue_121915; + +#[deny(unused_imports)] +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is imported redundantly + aux_issue_121915::item(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr new file mode 100644 index 00000000000..174ed4fb96b --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -0,0 +1,17 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + | +LL | extern crate aux_issue_121915; + | ------------------------------ the item `aux_issue_121915` is already imported here +... +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915-2015.rs:6:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs new file mode 100644 index 00000000000..237acc4af25 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.rs @@ -0,0 +1,9 @@ +//@ compile-flags: --extern aux_issue_121915 --edition 2018 +//@ aux-build: aux-issue-121915.rs + +#[deny(unused_imports)] +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is imported redundantly + aux_issue_121915::item(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-issue-121915.stderr new file mode 100644 index 00000000000..0047d7c3420 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-issue-121915.rs:6:9 + | +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915.rs:4:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs new file mode 100644 index 00000000000..63533480ec1 --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -0,0 +1,40 @@ +//@ compile-flags: --edition 2021 +#![deny(unused_imports)] +#![allow(dead_code)] + +fn test0() { + // Test remove FlatUnused + use std::convert::TryFrom; + //~^ ERROR the item `TryFrom` is imported redundantly + let _ = u32::try_from(5i32); +} + +fn test1() { + // FIXME(yukang) Test remove NestedFullUnused + use std::convert::{TryFrom, TryInto}; + //~^ ERROR the item `TryFrom` is imported redundantly + //~| ERROR the item `TryInto` is imported redundantly + + let _ = u32::try_from(5i32); + let _a: i32 = u32::try_into(5u32).unwrap(); +} + +fn test2() { + // FIXME(yukang): Test remove both redundant and unused + use std::convert::{AsMut, Into}; + //~^ ERROR unused import: `AsMut` + //~| ERROR the item `Into` is imported redundantly + + let _a: u32 = (5u8).into(); +} + +fn test3() { + // Test remove NestedPartialUnused + use std::convert::{From, Infallible}; + //~^ ERROR unused import: `From` + + trait MyTrait {} + impl MyTrait for fn() -> Infallible {} +} + +fn main() {} diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr new file mode 100644 index 00000000000..dbd742f6c78 --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.stderr @@ -0,0 +1,56 @@ +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:7:9 + | +LL | use std::convert::TryFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + | +note: the lint level is defined here + --> $DIR/suggest-remove-issue-121315.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:24 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + +error: the item `TryInto` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:33 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryInto` is already defined here + +error: unused import: `AsMut` + --> $DIR/suggest-remove-issue-121315.rs:24:24 + | +LL | use std::convert::{AsMut, Into}; + | ^^^^^ + +error: the item `Into` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:24:31 + | +LL | use std::convert::{AsMut, Into}; + | ^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Into` is already defined here + +error: unused import: `From` + --> $DIR/suggest-remove-issue-121315.rs:33:24 + | +LL | use std::convert::{From, Infallible}; + | ^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/issues/issue-16560.rs b/tests/ui/issues/issue-16560.rs index 37b536e644d..d9a7aa9101d 100644 --- a/tests/ui/issues/issue-16560.rs +++ b/tests/ui/issues/issue-16560.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::mem; diff --git a/tests/ui/issues/issue-21291.rs b/tests/ui/issues/issue-21291.rs index 357d5520028..06f50ac6996 100644 --- a/tests/ui/issues/issue-21291.rs +++ b/tests/ui/issues/issue-21291.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads // Regression test for unwrapping the result of `join`, issue #21291 diff --git a/tests/ui/issues/issue-22864-2.rs b/tests/ui/issues/issue-22864-2.rs index 1b702f4f509..d98dbeda46b 100644 --- a/tests/ui/issues/issue-22864-2.rs +++ b/tests/ui/issues/issue-22864-2.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads pub fn main() { let f = || || 0; diff --git a/tests/ui/issues/issue-29861.rs b/tests/ui/issues/issue-29861.rs index 58f8eb5362c..875c168185f 100644 --- a/tests/ui/issues/issue-29861.rs +++ b/tests/ui/issues/issue-29861.rs @@ -14,6 +14,7 @@ impl<'a, T: 'a> MakeRef2 for T { } fn foo() -> <String as MakeRef2>::Ref2 { &String::from("foo") } +//~^ ERROR temporary value dropped while borrowed fn main() { println!("{}", foo()); diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr index e7860c19eaa..a25cbf0515d 100644 --- a/tests/ui/issues/issue-29861.stderr +++ b/tests/ui/issues/issue-29861.stderr @@ -4,6 +4,18 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, T: 'a> MakeRef2 for T { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-29861.rs:16:43 + | +LL | fn foo() -> <String as MakeRef2>::Ref2 { &String::from("foo") } + | ^^^^^^^^^^^^^^^^^^^ -- borrow later used here + | | | + | | temporary value is freed at the end of this statement + | creates a temporary value which is freed while still in use + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0716. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 0ad7cbe8efc..7b5be30834b 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -5,5 +5,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr index e7f4a4fa004..f1b6b6ba17e 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.stderr @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator` = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator` -error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_` - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr index 9ecae3e7a2b..588696f3541 100644 --- a/tests/ui/issues/issue-37131.stderr +++ b/tests/ui/issues/issue-37131.stderr @@ -4,8 +4,6 @@ error[E0463]: can't find crate for `std` = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs index 3b62cc73f93..db45d040f79 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.rs +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs @@ -1,5 +1,4 @@ //~ ERROR can't find crate for `core` -//~^ ERROR can't find crate for `compiler_builtins` //@ compile-flags: --target thumbv7em-none-eabihf //@ needs-llvm-components: arm @@ -8,6 +7,5 @@ #![no_std] extern crate cortex_m; -//~^ ERROR can't find crate for `cortex_m` fn main() {} diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr index fcfa2bf119c..1cd65a1b68c 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -4,16 +4,6 @@ error[E0463]: can't find crate for `core` = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error[E0463]: can't find crate for `compiler_builtins` - -error[E0463]: can't find crate for `cortex_m` - --> $DIR/compiler-builtins-error.rs:10:1 - | -LL | extern crate cortex_m; - | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate - -error: requires `sized` lang_item - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-59020.rs b/tests/ui/issues/issue-59020.rs index 5692afe811e..2a34ba52b88 100644 --- a/tests/ui/issues/issue-59020.rs +++ b/tests/ui/issues/issue-59020.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::time::Duration; diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs index eceefa719ec..7bc91ef426b 100644 --- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs +++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs @@ -3,6 +3,6 @@ impl<T> Loop<T> {} //~ ERROR the type parameter `T` is not constrained -type Loop<T> = Loop<T>; +type Loop<T> = Loop<T>; //~ ERROR overflow fn main() {} diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr index b65c84226ce..bcffa02ddd4 100644 --- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr +++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr @@ -4,6 +4,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<T> Loop<T> {} | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0275]: overflow normalizing the type alias `Loop<T>` + --> $DIR/unconstrained-params-in-impl-due-to-overflow.rs:6:16 + | +LL | type Loop<T> = Loop<T>; + | ^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0275. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr index 667bb3ec130..93015bb2bac 100644 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr @@ -1,3 +1,3 @@ 'common' global must have a zero initializer! ptr @TEST -LLVM ERROR: Broken module found, compilation aborted! +rustc-LLVM ERROR: Broken module found, compilation aborted! diff --git a/tests/ui/lint/non_local_definitions.rs b/tests/ui/lint/non_local_definitions.rs index c9aaa049346..bbcc8189871 100644 --- a/tests/ui/lint/non_local_definitions.rs +++ b/tests/ui/lint/non_local_definitions.rs @@ -4,6 +4,7 @@ //@ rustc-env:CARGO=/usr/bin/cargo #![feature(inline_const)] +#![warn(non_local_definitions)] extern crate non_local_macro; diff --git a/tests/ui/lint/non_local_definitions.stderr b/tests/ui/lint/non_local_definitions.stderr index f9f29ec63a8..b9583ae983f 100644 --- a/tests/ui/lint/non_local_definitions.stderr +++ b/tests/ui/lint/non_local_definitions.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:36:5 + --> $DIR/non_local_definitions.rs:37:5 | LL | const Z: () = { | - help: use a const-anon item to suppress this lint: `_` @@ -11,10 +11,14 @@ LL | impl Uto for &Test {} = note: an `impl` definition is non-local if it is nested inside an item and neither the type nor the trait are at the same nesting level as the `impl` block = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/non_local_definitions.rs:7:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:46:5 + --> $DIR/non_local_definitions.rs:47:5 | LL | impl Uto for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +29,7 @@ LL | impl Uto for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:54:9 + --> $DIR/non_local_definitions.rs:55:9 | LL | impl Uto for Test {} | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +40,7 @@ LL | impl Uto for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:63:5 + --> $DIR/non_local_definitions.rs:64:5 | LL | impl Uto2 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +51,7 @@ LL | impl Uto2 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:71:5 + --> $DIR/non_local_definitions.rs:72:5 | LL | impl Uto3 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +62,7 @@ LL | impl Uto3 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:75:5 + --> $DIR/non_local_definitions.rs:76:5 | LL | macro_rules! m0 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +73,7 @@ LL | macro_rules! m0 { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:87:5 + --> $DIR/non_local_definitions.rs:88:5 | LL | macro_rules! m { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +84,7 @@ LL | macro_rules! m { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:90:5 + --> $DIR/non_local_definitions.rs:91:5 | LL | / impl Test { LL | | @@ -94,7 +98,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:96:9 + --> $DIR/non_local_definitions.rs:97:9 | LL | / impl Test { LL | | @@ -108,7 +112,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:105:9 + --> $DIR/non_local_definitions.rs:106:9 | LL | / impl Test { LL | | @@ -122,7 +126,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:114:9 + --> $DIR/non_local_definitions.rs:115:9 | LL | / impl Test { LL | | @@ -136,7 +140,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:122:5 + --> $DIR/non_local_definitions.rs:123:5 | LL | / impl Display for Test { LL | | @@ -152,7 +156,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:129:5 + --> $DIR/non_local_definitions.rs:130:5 | LL | impl dyn Uto5 {} | ^^^^^^^^^^^^^^^^ @@ -163,7 +167,7 @@ LL | impl dyn Uto5 {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:132:5 + --> $DIR/non_local_definitions.rs:133:5 | LL | impl<T: Uto5> Uto5 for Vec<T> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +178,7 @@ LL | impl<T: Uto5> Uto5 for Vec<T> { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:135:5 + --> $DIR/non_local_definitions.rs:136:5 | LL | impl Uto5 for &dyn Uto5 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +189,7 @@ LL | impl Uto5 for &dyn Uto5 {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:138:5 + --> $DIR/non_local_definitions.rs:139:5 | LL | impl Uto5 for *mut Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +200,7 @@ LL | impl Uto5 for *mut Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:141:5 + --> $DIR/non_local_definitions.rs:142:5 | LL | impl Uto5 for *mut [Test] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,7 +211,7 @@ LL | impl Uto5 for *mut [Test] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:144:5 + --> $DIR/non_local_definitions.rs:145:5 | LL | impl Uto5 for [Test; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +222,7 @@ LL | impl Uto5 for [Test; 8] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:147:5 + --> $DIR/non_local_definitions.rs:148:5 | LL | impl Uto5 for (Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +233,7 @@ LL | impl Uto5 for (Test,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:150:5 + --> $DIR/non_local_definitions.rs:151:5 | LL | impl Uto5 for fn(Test) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +244,7 @@ LL | impl Uto5 for fn(Test) -> () {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:153:5 + --> $DIR/non_local_definitions.rs:154:5 | LL | impl Uto5 for fn() -> Test {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -251,7 +255,7 @@ LL | impl Uto5 for fn() -> Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:157:9 + --> $DIR/non_local_definitions.rs:158:9 | LL | impl Uto5 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -262,7 +266,7 @@ LL | impl Uto5 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:164:9 + --> $DIR/non_local_definitions.rs:165:9 | LL | impl Uto5 for &Test {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -273,7 +277,7 @@ LL | impl Uto5 for &Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:171:9 + --> $DIR/non_local_definitions.rs:172:9 | LL | impl Uto5 for &(Test,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -284,7 +288,7 @@ LL | impl Uto5 for &(Test,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:178:9 + --> $DIR/non_local_definitions.rs:179:9 | LL | impl Uto5 for &(Test,Test) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +299,7 @@ LL | impl Uto5 for &(Test,Test) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:186:5 + --> $DIR/non_local_definitions.rs:187:5 | LL | impl Uto5 for *mut InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,7 +310,7 @@ LL | impl Uto5 for *mut InsideMain {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:188:5 + --> $DIR/non_local_definitions.rs:189:5 | LL | impl Uto5 for *mut [InsideMain] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +321,7 @@ LL | impl Uto5 for *mut [InsideMain] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:190:5 + --> $DIR/non_local_definitions.rs:191:5 | LL | impl Uto5 for [InsideMain; 8] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -328,7 +332,7 @@ LL | impl Uto5 for [InsideMain; 8] {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:192:5 + --> $DIR/non_local_definitions.rs:193:5 | LL | impl Uto5 for (InsideMain,) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -339,7 +343,7 @@ LL | impl Uto5 for (InsideMain,) {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:194:5 + --> $DIR/non_local_definitions.rs:195:5 | LL | impl Uto5 for fn(InsideMain) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +354,7 @@ LL | impl Uto5 for fn(InsideMain) -> () {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:196:5 + --> $DIR/non_local_definitions.rs:197:5 | LL | impl Uto5 for fn() -> InsideMain {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +365,7 @@ LL | impl Uto5 for fn() -> InsideMain {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:210:9 + --> $DIR/non_local_definitions.rs:211:9 | LL | / impl Display for InsideMain { LL | | @@ -377,7 +381,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:217:9 + --> $DIR/non_local_definitions.rs:218:9 | LL | / impl InsideMain { LL | | @@ -394,7 +398,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:221:17 + --> $DIR/non_local_definitions.rs:222:17 | LL | macro_rules! m2 { () => { } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -405,7 +409,7 @@ LL | macro_rules! m2 { () => { } }; = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:231:5 + --> $DIR/non_local_definitions.rs:232:5 | LL | impl<T: Uto6> Uto3 for Vec<T> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -416,7 +420,7 @@ LL | impl<T: Uto6> Uto3 for Vec<T> { } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:240:5 + --> $DIR/non_local_definitions.rs:241:5 | LL | impl Uto7 for Test where Local: std::any::Any {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -427,7 +431,7 @@ LL | impl Uto7 for Test where Local: std::any::Any {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:243:5 + --> $DIR/non_local_definitions.rs:244:5 | LL | impl<T> Uto8 for T {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -438,7 +442,7 @@ LL | impl<T> Uto8 for T {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:252:5 + --> $DIR/non_local_definitions.rs:253:5 | LL | / impl Default for UwU<OwO> { LL | | @@ -454,7 +458,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:263:5 + --> $DIR/non_local_definitions.rs:264:5 | LL | / impl From<Cat> for () { LL | | @@ -470,7 +474,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:272:5 + --> $DIR/non_local_definitions.rs:273:5 | LL | / impl AsRef<Cat> for () { LL | | @@ -484,7 +488,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:283:5 + --> $DIR/non_local_definitions.rs:284:5 | LL | / impl PartialEq<B> for G { LL | | @@ -500,7 +504,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:300:5 + --> $DIR/non_local_definitions.rs:301:5 | LL | / impl PartialEq<Dog> for &Dog { LL | | @@ -516,7 +520,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:307:5 + --> $DIR/non_local_definitions.rs:308:5 | LL | / impl PartialEq<()> for Dog { LL | | @@ -532,7 +536,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:314:5 + --> $DIR/non_local_definitions.rs:315:5 | LL | / impl PartialEq<()> for &Dog { LL | | @@ -548,7 +552,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:321:5 + --> $DIR/non_local_definitions.rs:322:5 | LL | / impl PartialEq<Dog> for () { LL | | @@ -564,7 +568,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:343:5 + --> $DIR/non_local_definitions.rs:344:5 | LL | / impl From<Wrap<Wrap<Lion>>> for () { LL | | @@ -580,7 +584,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:350:5 + --> $DIR/non_local_definitions.rs:351:5 | LL | / impl From<()> for Wrap<Lion> { LL | | @@ -596,7 +600,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:363:13 + --> $DIR/non_local_definitions.rs:364:13 | LL | impl MacroTrait for OutsideStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -611,7 +615,7 @@ LL | m!(); = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:373:1 + --> $DIR/non_local_definitions.rs:374:1 | LL | non_local_macro::non_local_impl!(CargoUpdate); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -624,7 +628,7 @@ LL | non_local_macro::non_local_impl!(CargoUpdate); = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation - --> $DIR/non_local_definitions.rs:376:1 + --> $DIR/non_local_definitions.rs:377:1 | LL | non_local_macro::non_local_macro_rules!(my_macro); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs index 75ef0a274ee..5377d5eeae2 100644 --- a/tests/ui/logging-only-prints-once.rs +++ b/tests/ui/logging-only-prints-once.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-windows -//@ ignore-emscripten no threads support +//@ needs-threads use std::cell::Cell; use std::fmt; diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs index a93d7cf35cc..504923a93c2 100644 --- a/tests/ui/lto/lto-still-runs-thread-dtors.rs +++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs @@ -1,7 +1,7 @@ //@ run-pass //@ compile-flags: -C lto //@ no-prefer-dynamic -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/macros/macro-with-braces-in-expr-position.rs b/tests/ui/macros/macro-with-braces-in-expr-position.rs index febfa7241f2..4607349e963 100644 --- a/tests/ui/macros/macro-with-braces-in-expr-position.rs +++ b/tests/ui/macros/macro-with-braces-in-expr-position.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr index 92a54cff7f5..ab86df9c8a5 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -1,15 +1,3 @@ -error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:12:1 - | -LL | impl Marker for OverrideConst { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:18:1 - | -LL | impl Marker for OverrideFn { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0714]: marker traits cannot have associated items --> $DIR/override-item-on-marker-trait.rs:5:5 | @@ -22,6 +10,18 @@ error[E0714]: marker traits cannot have associated items LL | fn do_something() {} | ^^^^^^^^^^^^^^^^^ +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:12:1 + | +LL | impl Marker for OverrideConst { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:18:1 + | +LL | impl Marker for OverrideFn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 4 previous errors Some errors have detailed explanations: E0714, E0715. diff --git a/tests/ui/moves/moves-based-on-type-capture-clause.rs b/tests/ui/moves/moves-based-on-type-capture-clause.rs index baf52ffb515..46759f66468 100644 --- a/tests/ui/moves/moves-based-on-type-capture-clause.rs +++ b/tests/ui/moves/moves-based-on-type-capture-clause.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 9d27cb22ae9..82b61e43f44 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -21,5 +21,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [resolver_for_lowering] getting the resolver for lowering +#0 [resolver_for_lowering_raw] getting the resolver for lowering end of query stack diff --git a/tests/ui/panics/panic-handler-chain.rs b/tests/ui/panics/panic-handler-chain.rs index eb23849f3ac..fea71ad9ec4 100644 --- a/tests/ui/panics/panic-handler-chain.rs +++ b/tests/ui/panics/panic-handler-chain.rs @@ -1,9 +1,8 @@ //@ run-pass //@ needs-unwind +//@ needs-threads #![allow(stable_features)] -//@ ignore-emscripten no threads support - #![feature(std_panic)] use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/tests/ui/panics/panic-task-name-none.rs b/tests/ui/panics/panic-task-name-none.rs index 7eb974bde4c..8695771ff5e 100644 --- a/tests/ui/panics/panic-task-name-none.rs +++ b/tests/ui/panics/panic-task-name-none.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread '<unnamed>' panicked //@ error-pattern:test -//@ ignore-emscripten Needs threads +//@ needs-threads use std::thread; diff --git a/tests/ui/panics/panic-task-name-owned.rs b/tests/ui/panics/panic-task-name-owned.rs index 9a680676dc0..42ae33b5d35 100644 --- a/tests/ui/panics/panic-task-name-owned.rs +++ b/tests/ui/panics/panic-task-name-owned.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'owned name' panicked //@ error-pattern:test -//@ ignore-emscripten Needs threads. +//@ needs-threads use std::thread::Builder; diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 1c71cdacd89..29b0b25a564 100644 --- a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -82,15 +82,6 @@ LL | type W where Self: Eq; = help: add `#![feature(inherent_associated_types)]` 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[E0592]: duplicate definitions with name `W` - --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 - | -LL | type W: Ord where Self: Eq; - | ------ other definition for `W` -... -LL | type W where Self: Eq; - | ^^^^^^ duplicate definitions for `W` - error[E0277]: the trait bound `X: Eq` is not satisfied --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:23 | @@ -119,6 +110,15 @@ LL + #[derive(Eq)] LL | struct X; | +error[E0592]: duplicate definitions with name `W` + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 + | +LL | type W: Ord where Self: Eq; + | ------ other definition for `W` +... +LL | type W where Self: Eq; + | ^^^^^^ duplicate definitions for `W` + error: aborting due to 13 previous errors Some errors have detailed explanations: E0277, E0592, E0658. diff --git a/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs new file mode 100644 index 00000000000..36a7825cec8 --- /dev/null +++ b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs @@ -0,0 +1,35 @@ +// Regression test for issue #89342 and for part of #119924. +//@ check-pass + +struct Expr<const N: u32>; + +trait Trait0 { + fn required(_: Expr<{ + struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + + 0 + }>); +} + +trait Trait1 {} + +impl Trait1 for () +where + [(); { + struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub const STORE: Self = Self; + } + + 0 + }]: +{} + +fn main() {} diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-0.rs b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs new file mode 100644 index 00000000000..107380d33c7 --- /dev/null +++ b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs @@ -0,0 +1,15 @@ +// Regression test for #121607 and for part of issue #119924. +//@ check-pass + +trait Trait { + fn provided() { + pub struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs new file mode 100644 index 00000000000..43530e41a66 --- /dev/null +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -0,0 +1,22 @@ +// Regression test for part of issue #119924. +//@ check-pass + +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + fn required(); +} + +impl const Trait for () { + fn required() { + pub struct Type; + + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs index ed4de58cd23..521eb6a818b 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs @@ -1,3 +1,10 @@ +#![allow(unused)] + +fn test_122112() { + // Make sure we don't ICE if parsing in recovery fails + let _: std::env::temp_dir().join(&self, push: Box<usize>); //~ ERROR expected one of +} + fn main() { let _: std::env::temp_dir().join("foo"); //~ ERROR expected one of } diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr index d03f3ae0283..15c27bb9451 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr @@ -1,5 +1,13 @@ error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` - --> $DIR/recover-colon-instead-of-eq-in-local.rs:2:32 + --> $DIR/recover-colon-instead-of-eq-in-local.rs:5:32 + | +LL | let _: std::env::temp_dir().join(&self, push: Box<usize>); + | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` + | | + | while parsing the type for `_` + +error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` + --> $DIR/recover-colon-instead-of-eq-in-local.rs:9:32 | LL | let _: std::env::temp_dir().join("foo"); | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` @@ -7,5 +15,5 @@ LL | let _: std::env::temp_dir().join("foo"); | while parsing the type for `_` | help: use `=` if you meant to assign -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs index 0dce3c408c2..2f0d85c4bbf 100644 --- a/tests/ui/proc-macro/nested-macro-rules.rs +++ b/tests/ui/proc-macro/nested-macro-rules.rs @@ -5,6 +5,8 @@ //@ edition:2018 #![no_std] // Don't load unnecessary hygiene information from std +#![warn(non_local_definitions)] + extern crate std; extern crate nested_macro_rules; diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 111be882771..270e9161b03 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -12,7 +12,7 @@ LL | | } LL | | } | |_________^ | - ::: $DIR/nested-macro-rules.rs:21:5 + ::: $DIR/nested-macro-rules.rs:23:5 | LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | ---------------------------------------------------------------- in this macro invocation @@ -21,7 +21,11 @@ LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> - = note: `#[warn(non_local_definitions)]` on by default +note: the lint level is defined here + --> $DIR/nested-macro-rules.rs:8:9 + | +LL | #![warn(non_local_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/proc-macro/nested-macro-rules.stdout b/tests/ui/proc-macro/nested-macro-rules.stdout index 829cfdc0c33..5b678554b9e 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stdout +++ b/tests/ui/proc-macro/nested-macro-rules.stdout @@ -25,7 +25,7 @@ PRINT-BANG INPUT (DISPLAY): SecondStruct PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "SecondStruct", - span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#15), + span: $DIR/nested-macro-rules.rs:23:38: 23:50 (#15), }, ] PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {} @@ -36,7 +36,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, Ident { ident: "SecondAttrStruct", - span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#15), + span: $DIR/nested-macro-rules.rs:23:52: 23:68 (#15), }, Group { delimiter: Brace, diff --git a/tests/ui/process-termination/process-termination-blocking-io.rs b/tests/ui/process-termination/process-termination-blocking-io.rs index c21edff25cf..f725a958941 100644 --- a/tests/ui/process-termination/process-termination-blocking-io.rs +++ b/tests/ui/process-termination/process-termination-blocking-io.rs @@ -2,7 +2,7 @@ // https://github.com/fortanix/rust-sgx/issues/109 //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::{net::TcpListener, sync::mpsc, thread}; diff --git a/tests/ui/process-termination/process-termination-simple.rs b/tests/ui/process-termination/process-termination-simple.rs index 63eb2c74706..8f5f185b7f9 100644 --- a/tests/ui/process-termination/process-termination-simple.rs +++ b/tests/ui/process-termination/process-termination-simple.rs @@ -1,7 +1,7 @@ // program should terminate when std::process::exit is called from any thread //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::{process, thread}; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr index 8f374bc4d8f..9ca7b574b13 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr @@ -37,7 +37,19 @@ error[E0207]: the const parameter `host` is not constrained by the impl trait, s = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/derive-const-use.rs:16:14 + | +LL | #[derive_const(Default, PartialEq)] + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0207, E0635. +Some errors have detailed explanations: E0207, E0308, E0635. For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs index 97e89f96fe1..7bead45b35a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs @@ -8,6 +8,8 @@ impl const dyn T { //~^ ERROR inherent impls cannot be `const` //~| ERROR the const parameter `host` is not constrained by the impl trait, self type, or pub const fn new() -> std::sync::Mutex<dyn T> {} + //~^ ERROR mismatched types + //~| ERROR cannot be known at compilation time } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr index 11577d9ec1d..3ff1efb5988 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr @@ -17,6 +17,29 @@ LL | impl const dyn T { = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/span-bug-issue-121418.rs:10:27 + | +LL | pub const fn new() -> std::sync::Mutex<dyn T> {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex<dyn T>`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Mutex<(dyn T + 'static)>` + found unit type `()` + +error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time + --> $DIR/span-bug-issue-121418.rs:10:27 + | +LL | pub const fn new() -> std::sync::Mutex<dyn T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`, which is required by `Mutex<(dyn T + 'static)>: Sized` +note: required because it appears within the type `Mutex<(dyn T + 'static)>` + --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL + = note: the return type of a function must have a statically known size + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0277, E0308. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/structs-enums/ivec-tag.rs b/tests/ui/structs-enums/ivec-tag.rs index 9185a0cbb6e..2a0b6dd1ed4 100644 --- a/tests/ui/structs-enums/ivec-tag.rs +++ b/tests/ui/structs-enums/ivec-tag.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/test-attrs/test-filter-multiple.rs b/tests/ui/test-attrs/test-filter-multiple.rs index 0347ce457ae..05fc022834a 100644 --- a/tests/ui/test-attrs/test-filter-multiple.rs +++ b/tests/ui/test-attrs/test-filter-multiple.rs @@ -3,7 +3,7 @@ //@ run-flags: --test-threads=1 test1 test2 //@ check-run-results //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads #[test] fn test1() {} diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs index 8f75ff309e0..7db7e31d01d 100644 --- a/tests/ui/test-attrs/test-type.rs +++ b/tests/ui/test-attrs/test-type.rs @@ -2,7 +2,7 @@ //@ run-flags: --test-threads=1 //@ check-run-results //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads //@ run-pass #[test] diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs index 17096319d23..fa6a722b291 100644 --- a/tests/ui/thread-local/tls.rs +++ b/tests/ui/thread-local/tls.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads //@ compile-flags: -O //@ ignore-nto Doesn't work without emulated TLS enabled (in LLVM) diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs index 2fb4a6f637a..213fd008cd3 100644 --- a/tests/ui/threads-sendsync/child-outlives-parent.rs +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -2,7 +2,7 @@ // Reported as issue #126, child leaks the string. //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs index 58529e4a788..67790367e27 100644 --- a/tests/ui/threads-sendsync/clone-with-exterior.rs +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs index 589859e60a6..0c37fda8a39 100644 --- a/tests/ui/threads-sendsync/comm.rs +++ b/tests/ui/threads-sendsync/comm.rs @@ -1,13 +1,13 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { child(&tx) }); + let t = thread::spawn(move || { child(&tx) }); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs index 3ff9fb10f24..82abf21df3f 100644 --- a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs +++ b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no processes +//@ needs-threads //@ ignore-sgx no processes use std::cell::RefCell; diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 17e027520c1..1ea862f1e7d 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads +//@ needs-threads //@ ignore-sgx no processes use std::thread; diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs index c848e7b50bb..fbbd6b02a06 100644 --- a/tests/ui/threads-sendsync/issue-29488.rs +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs index 5a9ee015cb9..372ebf2cff9 100644 --- a/tests/ui/threads-sendsync/issue-43733-2.rs +++ b/tests/ui/threads-sendsync/issue-43733-2.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32 +//@ needs-threads //@ dont-check-compiler-stderr #![feature(cfg_target_thread_local, thread_local_internals)] diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs index 12207f4e6aa..c90f60887cf 100644 --- a/tests/ui/threads-sendsync/issue-43733.rs +++ b/tests/ui/threads-sendsync/issue-43733.rs @@ -1,4 +1,4 @@ -//@ ignore-wasm32 +//@ needs-threads #![feature(thread_local)] #![feature(cfg_target_thread_local, thread_local_internals)] diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs index b5e3a20ccde..aa2de51974b 100644 --- a/tests/ui/threads-sendsync/issue-4446.rs +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::channel; use std::thread; diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs index 0f3bf65c441..b8324a8c43f 100644 --- a/tests/ui/threads-sendsync/issue-4448.rs +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::channel; use std::thread; diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs index b7deef0f34d..fa07a4ebc7d 100644 --- a/tests/ui/threads-sendsync/issue-8827.rs +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Receiver}; diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs index 6228f4ba706..6b5907e5c1d 100644 --- a/tests/ui/threads-sendsync/issue-9396.rs +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(deprecated)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{TryRecvError, channel}; use std::thread; diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs index 68c40151281..f5354c60bfc 100644 --- a/tests/ui/threads-sendsync/mpsc_stress.rs +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags:--test -//@ ignore-emscripten +//@ needs-threads use std::sync::mpsc::channel; use std::sync::mpsc::TryRecvError; diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs index 32910c5f7d1..3e1532b3132 100644 --- a/tests/ui/threads-sendsync/send-resource.rs +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -4,7 +4,7 @@ #![allow(non_camel_case_types)] //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 5306d69a7d2..63cf3ff4049 100644 --- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs index 863c22f70d6..e4d83b53f3c 100644 --- a/tests/ui/threads-sendsync/spawn-fn.rs +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs index 9c1b6550d9b..2a7a9e2f497 100644 --- a/tests/ui/threads-sendsync/spawn-types.rs +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(non_camel_case_types)] -//@ ignore-emscripten no threads support +//@ needs-threads /* Make sure we can spawn tasks that take different types of diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs index 2c06fc2837f..c7b344b9f75 100644 --- a/tests/ui/threads-sendsync/spawn.rs +++ b/tests/ui/threads-sendsync/spawn.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs index cfe907ea6d9..8278fec1885 100644 --- a/tests/ui/threads-sendsync/spawn2.rs +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs index 58f1743527c..90a81c1e53b 100644 --- a/tests/ui/threads-sendsync/spawning-with-debug.rs +++ b/tests/ui/threads-sendsync/spawning-with-debug.rs @@ -3,7 +3,7 @@ #![allow(unused_mut)] //@ ignore-windows //@ exec-env:RUST_LOG=debug -//@ ignore-emscripten no threads support +//@ needs-threads // regression test for issue #10405, make sure we don't call println! too soon. diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs index 06ce739b8e5..50f2b591894 100644 --- a/tests/ui/threads-sendsync/task-comm-0.rs +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs index 77ca940e947..41592bd916b 100644 --- a/tests/ui/threads-sendsync/task-comm-1.rs +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs index 6f043b64a09..844652c0dde 100644 --- a/tests/ui/threads-sendsync/task-comm-10.rs +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs index 51f13434435..199082fda96 100644 --- a/tests/ui/threads-sendsync/task-comm-11.rs +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] //@ pretty-expanded FIXME #23616 -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs index cb1fb774f10..7be7ec4c988 100644 --- a/tests/ui/threads-sendsync/task-comm-12.rs +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs index 6b5384e3f08..414e6e0db76 100644 --- a/tests/ui/threads-sendsync/task-comm-13.rs +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs index 65cc750a7c3..54deb221294 100644 --- a/tests/ui/threads-sendsync/task-comm-14.rs +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_parens)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs index 844a18b6158..f487bf3cc84 100644 --- a/tests/ui/threads-sendsync/task-comm-15.rs +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs index 14ef4dd3ede..687322d4dc9 100644 --- a/tests/ui/threads-sendsync/task-comm-17.rs +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 // Issue #922 diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs index 1f2a6406d79..26f3eaf9dc6 100644 --- a/tests/ui/threads-sendsync/task-comm-3.rs +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs index f6e77986e16..d9b322daa66 100644 --- a/tests/ui/threads-sendsync/task-comm-7.rs +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_assignments)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs index f8fe680e5e0..3e617e4a40c 100644 --- a/tests/ui/threads-sendsync/task-comm-9.rs +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs index a4652197afc..d3eca5d371f 100644 --- a/tests/ui/threads-sendsync/task-life-0.rs +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ pretty-expanded FIXME #23616 use std::thread; diff --git a/tests/ui/threads-sendsync/task-spawn-barefn.rs b/tests/ui/threads-sendsync/task-spawn-barefn.rs index 2c957878c95..a97e92206e2 100644 --- a/tests/ui/threads-sendsync/task-spawn-barefn.rs +++ b/tests/ui/threads-sendsync/task-spawn-barefn.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:Ensure that the child thread runs by panicking -//@ ignore-emscripten Needs threads. +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs index 442955421d8..ea1c6a9b108 100644 --- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs index 0f215a2b763..cad10c7a792 100644 --- a/tests/ui/threads-sendsync/task-stderr.rs +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #![feature(internal_output_capture)] diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs index 488cab40140..429a4657314 100644 --- a/tests/ui/threads-sendsync/tcp-stress.rs +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-android needs extra network permissions -//@ ignore-emscripten no threads or sockets support +//@ needs-threads //@ ignore-netbsd system ulimit (Too many open files) //@ ignore-openbsd system ulimit (Too many open files) diff --git a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs index 4b38b9ce2c9..127086743ca 100644 --- a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs +++ b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs @@ -5,7 +5,7 @@ //@ error-pattern:should be a positive integer //@ compile-flags: --test //@ exec-env:RUST_TEST_THREADS=foo -//@ ignore-emscripten +//@ needs-threads #[test] fn do_nothing() {} diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs index 7b7e52abab4..f3ed7890364 100644 --- a/tests/ui/threads-sendsync/threads.rs +++ b/tests/ui/threads-sendsync/threads.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs index 66fd6169db0..84176659412 100644 --- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -1,6 +1,6 @@ //@ run-pass //@ no-prefer-dynamic -//@ ignore-emscripten no threads support +//@ needs-threads static mut HIT: bool = false; diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs index ba5e4698e63..fd764669e7f 100644 --- a/tests/ui/threads-sendsync/tls-init-on-init.rs +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(stable_features)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(thread_local_try_with)] diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs index d9af1caf741..72cee219a0a 100644 --- a/tests/ui/threads-sendsync/tls-try-with.rs +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(stable_features)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(thread_local_try_with)] diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs index ea9e0c7514c..3b1ab57b46e 100644 --- a/tests/ui/threads-sendsync/unwind-resource.rs +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -2,7 +2,7 @@ //@ needs-unwind #![allow(non_camel_case_types)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::mpsc::{channel, Sender}; use std::thread; diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs index 4d89b10af95..99d14bd92ea 100644 --- a/tests/ui/threads-sendsync/yield.rs +++ b/tests/ui/threads-sendsync/yield.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs index b003a70f47e..c965d2fc303 100644 --- a/tests/ui/threads-sendsync/yield1.rs +++ b/tests/ui/threads-sendsync/yield1.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs new file mode 100644 index 00000000000..97dfec80e31 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -0,0 +1,60 @@ +trait Super { + type Assoc; +} +impl Super for () { + type Assoc = u8; +} +trait Sub: Super<Assoc = u16> {} + +trait BoundOnSelf: Sub {} +impl BoundOnSelf for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnParam<T: Sub> {} +impl BoundOnParam<()> for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnAssoc { + type Assoc: Sub; +} +impl BoundOnAssoc for () { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +trait BoundOnGat where Self::Assoc<u8>: Sub { + type Assoc<T>; +} +impl BoundOnGat for u8 { + type Assoc<T> = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +fn trivial_bound() where (): Sub {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +// The following is an edge case where the unsatisfied projection predicate +// `<<u8 as MultiAssoc>::Assoc1<()> as SuperGeneric<u16>>::Assoc == <u8 as MultiAssoc>::Assoc2` +// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied +// super projection, the error's span must be equal to the span of the unsatisfied trait error. +trait SuperGeneric<T> { + type Assoc; +} +trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {} +trait MultiAssoc +where + Self::Assoc1<()>: SubGeneric<Self::Assoc2> +{ + type Assoc1<T>; + type Assoc2; +} +impl SuperGeneric<u16> for () { + type Assoc = u8; +} +impl MultiAssoc for u8 { + type Assoc1<T> = (); + //~^ ERROR the trait bound `(): SubGeneric<u16>` is not satisfied + type Assoc2 = u16; +} + +fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr new file mode 100644 index 00000000000..47535776348 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -0,0 +1,105 @@ +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:10:22 + | +LL | impl BoundOnSelf for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super<Assoc = u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnSelf` + --> $DIR/super-assoc-mismatch.rs:9:20 + | +LL | trait BoundOnSelf: Sub {} + | ^^^ required by this bound in `BoundOnSelf` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:14:27 + | +LL | impl BoundOnParam<()> for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super<Assoc = u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnParam` + --> $DIR/super-assoc-mismatch.rs:13:23 + | +LL | trait BoundOnParam<T: Sub> {} + | ^^^ required by this bound in `BoundOnParam` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:21:18 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super<Assoc = u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnAssoc::Assoc` + --> $DIR/super-assoc-mismatch.rs:18:17 + | +LL | type Assoc: Sub; + | ^^^ required by this bound in `BoundOnAssoc::Assoc` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:29:21 + | +LL | type Assoc<T> = (); + | ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super<Assoc = u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnGat` + --> $DIR/super-assoc-mismatch.rs:25:41 + | +LL | trait BoundOnGat where Self::Assoc<u8>: Sub { + | ^^^ required by this bound in `BoundOnGat` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:33:26 + | +LL | fn trivial_bound() where (): Sub {} + | ^^^^^^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super<Assoc = u16> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): SubGeneric<u16>` is not satisfied + --> $DIR/super-assoc-mismatch.rs:55:22 + | +LL | type Assoc1<T> = (); + | ^^ the trait `SubGeneric<u16>` is not implemented for `()`, which is required by `<u8 as MultiAssoc>::Assoc1<()>: SubGeneric<<u8 as MultiAssoc>::Assoc2>` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:43:1 + | +LL | trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `MultiAssoc` + --> $DIR/super-assoc-mismatch.rs:46:23 + | +LL | trait MultiAssoc + | ---------- required by a bound in this trait +LL | where +LL | Self::Assoc1<()>: SubGeneric<Self::Assoc2> + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs new file mode 100644 index 00000000000..35149fdfba0 --- /dev/null +++ b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![feature(trait_alias)] + +trait Foo<T> {} +trait Bar { type Assoc; } + +trait Alias<T: Bar> = Foo<T>; + +// Check that an alias only requires us to specify the associated types +// of the principal's supertraits. For example, we shouldn't require +// specifying the type `Assoc` on trait `Bar` just because we have some +// `T: Bar` where clause on the alias... because that makes no sense. +fn use_alias<T: Bar>(x: &dyn Alias<T>) {} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs index 52ecbcc9e2c..7d71fcdd158 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs @@ -20,6 +20,7 @@ impl<T, S> Trait<T, S> for () {} fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> { //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied +//~| ERROR type annotations needed 3 } diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr index e7ceb7372bf..5062d17033e 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr @@ -43,7 +43,7 @@ LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), Assoc = i32> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:18 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:18 | LL | struct Struct<T: Trait<u32, String>> { | ^^^^^ expected 1 generic argument @@ -59,7 +59,7 @@ LL | struct Struct<T: Trait<u32, Assoc = String>> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:31:23 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:32:23 | LL | trait AnotherTrait<T: Trait<T, i32>> {} | ^^^^^ expected 1 generic argument @@ -75,7 +75,7 @@ LL | trait AnotherTrait<T: Trait<T, Assoc = i32>> {} | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:34:9 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:35:9 | LL | impl<T: Trait<u32, String>> Struct<T> {} | ^^^^^ expected 1 generic argument @@ -91,7 +91,7 @@ LL | impl<T: Trait<u32, Assoc = String>> Struct<T> {} | +++++++ error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:58 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:41:58 | LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {} | ^^^^^^ - help: remove this generic argument @@ -99,7 +99,7 @@ LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {} | expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:8 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:8 | LL | struct Struct<T: Trait<u32, String>> { | ^^^^^^ - @@ -116,7 +116,13 @@ error[E0207]: the type parameter `S` is not constrained by the impl trait, self LL | impl<T, S> Trait<T, S> for () {} | ^ unconstrained type parameter -error: aborting due to 9 previous errors +error[E0282]: type annotations needed + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:41 + | +LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> { + | ^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0107, E0207. +Some errors have detailed explanations: E0107, E0207, E0282. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs index 40a6115e838..2616ad84ff8 100644 --- a/tests/ui/traits/bound/in-arc.rs +++ b/tests/ui/traits/bound/in-arc.rs @@ -3,7 +3,7 @@ // Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc // and shared between threads as long as all types fulfill Send. -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::Arc; use std::sync::mpsc::channel; diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 74c7afd6b9e..89b2da4452a 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,7 +1,9 @@ //~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send` struct A<T>(B<T>); //~^ ERROR recursive types `A` and `B` have infinite size +//~| ERROR `T` is never used struct B<T>(A<A<T>>); +//~^ ERROR `T` is never used trait Foo {} impl<T> Foo for T where T: Send {} impl Foo for B<u8> {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index fe20c47c57a..6467a438375 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -3,7 +3,7 @@ error[E0072]: recursive types `A` and `B` have infinite size | LL | struct A<T>(B<T>); | ^^^^^^^^^^^ ---- recursive without indirection -LL | +... LL | struct B<T>(A<A<T>>); | ^^^^^^^^^^^ ------- recursive without indirection | @@ -11,19 +11,38 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | LL ~ struct A<T>(Box<B<T>>); LL | +LL | LL ~ struct B<T>(Box<A<A<T>>>); | +error[E0392]: type parameter `T` is never used + --> $DIR/issue-105231.rs:2:10 + | +LL | struct A<T>(B<T>); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/issue-105231.rs:5:10 + | +LL | struct B<T>(A<A<T>>); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-105231.rs:4:8 + --> $DIR/issue-105231.rs:5:8 | LL | struct B<T>(A<A<T>>); | ^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0275. +Some errors have detailed explanations: E0072, E0275, E0392. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 5bc79d9cee8..330b23b5755 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -60,6 +60,14 @@ error[E0412]: cannot find type `NotDefined` in this scope LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | ^^^^^^^^^^ not found in this scope +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:3:27 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-50480.rs:1:17 | @@ -87,14 +95,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 - | -LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); - | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator - | - = help: the trait `Iterator` is not implemented for `i32` - -error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:14:33 | LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index a04fa1ab8a1..39d453e8035 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,15 +1,3 @@ -error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 - | -LL | impl<T: Copy> Trait for T {} - | ------------------------- first implementation here -LL | struct LocalTy; -LL | impl Trait for <LocalTy as Overflow>::Assoc {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - | - = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc` - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) - error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc: Sized` --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18 | @@ -27,6 +15,18 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assoc: ?Sized; | ++++++++ +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 + | +LL | impl<T: Copy> Trait for T {} + | ------------------------- first implementation here +LL | struct LocalTy; +LL | impl Trait for <LocalTy as Overflow>::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | + = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc` + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) + error: aborting due to 2 previous errors Some errors have detailed explanations: E0119, E0275. 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 931c46c6887..45ff9f763cd 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -13,6 +13,12 @@ LL | #![feature(lazy_type_alias)] = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information = note: `#[warn(incomplete_features)]` on by default +error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed + --> $DIR/issue-118950-root-region.rs:14:21 + | +LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } @@ -26,12 +32,6 @@ LL | LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` -error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed - --> $DIR/issue-118950-root-region.rs:14:21 - | -LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0412. diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs index 7c7c68ad60a..f62dccff58d 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs @@ -20,6 +20,7 @@ impl<'a, I> UnwrapItemsExt for I { fn unwrap_items(self) -> Self::Iter { MyStruct {} + //~^ ERROR expected generic lifetime parameter } } diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr index 089c3e4fd8a..e6b94c525ff 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I> UnwrapItemsExt for I { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/assoc-type-lifetime-unconstrained.rs:22:9 + | +LL | impl<'a, I> UnwrapItemsExt for I { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | MyStruct {} + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs index 1824ff5e2fb..fcac83500ec 100644 --- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs @@ -12,6 +12,8 @@ impl<T> X for () { //~^ ERROR the type parameter `T` is not constrained type I = impl Sized; fn f() -> Self::I {} + //~^ ERROR type annotations needed + //~| ERROR type annotations needed } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr index 137a4db81b5..bb0e11d314c 100644 --- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr @@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<T> X for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/impl-with-unconstrained-param.rs:14:23 + | +LL | fn f() -> Self::I {} + | ^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/impl-with-unconstrained-param.rs:14:15 + | +LL | fn f() -> Self::I {} + | ^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs index bb4104b3d25..ce8a38a3361 100644 --- a/tests/ui/type-alias-impl-trait/issue-74244.rs +++ b/tests/ui/type-alias-impl-trait/issue-74244.rs @@ -14,6 +14,7 @@ impl<T> Allocator for DefaultAllocator { type A = impl Fn(<DefaultAllocator as Allocator>::Buffer); fn foo() -> A { + //~^ ERROR: type annotations needed |_| () } diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr index f5ca56baccc..d2b50ffd86b 100644 --- a/tests/ui/type-alias-impl-trait/issue-74244.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr @@ -4,6 +4,13 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<T> Allocator for DefaultAllocator { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-74244.rs:16:13 + | +LL | fn foo() -> A { + | ^ cannot infer type for type parameter `T` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.rs b/tests/ui/type-alias-impl-trait/issue-74761-2.rs index f582592e9bc..e556025adee 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.rs @@ -10,6 +10,7 @@ impl<'a, 'b> A for () { type B = impl core::fmt::Debug; fn f(&self) -> Self::B {} + //~^ ERROR expected generic lifetime parameter } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr index f15d0a069ca..26babc29000 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter -error: aborting due to 2 previous errors +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-74761-2.rs:12:28 + | +LL | impl<'a, 'b> A for () { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | fn f(&self) -> Self::B {} + | ^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761.rs b/tests/ui/type-alias-impl-trait/issue-74761.rs index f582592e9bc..e556025adee 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761.rs +++ b/tests/ui/type-alias-impl-trait/issue-74761.rs @@ -10,6 +10,7 @@ impl<'a, 'b> A for () { type B = impl core::fmt::Debug; fn f(&self) -> Self::B {} + //~^ ERROR expected generic lifetime parameter } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr index 1d016fe070f..a4826c29346 100644 --- a/tests/ui/type-alias-impl-trait/issue-74761.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr @@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter -error: aborting due to 2 previous errors +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/issue-74761.rs:12:28 + | +LL | impl<'a, 'b> A for () { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | fn f(&self) -> Self::B {} + | ^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs index 296a3f3e300..b232097fdb3 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs @@ -12,6 +12,7 @@ impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) { type Associated = (i32, impl Iterator<Item = i32>); fn into(self) -> Self::Associated { (0_i32, [0_i32].iter().copied()) + //~^ ERROR: expected generic lifetime parameter, found `'_` } } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr index cff2695304a..5f9c56f1ca9 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr @@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) { | ^^ unconstrained lifetime parameter -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:14:9 + | +LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | (0_i32, [0_i32].iter().copied()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0792. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index e92cf2513e7..eae5e5fdde2 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -6,16 +6,21 @@ trait Captures<'a> {} impl<T> Captures<'_> for T {} type NotCapturedEarly<'a> = impl Sized; //~ [o] +//~^ ERROR: unconstrained opaque type type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o] +//~^ ERROR: unconstrained opaque type // TAIT does *not* capture `'b` type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o] +//~^ ERROR: unconstrained opaque type // TAIT does *not* capture `'b` type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [o] +//~^ ERROR: unconstrained opaque type type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o] +//~^ ERROR: unconstrained opaque type trait Foo<'i> { type ImplicitCapture<'a>; @@ -27,18 +32,24 @@ trait Foo<'i> { impl<'i> Foo<'i> for &'i () { type ImplicitCapture<'a> = impl Sized; //~ [o, o] + //~^ ERROR: unconstrained opaque type type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] + //~^ ERROR: unconstrained opaque type type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] + //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { type ImplicitCapture<'a> = impl Sized; //~ [o, o] + //~^ ERROR: unconstrained opaque type type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o] + //~^ ERROR: unconstrained opaque type type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o] + //~^ ERROR: unconstrained opaque type } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index 1794447c89a..914541fcf66 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -1,3 +1,91 @@ +error: unconstrained opaque type + --> $DIR/variance.rs:8:29 + | +LL | type NotCapturedEarly<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `NotCapturedEarly` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:11:26 + | +LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `CapturedEarly` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:15:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; + | ^^^^^^^^^^ + | + = note: `NotCapturedLate` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:19:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Captured` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:22:27 + | +LL | type Bar<'a, 'b: 'b, T> = impl Sized; + | ^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/variance.rs:34:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:37:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:40:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:45:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + | + = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:48:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl + +error: unconstrained opaque type + --> $DIR/variance.rs:51:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl + error: [o] --> $DIR/variance.rs:8:29 | @@ -5,64 +93,64 @@ LL | type NotCapturedEarly<'a> = impl Sized; | ^^^^^^^^^^ error: [o] - --> $DIR/variance.rs:10:26 + --> $DIR/variance.rs:11:26 | LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o] - --> $DIR/variance.rs:13:56 + --> $DIR/variance.rs:15:56 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; | ^^^^^^^^^^ error: [o] - --> $DIR/variance.rs:16:49 + --> $DIR/variance.rs:19:49 | LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o, o] - --> $DIR/variance.rs:18:27 + --> $DIR/variance.rs:22:27 | LL | type Bar<'a, 'b: 'b, T> = impl Sized; | ^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:29:32 + --> $DIR/variance.rs:34:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:31:42 + --> $DIR/variance.rs:37:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:33:39 + --> $DIR/variance.rs:40:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:37:32 + --> $DIR/variance.rs:45:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:39:42 + --> $DIR/variance.rs:48:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o] - --> $DIR/variance.rs:41:39 + --> $DIR/variance.rs:51:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/typeck/issue-13853-5.rs b/tests/ui/typeck/issue-13853-5.rs index 2afdf95aacf..fc97c6c67d6 100644 --- a/tests/ui/typeck/issue-13853-5.rs +++ b/tests/ui/typeck/issue-13853-5.rs @@ -7,6 +7,7 @@ trait Deserializable { impl<'a, T: Deserializable> Deserializable for &'a str { //~^ ERROR type parameter `T` is not constrained fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str { + //~^ ERROR mismatched types } } diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr index 1eead956328..388d5ec746c 100644 --- a/tests/ui/typeck/issue-13853-5.stderr +++ b/tests/ui/typeck/issue-13853-5.stderr @@ -4,6 +4,22 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<'a, T: Deserializable> Deserializable for &'a str { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/issue-13853-5.rs:9:70 + | +LL | fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str { + | ----------------- ^^^^^^^ expected `&str`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `_y` + | +LL ~ fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str { +LL + _y +LL ~ + | + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0308. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs index da55bc96244..6a44a94df3f 100644 --- a/tests/ui/variance/variance-associated-consts.rs +++ b/tests/ui/variance/variance-associated-consts.rs @@ -12,6 +12,7 @@ trait Trait { #[rustc_variance] struct Foo<T: Trait> { //~ ERROR [o] field: [u8; <T as Trait>::Const] + //~^ ERROR: unconstrained generic constant } fn main() { } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index e25f0879add..f41574ca3a3 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -1,8 +1,16 @@ +error: unconstrained generic constant + --> $DIR/variance-associated-consts.rs:14:12 + | +LL | field: [u8; <T as Trait>::Const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); <T as Trait>::Const]:` + error: [o] --> $DIR/variance-associated-consts.rs:13:1 | LL | struct Foo<T: Trait> { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index 39ea77a8aa2..f1763c403f1 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -50,6 +50,7 @@ struct Test6<'a, 'b:'a> { //~ ERROR [+, o] #[rustc_variance] struct Test7<'a> { //~ ERROR [*] + //~^ ERROR: `'a` is never used x: isize } diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index c55730296f1..edfc888f656 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -1,3 +1,11 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-regions-direct.rs:52:14 + | +LL | struct Test7<'a> { + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + error: [+, +, +] --> $DIR/variance-regions-direct.rs:9:1 | @@ -35,10 +43,11 @@ LL | struct Test7<'a> { | ^^^^^^^^^^^^^^^^ error: [-, +, o] - --> $DIR/variance-regions-direct.rs:59:1 + --> $DIR/variance-regions-direct.rs:60:1 | LL | enum Test8<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 0d00535fef1..31e25641d8c 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -6,6 +6,7 @@ #[rustc_variance] enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] + //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), @@ -13,16 +14,19 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] #[rustc_variance] struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] + //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] + //~^ ERROR: `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *] + //~^ ERROR: `'c` is never used f: Base<'a, 'b, 'a, 'c> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index edf2626d598..901ec0c6a76 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -1,3 +1,35 @@ +error[E0392]: lifetime parameter `'d` is never used + --> $DIR/variance-regions-indirect.rs:8:26 + | +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^ unused lifetime parameter + | + = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'w` is never used + --> $DIR/variance-regions-indirect.rs:16:17 + | +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^ unused lifetime parameter + | + = help: consider removing `'w`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'c` is never used + --> $DIR/variance-regions-indirect.rs:22:28 + | +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^ unused lifetime parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: lifetime parameter `'c` is never used + --> $DIR/variance-regions-indirect.rs:28:28 + | +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^ unused lifetime parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + error: [-, +, o, *] --> $DIR/variance-regions-indirect.rs:8:1 | @@ -5,28 +37,29 @@ LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, o, +, -] - --> $DIR/variance-regions-indirect.rs:15:1 + --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, o, *] - --> $DIR/variance-regions-indirect.rs:20:1 + --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [o, +, *] - --> $DIR/variance-regions-indirect.rs:25:1 + --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [-, +, o] - --> $DIR/variance-regions-indirect.rs:30:1 + --> $DIR/variance-regions-indirect.rs:34:1 | LL | struct Derived4<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index ad5334602a2..25a01b160dd 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -19,16 +19,19 @@ struct TestStruct<U,T:Setter<U>> { //~ ERROR [+, +] #[rustc_variance] enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used t: T } #[rustc_variance] struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [*, +] + //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 5a73e541c3a..95ed18c1ad2 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -1,3 +1,30 @@ +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:21:15 + | +LL | enum TestEnum<U,T:Setter<U>> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:27:25 + | +LL | struct TestContraStruct<U,T:Setter<U>> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + +error[E0392]: type parameter `U` is never used + --> $DIR/variance-trait-bounds.rs:33:16 + | +LL | struct TestBox<U,T:Getter<U>+Setter<U>> { + | ^ unused type parameter + | + = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead + error: [+, +] --> $DIR/variance-trait-bounds.rs:16:1 | @@ -11,16 +38,17 @@ LL | enum TestEnum<U,T:Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, +] - --> $DIR/variance-trait-bounds.rs:26:1 + --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct<U,T:Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: [*, +] - --> $DIR/variance-trait-bounds.rs:31:1 + --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox<U,T:Getter<U>+Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0392`. |
