diff options
370 files changed, 3834 insertions, 2255 deletions
diff --git a/Cargo.lock b/Cargo.lock index df7d8441941..4150285b461 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -278,6 +278,7 @@ dependencies = [ "humantime 2.0.1", "ignore", "im-rc", + "itertools 0.10.0", "jobserver", "lazy_static", "lazycell", @@ -293,7 +294,7 @@ dependencies = [ "rand 0.8.3", "rustc-workspace-hack", "rustfix", - "semver 0.10.0", + "semver 1.0.1", "serde", "serde_ignored", "serde_json", @@ -551,10 +552,10 @@ name = "clippy" version = "0.1.54" dependencies = [ "cargo_metadata 0.12.0", - "clippy-mini-macro-test", "clippy_lints", "compiletest_rs", "derive-new", + "filetime", "quote", "regex", "rustc-workspace-hack", @@ -567,10 +568,6 @@ dependencies = [ ] [[package]] -name = "clippy-mini-macro-test" -version = "0.2.0" - -[[package]] name = "clippy_dev" version = "0.0.1" dependencies = [ @@ -1716,6 +1713,15 @@ dependencies = [ ] [[package]] +name = "itertools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +dependencies = [ + "either", +] + +[[package]] name = "itoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1743,11 +1749,10 @@ dependencies = [ "fs-err", "getopts", "jsonpath_lib", - "lazy_static", + "once_cell", "regex", - "serde", "serde_json", - "shlex 0.1.1", + "shlex", ] [[package]] @@ -2128,7 +2133,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "shlex 1.0.0", + "shlex", "tempfile", "toml", ] @@ -4675,6 +4680,15 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d023dabf011d5dcb5ac64e3685d97d3b0ef412911077a2851455c6098524a723" +dependencies = [ + "serde", +] + +[[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4796,12 +4810,6 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" [[package]] name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "shlex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" @@ -5033,9 +5041,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.33" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228" +checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80" dependencies = [ "filetime", "libc", diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 14ecf27813d..7c79b4aab3c 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -12,13 +12,11 @@ #![feature(box_patterns)] #![cfg_attr(bootstrap, feature(const_fn_unsize))] #![feature(const_fn_transmute)] -#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] #![feature(min_specialization)] -#![feature(trusted_step)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index c9e2d202da9..26da18b571c 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -6,7 +6,6 @@ #![feature(bindings_after_at)] #![feature(iter_is_partitioned)] -#![feature(box_syntax)] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0db6659f8e2..1e70664e64d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1457,7 +1457,6 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { enum_type: Ty<'tcx>, layout: TyAndLayout<'tcx>, tag_type_metadata: Option<&'ll DIType>, - containing_scope: &'ll DIScope, common_members: Vec<Option<&'ll DIType>>, span: Span, } @@ -1486,13 +1485,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { _ => bug!(), }; - // This will always find the metadata in the type map. let fallback = use_enum_fallback(cx); - let self_metadata = if fallback { - self.containing_scope - } else { - type_metadata(cx, self.enum_type, self.span) - }; + // This will always find the metadata in the type map. + let self_metadata = type_metadata(cx, self.enum_type, self.span); match self.layout.variants { Variants::Single { index } => { @@ -1507,7 +1502,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, self.layout, variant_info, - NoTag, + None, self_metadata, self.span, ); @@ -1539,13 +1534,26 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .. } => { let tag_info = if fallback { - RegularTag { + // For MSVC, we generate a union of structs for each variant with an explicit + // discriminant field roughly equivalent to the following C: + // ```c + // union enum$<{name}> { + // struct {variant 0 name} { + // tag$ variant$; + // <variant 0 fields> + // } variant0; + // <other variant structs> + // } + // ``` + // The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to + // determine which variant is active and then displays it. + Some(DirectTag { tag_field: Field::from(tag_field), tag_type_metadata: self.tag_type_metadata.unwrap(), - } + }) } else { // This doesn't matter in this case. - NoTag + None }; variants .iter_enumerated() @@ -1574,7 +1582,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { MemberDescription { name: if fallback { - String::new() + format!("variant{}", i.as_u32()) } else { variant_info.variant_name() }, @@ -1599,77 +1607,135 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { ref variants, tag_field, } => { + let calculate_niche_value = |i: VariantIdx| { + if i == dataful_variant { + None + } else { + let value = (i.as_u32() as u128) + .wrapping_sub(niche_variants.start().as_u32() as u128) + .wrapping_add(niche_start); + let value = tag.value.size(cx).truncate(value); + // NOTE(eddyb) do *NOT* remove this assert, until + // we pass the full 128-bit value to LLVM, otherwise + // truncation will be silent and remain undetected. + assert_eq!(value as u64 as u128, value); + Some(value as u64) + } + }; + + // For MSVC, we will generate a union of two fields, one for the dataful variant + // and one that just points to the discriminant. We also create an enum that + // contains tag values for the non-dataful variants and make the discriminant field + // that type. We then use natvis to render the enum type correctly in Windbg/VS. + // This will generate debuginfo roughly equivalent to the following C: + // ```c + // union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> { + // struct <dataful variant name> { + // <fields in dataful variant> + // } dataful_variant; + // enum Discriminant$ { + // <non-dataful variants> + // } discriminant; + // } + // ``` + // The natvis in `intrinsic.natvis` matches on the type name `enum$<*, *, *, *>` + // and evaluates `this.discriminant`. If the value is between the min niche and max + // niche, then the enum is in the dataful variant and `this.dataful_variant` is + // rendered. Otherwise, the enum is in one of the non-dataful variants. In that + // case, we just need to render the name of the `this.discriminant` enum. if fallback { - let variant = self.layout.for_variant(cx, dataful_variant); - // Create a description of the non-null variant. - let (variant_type_metadata, member_description_factory) = describe_enum_variant( + let dataful_variant_layout = self.layout.for_variant(cx, dataful_variant); + + let mut discr_enum_ty = tag.value.to_ty(cx.tcx); + // If the niche is the NULL value of a reference, then `discr_enum_ty` will be a RawPtr. + // CodeView doesn't know what to do with enums whose base type is a pointer so we fix this up + // to just be `usize`. + if let ty::RawPtr(_) = discr_enum_ty.kind() { + discr_enum_ty = cx.tcx.types.usize; + } + + let tags: Vec<_> = variants + .iter_enumerated() + .filter_map(|(variant_idx, _)| { + calculate_niche_value(variant_idx).map(|tag| { + let variant = variant_info_for(variant_idx); + let name = variant.variant_name(); + + Some(unsafe { + llvm::LLVMRustDIBuilderCreateEnumerator( + DIB(cx), + name.as_ptr().cast(), + name.len(), + tag as i64, + !discr_enum_ty.is_signed(), + ) + }) + }) + }) + .collect(); + + let discr_enum = unsafe { + llvm::LLVMRustDIBuilderCreateEnumerationType( + DIB(cx), + self_metadata, + "Discriminant$".as_ptr().cast(), + "Discriminant$".len(), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, + tag.value.size(cx).bits(), + tag.value.align(cx).abi.bits() as u32, + create_DIArray(DIB(cx), &tags), + type_metadata(cx, discr_enum_ty, self.span), + true, + ) + }; + + let variant_info = variant_info_for(dataful_variant); + let (variant_type_metadata, member_desc_factory) = describe_enum_variant( cx, - variant, - variant_info_for(dataful_variant), - OptimizedTag, - self.containing_scope, + dataful_variant_layout, + variant_info, + Some(NicheTag), + self_metadata, self.span, ); - let variant_member_descriptions = - member_description_factory.create_member_descriptions(cx); + let member_descriptions = member_desc_factory.create_member_descriptions(cx); set_members_of_composite_type( cx, self.enum_type, variant_type_metadata, - variant_member_descriptions, + member_descriptions, Some(&self.common_members), ); - // Encode the information about the null variant in the union - // member's name. - let mut name = String::from("RUST$ENCODED$ENUM$"); - // Right now it's not even going to work for `niche_start > 0`, - // and for multiple niche variants it only supports the first. - fn compute_field_path<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, - name: &mut String, - layout: TyAndLayout<'tcx>, - offset: Size, - size: Size, - ) { - for i in 0..layout.fields.count() { - let field_offset = layout.fields.offset(i); - if field_offset > offset { - continue; - } - let inner_offset = offset - field_offset; - let field = layout.field(cx, i); - if inner_offset + size <= field.size { - write!(name, "{}$", i).unwrap(); - compute_field_path(cx, name, field, inner_offset, size); - } - } - } - compute_field_path( - cx, - &mut name, - self.layout, - self.layout.fields.offset(tag_field), - self.layout.field(cx, tag_field).size, - ); - let variant_info = variant_info_for(*niche_variants.start()); - variant_info.map_struct_name(|variant_name| { - name.push_str(variant_name); - }); - - // Create the (singleton) list of descriptions of union members. - vec![MemberDescription { - name, - type_metadata: variant_type_metadata, - offset: Size::ZERO, - size: variant.size, - align: variant.align.abi, - flags: DIFlags::FlagZero, - discriminant: None, - source_info: variant_info.source_info(cx), - }] + let (size, align) = + cx.size_and_align_of(dataful_variant_layout.field(cx, tag_field).ty); + + vec![ + MemberDescription { + // Name the dataful variant so that we can identify it for natvis + name: "dataful_variant".to_string(), + type_metadata: variant_type_metadata, + offset: Size::ZERO, + size: self.layout.size, + align: self.layout.align.abi, + flags: DIFlags::FlagZero, + discriminant: None, + source_info: variant_info.source_info(cx), + }, + MemberDescription { + name: "discriminant".into(), + type_metadata: discr_enum, + offset: dataful_variant_layout.fields.offset(tag_field), + size, + align, + flags: DIFlags::FlagZero, + discriminant: None, + source_info: None, + }, + ] } else { variants .iter_enumerated() @@ -1681,7 +1747,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info, - OptimizedTag, + Some(NicheTag), self_metadata, self.span, ); @@ -1697,19 +1763,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { Some(&self.common_members), ); - let niche_value = if i == dataful_variant { - None - } else { - let value = (i.as_u32() as u128) - .wrapping_sub(niche_variants.start().as_u32() as u128) - .wrapping_add(niche_start); - let value = tag.value.size(cx).truncate(value); - // NOTE(eddyb) do *NOT* remove this assert, until - // we pass the full 128-bit value to LLVM, otherwise - // truncation will be silent and remain undetected. - assert_eq!(value as u64 as u128, value); - Some(value as u64) - }; + let niche_value = calculate_niche_value(i); MemberDescription { name: variant_info.variant_name(), @@ -1771,14 +1825,10 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { } } -// FIXME: terminology here should be aligned with `abi::TagEncoding`. -// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`. -// `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead. #[derive(Copy, Clone)] enum EnumTagInfo<'ll> { - RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType }, - OptimizedTag, - NoTag, + DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType }, + NicheTag, } #[derive(Copy, Clone)] @@ -1859,7 +1909,7 @@ fn describe_enum_variant( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, - discriminant_info: EnumTagInfo<'ll>, + discriminant_info: Option<EnumTagInfo<'ll>>, containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { @@ -1882,12 +1932,11 @@ fn describe_enum_variant( let (offsets, args) = if use_enum_fallback(cx) { // If this is not a univariant enum, there is also the discriminant field. let (discr_offset, discr_arg) = match discriminant_info { - RegularTag { tag_field, .. } => { + Some(DirectTag { tag_field, .. }) => { // We have the layout of an enum variant, we need the layout of the outer enum let enum_layout = cx.layout_of(layout.ty); let offset = enum_layout.fields.offset(tag_field.as_usize()); - let args = - ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty); + let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty); (Some(offset), Some(args)) } _ => (None, None), @@ -1918,7 +1967,7 @@ fn describe_enum_variant( offsets, args, tag_type_metadata: match discriminant_info { - RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata), + Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata), _ => None, }, span, @@ -2048,9 +2097,9 @@ fn prepare_enum_metadata( if use_enum_fallback(cx) { let discriminant_type_metadata = match layout.variants { - Variants::Single { .. } - | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None, - Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => { + Variants::Single { .. } => None, + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. } + | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => { Some(discriminant_type_metadata(tag.value)) } }; @@ -2062,7 +2111,7 @@ fn prepare_enum_metadata( unsafe { llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), - containing_scope, + None, enum_name.as_ptr().cast(), enum_name.len(), file_metadata, @@ -2088,7 +2137,6 @@ fn prepare_enum_metadata( enum_type, layout, tag_type_metadata: discriminant_type_metadata, - containing_scope, common_members: vec![], span, }), @@ -2241,7 +2289,6 @@ fn prepare_enum_metadata( enum_type, layout, tag_type_metadata: None, - containing_scope, common_members: outer_fields, span, }), @@ -2437,7 +2484,7 @@ fn create_union_stub( llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), - containing_scope, + Some(containing_scope), union_type_name.as_ptr().cast(), union_type_name.len(), unknown_file_metadata(cx), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8b1dcea3fa2..54ef1a28468 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2038,7 +2038,7 @@ extern "C" { pub fn LLVMRustDIBuilderCreateUnionType( Builder: &DIBuilder<'a>, - Scope: &'a DIScope, + Scope: Option<&'a DIScope>, Name: *const c_char, NameLen: size_t, File: &'a DIFile, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index d1bbf74307c..7b4b0821c4b 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -3,7 +3,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt}; +use rustc_target::abi::{TagEncoding, Variants}; use std::fmt::Write; @@ -45,8 +46,12 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Float(float_ty) => output.push_str(float_ty.name_str()), ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), ty::Adt(def, substs) => { - push_item_name(tcx, def.did, qualified, output); - push_type_params(tcx, substs, output, visited); + if def.is_enum() && cpp_like_names { + msvc_enum_fallback(tcx, t, def, substs, output, visited); + } else { + push_item_name(tcx, def.did, qualified, output); + push_type_params(tcx, substs, output, visited); + } } ty::Tuple(component_types) => { if cpp_like_names { @@ -233,6 +238,54 @@ pub fn push_debuginfo_type_name<'tcx>( } } + /// MSVC names enums differently than other platforms so that the debugging visualization + // format (natvis) is able to understand enums and render the active variant correctly in the + // debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and + // `EnumMemberDescriptionFactor::create_member_descriptions`. + fn msvc_enum_fallback( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + def: &AdtDef, + substs: SubstsRef<'tcx>, + output: &mut String, + visited: &mut FxHashSet<Ty<'tcx>>, + ) { + let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error"); + + if let Variants::Multiple { + tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag, + variants, + .. + } = &layout.variants + { + let dataful_variant_layout = &variants[*dataful_variant]; + + // calculate the range of values for the dataful variant + let dataful_discriminant_range = + &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range; + + let min = dataful_discriminant_range.start(); + let min = tag.value.size(&tcx).truncate(*min); + + let max = dataful_discriminant_range.end(); + let max = tag.value.size(&tcx).truncate(*max); + + output.push_str("enum$<"); + push_item_name(tcx, def.did, true, output); + push_type_params(tcx, substs, output, visited); + + let dataful_variant_name = def.variants[*dataful_variant].ident.as_str(); + + output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name)); + } else { + output.push_str("enum$<"); + push_item_name(tcx, def.did, true, output); + push_type_params(tcx, substs, output, visited); + output.push('>'); + } + } + fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { if qualified { output.push_str(&tcx.crate_name(def_id.krate).as_str()); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 6c4bb021cb3..12da3d9e155 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,15 +1,11 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(assert_matches)] #![feature(bool_to_option)] #![feature(box_patterns)] -#![feature(drain_filter)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(associated_type_bounds)] -#![feature(iter_zip)] #![recursion_limit = "256"] -#![feature(box_syntax)] //! This crate contains codegen code that is used by all codegen backends (LLVM and others). //! The backend-agnostic functions of this crate use functions defined in various traits that diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index adbb98fa750..a8b9f479f1e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,15 +10,12 @@ #![feature(array_windows)] #![feature(control_flow_enum)] #![feature(in_band_lifetimes)] -#![feature(unboxed_closures)] #![feature(generator_trait)] -#![feature(fn_traits)] #![feature(min_specialization)] #![feature(auto_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] #![feature(hash_raw_entry)] -#![feature(stmt_expr_attributes)] #![feature(core_intrinsics)] #![feature(test)] #![feature(associated_type_bounds)] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 29d685ab530..3aabe94bfc6 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -597,7 +597,7 @@ impl<O: ForestObligation> ObligationForest<O> { Some(rpos) => { // Cycle detected. processor.process_backedge( - stack[rpos..].iter().map(GetObligation(&self.nodes)), + stack[rpos..].iter().map(|&i| &self.nodes[i].obligation), PhantomData, ); } @@ -705,20 +705,3 @@ impl<O: ForestObligation> ObligationForest<O> { }); } } - -// I need a Clone closure. -#[derive(Clone)] -struct GetObligation<'a, O>(&'a [Node<O>]); - -impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> { - type Output = &'a O; - extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O { - &self.0[*args.0].obligation - } -} - -impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> { - extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O { - &self.0[*args.0].obligation - } -} diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 16510b3eb07..f77eac2b068 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 7f3c410b1ec..ad2ecae9233 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -3,12 +3,10 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] -#![feature(const_panic)] #![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] -#![feature(trusted_step)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 04d62391c02..0093fa5e562 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,12 +1,10 @@ #![feature(allow_internal_unstable)] #![feature(bench_black_box)] -#![feature(const_panic)] #![feature(extend_one)] #![feature(iter_zip)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] -#![feature(trusted_step)] pub mod bit_set; pub mod vec; diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 3f759f4023b..246fa28d986 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -65,7 +65,7 @@ impl Idx for u32 { /// `u32::MAX`. You can also customize things like the `Debug` impl, /// what traits are derived, and so forth via the macro. #[macro_export] -#[allow_internal_unstable(step_trait, rustc_attrs)] +#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)] macro_rules! newtype_index { // ---- public rules ---- diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 680f6af63f2..fb762d2deba 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -524,7 +524,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { - Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) + Ok(vec![self.tcx.crate_name(cnum).to_string()]) } fn path_qualified( self, diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 6b452bca8e7..ee358c52c2f 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,14 +16,12 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_panic)] #![feature(extend_one)] #![feature(iter_zip)] #![feature(never_type)] #![feature(in_band_lifetimes)] #![feature(control_flow_enum)] #![feature(min_specialization)] -#![feature(trusted_step)] #![recursion_limit = "512"] // For rustdoc #[macro_use] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index f2b69da3f86..b5af2bfca35 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,6 +1,5 @@ #![feature(bool_to_option)] #![feature(box_patterns)] -#![feature(box_syntax)] #![feature(internal_output_capture)] #![feature(nll)] #![feature(generator_trait)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index dd4caab28dc..1666754d29a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -799,7 +799,7 @@ pub fn create_global_ctxt<'tcx>( query_result_on_disk_cache, queries.as_dyn(), &crate_name, - &outputs, + outputs, ) }) }); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index c1d6a4f1de1..862f8374d30 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -922,7 +922,7 @@ impl<'tcx> LateContext<'tcx> { } fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { - Ok(vec![self.tcx.original_crate_name(cnum)]) + Ok(vec![self.tcx.crate_name(cnum)]) } fn path_qualified( diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 45ed6872f18..4f59460aa82 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -36,8 +36,6 @@ #![feature(iter_zip)] #![feature(never_type)] #![feature(nll)] -#![feature(half_open_range_patterns)] -#![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![recursion_limit = "256"] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 9c94bab04e9..319adf42cf1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{is_range_literal, ExprKind, Node}; -use rustc_index::vec::Idx; use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; @@ -13,7 +12,7 @@ use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::Abi; -use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants}; +use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; use std::cmp; @@ -783,25 +782,14 @@ crate fn repr_nullable_ptr<'tcx>( ) -> Option<Ty<'tcx>> { debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty); if let ty::Adt(ty_def, substs) = ty.kind() { - if ty_def.variants.len() != 2 { - return None; - } - - let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields; - let variant_fields = [get_variant_fields(0), get_variant_fields(1)]; - let fields = if variant_fields[0].is_empty() { - &variant_fields[1] - } else if variant_fields[1].is_empty() { - &variant_fields[0] - } else { - return None; + let field_ty = match &ty_def.variants.raw[..] { + [var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) { + ([], [field]) | ([field], []) => field.ty(cx.tcx, substs), + _ => return None, + }, + _ => return None, }; - if fields.len() != 1 { - return None; - } - - let field_ty = fields[0].ty(cx.tcx, substs); if !ty_is_known_nonnull(cx, field_ty, ckind) { return None; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 70475563a4a..f1c4e5fb4a3 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -25,7 +25,11 @@ macro_rules! pluralize { /// before applying the suggestion. #[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub enum Applicability { - /// The suggestion is definitely what the user intended. This suggestion should be + /// The suggestion is definitely what the user intended, or maintains the exact meaning of the code. + /// This suggestion should be automatically applied. + /// + /// In case of multiple `MachineApplicable` suggestions (whether as part of + /// the same `multipart_suggestion` or not), all of them should be /// automatically applied. MachineApplicable, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 15c9eda9902..27842ac7796 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,5 +1,4 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(core_intrinsics)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] @@ -7,7 +6,6 @@ #![feature(once_cell)] #![feature(proc_macro_internals)] #![feature(min_specialization)] -#![feature(stmt_expr_attributes)] #![feature(try_blocks)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 706f3f6d854..59fec58f0a1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1931,6 +1931,10 @@ impl CrateMetadata { self.root.hash } + fn num_def_ids(&self) -> usize { + self.root.tables.def_keys.size() + } + fn local_def_id(&self, index: DefIndex) -> DefId { DefId { krate: self.cnum, index } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 3c05efd6a5e..9e615e48a3c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -188,7 +188,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, foreign_modules => { cdata.get_foreign_modules(tcx) } crate_hash => { cdata.root.hash } crate_host_hash => { cdata.host_hash } - original_crate_name => { cdata.root.name } + crate_name => { cdata.root.name } extra_filename => { cdata.root.extra_filename.clone() } @@ -205,7 +205,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, let r = *cdata.dep_kind.lock(); r } - crate_name => { cdata.root.name } item_children => { let mut result = SmallVec::<[_; 8]>::new(); cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); @@ -459,6 +458,13 @@ impl CStore { self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess) } + /// Only public-facing way to traverse all the definitions in a non-local crate. + /// Critically useful for this third-party project: <https://github.com/hacspec/hacspec>. + /// See <https://github.com/rust-lang/rust/pull/85889> for context. + pub fn num_def_ids_untracked(&self, cnum: CrateNum) -> usize { + self.get_crate_data(cnum).num_def_ids() + } + pub fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec<ast::Attribute> { self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess).collect() } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5c45e4130d2..2fd9a46cf42 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1673,7 +1673,7 @@ impl EncodeContext<'a, 'tcx> { .iter() .map(|&cnum| { let dep = CrateDep { - name: self.tcx.original_crate_name(cnum), + name: self.tcx.crate_name(cnum), hash: self.tcx.crate_hash(cnum), host_hash: self.tcx.crate_host_hash(cnum), kind: self.tcx.dep_kind(cnum), diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 8476929eaec..aa54d1ae7b9 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>; // required that their size stay the same, but we don't want to change // it inadvertently. This assert just ensures we're aware of any change. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 18); +static_assert_size!(DepNode, 17); #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] static_assert_size!(DepNode, 24); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 6f97716e2e0..e1d7bc4be53 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -29,7 +29,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_panic)] #![feature(core_intrinsics)] #![feature(discriminant_kind)] #![feature(never_type)] @@ -50,7 +49,6 @@ #![feature(associated_type_defaults)] #![feature(iter_zip)] #![feature(thread_local_const_init)] -#![feature(trusted_step)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 26694afb513..5ea78e087f8 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -49,7 +49,7 @@ impl<'tcx> ExportedSymbol<'tcx> { pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String { format!( "rust_metadata_{}_{:08x}", - tcx.original_crate_name(LOCAL_CRATE), + tcx.crate_name(LOCAL_CRATE), tcx.sess.local_stable_crate_id().to_u64(), ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bd030f7f7bf..f65dfea04eb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1247,10 +1247,6 @@ rustc_queries! { eval_always desc { "looking up the hash of a host version of a crate" } } - query original_crate_name(_: CrateNum) -> Symbol { - eval_always - desc { "looking up the original name a crate" } - } query extra_filename(_: CrateNum) -> String { eval_always desc { "looking up the extra filename for a crate" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 268acfcf819..970e669c16f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1005,7 +1005,7 @@ pub struct GlobalCtxt<'tcx> { /// The definite name of the current crate after taking into account /// attributes, commandline parameters, etc. - pub crate_name: Symbol, + crate_name: Symbol, /// Data layout specification for the current target. pub data_layout: TargetDataLayout, @@ -1135,7 +1135,7 @@ impl<'tcx> TyCtxt<'tcx> { on_disk_cache: Option<query::OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, crate_name: &str, - output_filenames: &OutputFilenames, + output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { s.fatal(&err); @@ -1179,7 +1179,7 @@ impl<'tcx> TyCtxt<'tcx> { stability_interner: Default::default(), const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), - output_filenames: Arc::new(output_filenames.clone()), + output_filenames: Arc::new(output_filenames), main_def: resolutions.main_def, } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7f6792ac270..af2be37f387 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1621,7 +1621,7 @@ impl<'tcx> TyCtxt<'tcx> { fn item_name_from_def_id(self, def_id: DefId) -> Option<Symbol> { if def_id.index == CRATE_DEF_INDEX { - Some(self.original_crate_name(def_id.krate)) + Some(self.crate_name(def_id.krate)) } else { let def_key = self.def_key(def_id); match def_key.disambiguated_data.data { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f514278a11c..25557bdd100 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -452,7 +452,7 @@ pub trait PrettyPrinter<'tcx>: } // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { - data = DefPathData::TypeNs(self.tcx().original_crate_name(def_id.krate)); + data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate)); } _ => {} } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f35ecb4d3cd..012d9bd82c8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1837,10 +1837,12 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_enum(&self) -> bool { - match self.kind() { - Adt(adt_def, _) => adt_def.is_enum(), - _ => false, - } + matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum()) + } + + #[inline] + pub fn is_union(&self) -> bool { + matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union()) } #[inline] diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 4c35be39a3d..36eb8a4baa8 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -1965,13 +1965,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // no move out from an earlier location) then this is an attempt at initialization // of the union - we should error in that case. let tcx = this.infcx.tcx; - if let ty::Adt(def, _) = base.ty(this.body(), tcx).ty.kind() { - if def.is_union() { - if this.move_data.path_map[mpi].iter().any(|moi| { - this.move_data.moves[*moi].source.is_predecessor_of(location, this.body) - }) { - return; - } + if base.ty(this.body(), tcx).ty.is_union() { + if this.move_data.path_map[mpi].iter().any(|moi| { + this.move_data.moves[*moi].source.is_predecessor_of(location, this.body) + }) { + return; } } diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs index 3654b51949e..d21550a8e1a 100644 --- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs +++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs @@ -331,17 +331,14 @@ fn place_projection_conflict<'tcx>( Overlap::EqualOrDisjoint } else { let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty; - match ty.kind() { - ty::Adt(def, _) if def.is_union() => { - // Different fields of a union, we are basically stuck. - debug!("place_element_conflict: STUCK-UNION"); - Overlap::Arbitrary - } - _ => { - // Different fields of a struct (`a.x` vs. `a.y`). Disjoint! - debug!("place_element_conflict: DISJOINT-FIELD"); - Overlap::Disjoint - } + if ty.is_union() { + // Different fields of a union, we are basically stuck. + debug!("place_element_conflict: STUCK-UNION"); + Overlap::Arbitrary + } else { + // Different fields of a struct (`a.x` vs. `a.y`). Disjoint! + debug!("place_element_conflict: DISJOINT-FIELD"); + Overlap::Disjoint } } } diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index 1bfbb843114..cea465ea1ed 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -519,10 +519,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // Check if we are assigning into a field of a union, if so, lookup the place // of the union so it is marked as initialized again. if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() { - if let ty::Adt(def, _) = place_base.ty(self.builder.body, self.builder.tcx).ty.kind() { - if def.is_union() { - place = place_base; - } + if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() { + place = place_base; } } diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs index 4978cc3606d..a7012cd63f3 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs @@ -1,5 +1,5 @@ use rustc_hir::def_id::CrateNum; -use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::mir::interpret::Allocation; use rustc_middle::ty::{ self, @@ -88,7 +88,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { - self.path.push_str(&self.tcx.original_crate_name(cnum).as_str()); + self.path.push_str(&self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -127,11 +127,6 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { ) -> Result<Self::Path, Self::Error> { self = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if disambiguated_data.data == DefPathData::Ctor { - return Ok(self); - } - write!(self.path, "::{}", disambiguated_data.data).unwrap(); Ok(self) diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index 647c368d2bb..12a36976f1d 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -12,16 +12,13 @@ Rust MIR: a lowered representation of Rust. #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] -#![feature(exhaustive_patterns)] #![feature(iter_zip)] #![feature(never_type)] #![feature(map_try_insert)] #![feature(min_specialization)] -#![feature(slice_ptr_len)] #![feature(slice_ptr_get)] #![feature(trusted_len)] #![feature(try_blocks)] @@ -31,7 +28,6 @@ Rust MIR: a lowered representation of Rust. #![feature(option_get_or_insert_default)] #![feature(once_cell)] #![feature(control_flow_enum)] -#![feature(trusted_step)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 41d9d0d04b5..ac3420ad339 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -356,10 +356,9 @@ impl Validator<'mir, 'tcx> { } fn check_static(&mut self, def_id: DefId, span: Span) { - assert!( - !self.tcx.is_thread_local_static(def_id), - "tls access is checked in `Rvalue::ThreadLocalRef" - ); + if self.tcx.is_thread_local_static(def_id) { + self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef"); + } self.check_op_spanned(ops::StaticAccess, span) } @@ -753,12 +752,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty; - match base_ty.ty_adt_def() { - Some(def) if def.is_union() => { - self.check_op(ops::UnionAccess); - } - - _ => {} + if base_ty.is_union() { + self.check_op(ops::UnionAccess); } } } diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index 955be8cc81e..103ddda1a1d 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } let base_ty = base.ty(self.body, self.tcx).ty; - if base_ty.ty_adt_def().map_or(false, |adt| adt.is_union()) { + if base_ty.is_union() { // If we did not hit a `Deref` yet and the overall place use is an assignment, the // rules are different. let assign_to_field = !saw_deref @@ -376,6 +376,12 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { /// Checks whether calling `func_did` needs an `unsafe` context or not, i.e. whether /// the called function has target features the calling function hasn't. fn check_target_features(&mut self, func_did: DefId) { + // Unsafety isn't required on wasm targets. For more information see + // the corresponding check in typeck/src/collect.rs + if self.tcx.sess.target.options.is_like_wasm { + return; + } + let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features; diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 29df86ca6cd..4f5a467a6ee 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -114,7 +114,7 @@ use rustc_middle::mir::{ traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::TyCtxt; // Empirical measurements have resulted in some observations: // - Running on a body with a single block and 500 locals takes barely any time @@ -910,17 +910,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> { // Handle the "subtle case" described above by rejecting any `dest` that is or // projects through a union. - let is_union = |ty: Ty<'_>| { - if let ty::Adt(def, _) = ty.kind() { - if def.is_union() { - return true; - } - } - - false - }; let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty); - if is_union(place_ty.ty) { + if place_ty.ty.is_union() { return; } for elem in dest.projection { @@ -930,7 +921,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> { } place_ty = place_ty.projection_ty(self.tcx, elem); - if is_union(place_ty.ty) { + if place_ty.ty.is_union() { return; } } diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index f6b1323e107..78e84419c62 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -415,11 +415,9 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { let base_ty = place_base.ty(self.body, self.tcx).ty; - if let Some(def) = base_ty.ty_adt_def() { + if base_ty.is_union() { // No promotion of union field accesses. - if def.is_union() { - return Err(Unpromotable); - } + return Err(Unpromotable); } } } diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs index 70f7538dd57..a0f225e6de6 100644 --- a/compiler/rustc_mir/src/transform/remove_zsts.rs +++ b/compiler/rustc_mir/src/transform/remove_zsts.rs @@ -69,21 +69,14 @@ fn involves_a_union<'tcx>( tcx: TyCtxt<'tcx>, ) -> bool { let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty); - if is_union(place_ty.ty) { + if place_ty.ty.is_union() { return true; } for elem in place.projection { place_ty = place_ty.projection_ty(tcx, elem); - if is_union(place_ty.ty) { + if place_ty.ty.is_union() { return true; } } return false; } - -fn is_union(ty: Ty<'_>) -> bool { - match ty.kind() { - ty::Adt(def, _) if def.is_union() => true, - _ => false, - } -} diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index d009b0b1b23..835789069bb 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -11,8 +11,9 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef, - Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, + PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, + TerminatorKind, }; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable}; @@ -217,6 +218,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.super_operand(operand, location); } + fn visit_projection_elem( + &mut self, + local: Local, + proj_base: &[PlaceElem<'tcx>], + elem: PlaceElem<'tcx>, + context: PlaceContext, + location: Location, + ) { + if let ProjectionElem::Index(index) = elem { + let index_ty = self.body.local_decls[index].ty; + if index_ty != self.tcx.types.usize { + self.fail(location, format!("bad index ({:?} != usize)", index_ty)) + } + } + self.super_projection_elem(local, proj_base, elem, context, location); + } + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match &statement.kind { StatementKind::Assign(box (dest, rvalue)) => { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 2185bd3a5c6..69786c14ee8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -186,25 +186,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // }; // ``` // - // FIXME(RFC2229, rust#85435): Remove feature gate once diagnostics are - // improved and unsafe checking works properly in closure bodies again. - if this.tcx.features().capture_disjoint_fields { - for (thir_place, cause, hir_id) in fake_reads.into_iter() { - let place_builder = - unpack!(block = this.as_place_builder(block, &this.thir[*thir_place])); - - if let Ok(place_builder_resolved) = - place_builder.try_upvars_resolved(this.tcx, this.typeck_results) - { - let mir_place = - place_builder_resolved.into_place(this.tcx, this.typeck_results); - this.cfg.push_fake_read( - block, - this.source_info(this.tcx.hir().span(*hir_id)), - *cause, - mir_place, - ); - } + for (thir_place, cause, hir_id) in fake_reads.into_iter() { + let place_builder = + unpack!(block = this.as_place_builder(block, &this.thir[*thir_place])); + + if let Ok(place_builder_resolved) = + place_builder.try_upvars_resolved(this.tcx, this.typeck_results) + { + let mir_place = + place_builder_resolved.into_place(this.tcx, this.typeck_results); + this.cfg.push_fake_read( + block, + this.source_info(this.tcx.hir().span(*hir_id)), + *cause, + mir_place, + ); } } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d1aaabe92ed..2d52577829c 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -166,13 +166,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(expr.span, CallToUnsafeFunction); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { // If the called function has target features the calling function hasn't, - // the call requires `unsafe`. - if !self - .tcx - .codegen_fn_attrs(func_did) - .target_features - .iter() - .all(|feature| self.body_target_features.contains(feature)) + // the call requires `unsafe`. Don't check this on wasm + // targets, though. For more information on wasm see the + // is_like_wasm check in typeck/src/collect.rs + if !self.tcx.sess.target.options.is_like_wasm + && !self + .tcx + .codegen_fn_attrs(func_did) + .target_features + .iter() + .all(|feature| self.body_target_features.contains(feature)) { self.requires_unsafe(expr.span, CallToFunctionWith); } diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 99b854ff066..d2992f0bf18 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,17 +1,14 @@ //! Construction of MIR from HIR. //! //! This crate also contains the match exhaustiveness and usefulness checking. -#![feature(array_windows)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_panic)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![feature(iter_zip)] #![feature(once_cell)] #![feature(min_specialization)] -#![feature(trusted_step)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index da642bb2d28..51df06bd989 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -3,7 +3,6 @@ #![feature(array_windows)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] -#![feature(iter_order_by)] #![feature(box_syntax)] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 4803148eba9..28633faa205 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,13 +5,11 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] #![feature(nll)] #![feature(min_specialization)] -#![feature(trusted_step)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index f41e0e03706..29a0a3c48e5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -828,7 +828,11 @@ impl Visitor<'tcx> for Checker<'tcx> { fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { - self.tcx.check_stability(def_id, Some(id), path.span, None) + let method_span = match path.segments { + [.., _, last] => Some(last.ident.span), + _ => None, + }; + self.tcx.check_stability(def_id, Some(id), path.span, method_span) } intravisit::walk_path(self, path) } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index ac81c0261e2..4175fb6925a 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -2,13 +2,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(in_band_lifetimes)] -#![feature(exhaustive_patterns)] #![feature(nll)] #![feature(min_specialization)] -#![feature(crate_visibility_modifier)] -#![feature(once_cell)] #![feature(rustc_attrs)] -#![feature(never_type)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 2517793ecea..95edc1e93a5 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -61,7 +61,7 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { match def_key.disambiguated_data.data { DefPathData::CrateRoot => { - crate_name = self.tcx.original_crate_name(def_id.krate).as_str(); + crate_name = self.tcx.crate_name(def_id.krate).as_str(); name = &*crate_name; dis = ""; end_index = 3; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 7df3804c986..0d4fb34265c 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,12 +1,8 @@ #![feature(bool_to_option)] -#![feature(const_panic)] #![feature(core_intrinsics)] -#![feature(drain_filter)] #![feature(hash_raw_entry)] #![feature(iter_zip)] #![feature(min_specialization)] -#![feature(stmt_expr_attributes)] -#![feature(trusted_step)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a1eafd65d64..03d94f43897 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -450,7 +450,7 @@ impl<'a> Resolver<'a> { err.span_label(shadowed_binding_span, msg); err } - ResolutionError::ForwardDeclaredTyParam => { + ResolutionError::ForwardDeclaredGenericParam => { let mut err = struct_span_err!( self.session, span, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 86431b44fd6..41935e7d6df 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -242,7 +242,7 @@ enum ResolutionError<'a> { shadowed_binding_span: Span, }, /// Error E0128: generic parameters with a default cannot use forward-declared identifiers. - ForwardDeclaredTyParam, // FIXME(const_generics_defaults) + ForwardDeclaredGenericParam, /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), /// generic parameters must not be used inside const evaluations. @@ -2608,7 +2608,7 @@ impl<'a> Resolver<'a> { let res_error = if rib_ident.name == kw::SelfUpper { ResolutionError::SelfInTyParamDefault } else { - ResolutionError::ForwardDeclaredTyParam + ResolutionError::ForwardDeclaredGenericParam }; self.report_error(span, res_error); } diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index cf5a9118275..c79786a839f 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -14,10 +14,7 @@ Core encoding and decoding interfaces. #![feature(nll)] #![feature(associated_type_bounds)] #![feature(min_specialization)] -#![feature(vec_spare_capacity)] #![feature(core_intrinsics)] -#![feature(maybe_uninit_array_assume_init)] -#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_slice)] #![feature(new_uninit)] #![cfg_attr(test, feature(test))] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index dc15c531d1e..51a53918f07 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -16,12 +16,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(crate_visibility_modifier)] -#![feature(const_panic)] #![feature(negative_impls)] #![feature(nll)] #![feature(min_specialization)] #![feature(thread_local_const_init)] -#![feature(trusted_step)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 1addfc8ee67..0c64fe6ea60 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -254,7 +254,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { } fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> { - self.write_str(&self.tcx.original_crate_name(cnum).as_str())?; + self.write_str(&self.tcx.crate_name(cnum).as_str())?; Ok(self) } fn path_qualified( diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 2ab7461fc60..e7da56ed0f3 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -594,7 +594,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.to_u64()); - let name = self.tcx.original_crate_name(cnum).as_str(); + let name = self.tcx.crate_name(cnum).as_str(); self.push_ident(&name); Ok(self) } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a40de5ef18e..cb8f6b9656c 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,13 +9,11 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] -#![feature(const_panic)] #![feature(nll)] #![feature(never_type)] #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] #![feature(min_specialization)] -#![feature(trusted_step)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index 2218c6c6da7..5682039b865 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -10,7 +10,6 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), - eliminate_frame_pointer: false, max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs index 758950bd344..8a832546d09 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -10,7 +10,6 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".to_string(), - eliminate_frame_pointer: false, max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index e594ceec1b7..2187015b627 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -18,7 +18,6 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), - eliminate_frame_pointer: false, max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index a83de77dc2a..cb6c06b3711 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -10,7 +10,6 @@ pub fn target() -> Target { arch: "aarch64".to_string(), options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), - eliminate_frame_pointer: false, max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 45c5c1a16e9..8530db179d9 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -27,6 +27,7 @@ pub fn opts(os: &str) -> TargetOptions { families: vec!["unix".to_string()], is_like_osx: true, dwarf_version: Some(2), + eliminate_frame_pointer: false, has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index 538c4ca8697..e7f7bb343d0 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -44,7 +44,6 @@ pub fn opts(os: &str, arch: Arch) -> TargetOptions { executables: true, link_env_remove: link_env_remove(arch), has_elf_tls: false, - eliminate_frame_pointer: false, ..super::apple_base::opts(os) } } diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 3f24a33f7d5..ac2e0ebae32 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; use rustc_session::DiagnosticMessageId; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; #[derive(Copy, Clone, Debug)] @@ -231,7 +232,8 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa .span_label(span, "deref recursion limit reached") .help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", - suggested_limit, tcx.crate_name, + suggested_limit, + tcx.crate_name(LOCAL_CRATE), )) .emit(); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 8bbd2da5375..5c35b515f3d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{ Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; @@ -2313,7 +2314,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let suggested_limit = current_limit * 2; err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", - suggested_limit, self.tcx.crate_name, + suggested_limit, + self.tcx.crate_name(LOCAL_CRATE), )); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index f38c5d8f2f7..07a3132568b 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,12 +1,11 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::map as hir_map; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, }; -use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_trait_selection::traits; @@ -388,11 +387,6 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE tcx.param_env(def_id).with_reveal_all_normalized(tcx) } -fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol { - assert_eq!(crate_num, LOCAL_CRATE); - tcx.crate_name -} - fn instance_def_size_estimate<'tcx>( tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>, @@ -538,7 +532,6 @@ pub fn provide(providers: &mut ty::query::Providers) { param_env, param_env_reveal_all_normalized, trait_of_item, - original_crate_name, instance_def_size_estimate, issue33140_self_ty, impl_defaultness, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 3f4c8a72f1d..2d102127dd9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,5 +1,4 @@ #![feature(min_specialization)] -#![feature(trusted_step)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e5fcdcfa743..9cc435a0dec 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -8,6 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; +use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; @@ -412,14 +413,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, expected: Ty<'tcx>, ) -> Option<(Span, &'static str, String, Applicability)> { - let sm = self.sess().source_map(); + let sess = self.sess(); let sp = expr.span; - if sm.is_imported(sp) { - // Ignore if span is from within a macro #41858, #58298. We previously used the macro - // call span, but that breaks down when the type error comes from multiple calls down. + + // If the span is from an external macro, there's no suggestion we can make. + if in_external_macro(sess, sp) { return None; } + let sm = sess.source_map(); + let replace_prefix = |s: &str, old: &str, new: &str| { s.strip_prefix(old).map(|stripped| new.to_string() + stripped) }; @@ -427,10 +430,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp); - // If the span is from a macro, then it's hard to extract the text - // and make a good suggestion, so don't bother. - let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none(); - // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. let expr = expr.peel_drop_temps(); @@ -570,10 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr), _, &ty::Ref(_, checked, _), - ) if { - self.infcx.can_sub(self.param_env, checked, &expected).is_ok() && !is_macro - } => - { + ) if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() => { // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest removing a `&`. if sm.is_imported(expr.span) { @@ -589,13 +585,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } return None; } - if let Ok(code) = sm.span_to_snippet(expr.span) { - return Some(( - sp, - "consider removing the borrow", - code, - Applicability::MachineApplicable, - )); + if sp.contains(expr.span) { + if let Ok(code) = sm.span_to_snippet(expr.span) { + return Some(( + sp, + "consider removing the borrow", + code, + Applicability::MachineApplicable, + )); + } } } ( @@ -643,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - _ if sp == expr.span && !is_macro => { + _ if sp == expr.span => { if let Some(steps) = self.deref_steps(checked_ty, expected) { let expr = expr.peel_blocks(); diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index a63aec07ad1..652b82f1063 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Clear previous flag; after a pointer indirection it does not apply any more. inside_union = false; } - if source.ty_adt_def().map_or(false, |adt| adt.is_union()) { + if source.is_union() { inside_union = true; } // Fix up the autoderefs. Autorefs can only occur immediately preceding diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 71e222c560a..6baa185406e 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -1588,6 +1588,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) { if let PlaceBase::Upvar(_) = place.base { + // We need to restrict Fake Read precision to avoid fake reading unsafe code, + // such as deref of a raw pointer. + let place = restrict_capture_precision(place); + let place = + restrict_repr_packed_field_ref_capture(self.fcx.tcx, self.fcx.param_env, &place); self.fake_reads.push((place, cause, diag_expr_id)); } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0528f8812f9..5d83375e5a1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2770,7 +2770,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } else if tcx.sess.check_name(attr, sym::target_feature) { if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { - if !tcx.features().target_feature_11 { + if tcx.sess.target.is_like_wasm { + // The `#[target_feature]` attribute is allowed on + // WebAssembly targets on all functions, including safe + // ones. Other targets require that `#[target_feature]` is + // only applied to unsafe funtions (pending the + // `target_feature_11` feature) because on most targets + // execution of instructions that are not supported is + // considered undefined behavior. For WebAssembly which is a + // 100% safe target at execution time it's not possible to + // execute undefined instructions, and even if a future + // feature was added in some form for this it would be a + // deterministic trap. There is no undefined behavior when + // executing WebAssembly so `#[target_feature]` is allowed + // on safe functions (but again, only for WebAssembly) + } else if !tcx.features().target_feature_11 { let mut err = feature_err( &tcx.sess.parse_sess, sym::target_feature_11, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 7d6fbf1c438..5d03be35e46 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2416,7 +2416,6 @@ impl<T> VecDeque<T> { /// found; the fourth could match any position in `[1, 4]`. /// /// ``` - /// #![feature(vecdeque_binary_search)] /// use std::collections::VecDeque; /// /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); @@ -2432,7 +2431,6 @@ impl<T> VecDeque<T> { /// sort order: /// /// ``` - /// #![feature(vecdeque_binary_search)] /// use std::collections::VecDeque; /// /// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); @@ -2441,7 +2439,7 @@ impl<T> VecDeque<T> { /// deque.insert(idx, num); /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); /// ``` - #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] #[inline] pub fn binary_search(&self, x: &T) -> Result<usize, usize> where @@ -2476,7 +2474,6 @@ impl<T> VecDeque<T> { /// found; the fourth could match any position in `[1, 4]`. /// /// ``` - /// #![feature(vecdeque_binary_search)] /// use std::collections::VecDeque; /// /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); @@ -2487,7 +2484,7 @@ impl<T> VecDeque<T> { /// let r = deque.binary_search_by(|x| x.cmp(&1)); /// assert!(matches!(r, Ok(1..=4))); /// ``` - #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize> where F: FnMut(&'a T) -> Ordering, @@ -2530,7 +2527,6 @@ impl<T> VecDeque<T> { /// fourth could match any position in `[1, 4]`. /// /// ``` - /// #![feature(vecdeque_binary_search)] /// use std::collections::VecDeque; /// /// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1), @@ -2543,7 +2539,7 @@ impl<T> VecDeque<T> { /// let r = deque.binary_search_by_key(&1, |&(a, b)| b); /// assert!(matches!(r, Ok(1..=4))); /// ``` - #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] #[inline] pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize> where @@ -2574,7 +2570,6 @@ impl<T> VecDeque<T> { /// # Examples /// /// ``` - /// #![feature(vecdeque_binary_search)] /// use std::collections::VecDeque; /// /// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into(); @@ -2584,7 +2579,7 @@ impl<T> VecDeque<T> { /// assert!(deque.iter().take(i).all(|&x| x < 5)); /// assert!(deque.iter().skip(i).all(|&x| !(x < 5))); /// ``` - #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[stable(feature = "vecdeque_binary_search", since = "1.54.0")] pub fn partition_point<P>(&self, mut pred: P) -> usize where P: FnMut(&T) -> bool, diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 73d15d30647..64943a273c9 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -5,6 +5,12 @@ use super::Vec; #[stable(feature = "cow_from_vec", since = "1.8.0")] impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a slice. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed fn from(s: &'a [T]) -> Cow<'a, [T]> { Cow::Borrowed(s) } @@ -12,6 +18,12 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { #[stable(feature = "cow_from_vec", since = "1.8.0")] impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> { + /// Creates an [`Owned`] variant of [`Cow`] + /// from an owned instance of [`Vec`]. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Owned`]: crate::borrow::Cow::Owned fn from(v: Vec<T>) -> Cow<'a, [T]> { Cow::Owned(v) } @@ -19,6 +31,12 @@ impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> { #[stable(feature = "cow_from_vec_ref", since = "1.28.0")] impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> { + /// Creates a [`Borrowed`] variant of [`Cow`] + /// from a reference to [`Vec`]. + /// + /// This conversion does not allocate or clone the data. + /// + /// [`Borrowed`]: crate::borrow::Cow::Borrowed fn from(v: &'a Vec<T>) -> Cow<'a, [T]> { Cow::Borrowed(v.as_slice()) } diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index bbfcc68daef..efa6868473e 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -1,6 +1,5 @@ use core::mem::ManuallyDrop; use core::ptr::{self}; -use core::slice::{self}; use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; @@ -19,9 +18,7 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; /// |where I: | | |where I: | /// | Iterator (default)----------+ | | Iterator (default) | /// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | | | -/// | slice::Iter | | | -/// | Iterator<Item = &Clone> | +---------------------+ +/// | SourceIterMarker---fallback-+ | +---------------------+ /// +---------------------------------+ /// ``` pub(super) trait SpecFromIter<T, I> { @@ -65,33 +62,3 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> { vec } } - -impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T> -where - I: Iterator<Item = &'a T>, - T: Clone, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIter::from_iter(iterator.cloned()) - } -} - -// This utilizes `iterator.as_slice().to_vec()` since spec_extend -// must take more steps to reason about the final capacity + length -// and thus do more work. `to_vec()` directly allocates the correct amount -// and fills it exactly. -impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> { - #[cfg(not(test))] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - iterator.as_slice().to_vec() - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global) - } -} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 25a83a0b014..3143afa269d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -17,7 +17,6 @@ #![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] #![feature(iter_map_while)] -#![feature(vecdeque_binary_search)] #![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(vec_spare_capacity)] diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 2f8f504d8fc..c95324c80ba 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -434,7 +434,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B /// called on `self`: /// * `std::clone::Clone::clone()` /// * `std::iter::Iterator::size_hint()` -/// * `std::iter::Iterator::next_back()` +/// * `std::iter::DoubleEndedIterator::next_back()` /// * `std::iter::Iterator::__iterator_get_unchecked()` /// * `std::iter::TrustedRandomAccess::size()` /// diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 77132cddca2..c47a2e8b05c 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -727,8 +727,8 @@ impl f32 { /// /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms. /// - /// See `from_bits` for some discussion of the portability of this operation - /// (there are almost no issues). + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 4c3f1fd16a0..cfcc08b9add 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -741,8 +741,8 @@ impl f64 { /// /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms. /// - /// See `from_bits` for some discussion of the portability of this operation - /// (there are almost no issues). + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index b0dc9903464..b36d6f0d404 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -114,3 +114,16 @@ fn any_unsized() { fn is_any<T: Any + ?Sized>() {} is_any::<[i32]>(); } + +#[test] +fn distinct_type_names() { + // https://github.com/rust-lang/rust/issues/84666 + + struct Velocity(f32, f32); + + fn type_name_of_val<T>(_: T) -> &'static str { + type_name::<T>() + } + + assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),); +} diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 030892a432b..89280149a03 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -149,4 +149,57 @@ <Synthetic Name="[...]"><DisplayString>...</DisplayString></Synthetic> </Expand> </Type> + <Type Name="enum$<*>"> + <Intrinsic Name="tag" Expression="variant0.variant$" /> + <DisplayString Condition="tag() == 0">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 3" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 4" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 5" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 6" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 7" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 8" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 9" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 10" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 11" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 12" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 13" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 14" Optional="true">{tag(),en}</DisplayString> + <DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString> + + <Expand> + <ExpandedItem Condition="tag() == 0">variant0</ExpandedItem> + <ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem> + <ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem> + <ExpandedItem Condition="tag() == 3" Optional="true">variant3</ExpandedItem> + <ExpandedItem Condition="tag() == 4" Optional="true">variant4</ExpandedItem> + <ExpandedItem Condition="tag() == 5" Optional="true">variant5</ExpandedItem> + <ExpandedItem Condition="tag() == 6" Optional="true">variant6</ExpandedItem> + <ExpandedItem Condition="tag() == 7" Optional="true">variant7</ExpandedItem> + <ExpandedItem Condition="tag() == 8" Optional="true">variant8</ExpandedItem> + <ExpandedItem Condition="tag() == 9" Optional="true">variant9</ExpandedItem> + <ExpandedItem Condition="tag() == 10" Optional="true">variant10</ExpandedItem> + <ExpandedItem Condition="tag() == 11" Optional="true">variant11</ExpandedItem> + <ExpandedItem Condition="tag() == 12" Optional="true">variant12</ExpandedItem> + <ExpandedItem Condition="tag() == 13" Optional="true">variant13</ExpandedItem> + <ExpandedItem Condition="tag() == 14" Optional="true">variant14</ExpandedItem> + <ExpandedItem Condition="tag() == 15" Optional="true">variant15</ExpandedItem> + </Expand> + </Type> + + <!-- $T1 is the name of the enum, $T2 is the low value of the dataful variant tag, + $T3 is the high value of the dataful variant tag, $T4 is the name of the dataful variant --> + <Type Name="enum$<*, *, *, *>"> + <Intrinsic Name="tag" Expression="discriminant" /> + <Intrinsic Name="is_dataful" Expression="tag() >= $T2 && tag() <= $T3" /> + <DisplayString Condition="is_dataful()">{"$T4",sb}({dataful_variant})</DisplayString> + <DisplayString Condition="!is_dataful()">{discriminant,en}</DisplayString> + <Expand> + <ExpandedItem Condition="is_dataful()">dataful_variant</ExpandedItem> + <Synthetic Condition="is_dataful()" Name="[variant]"> + <DisplayString>{"$T4",sb}</DisplayString> + </Synthetic> + </Expand> + </Type> </AutoVisualizer> diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 9c3c26f5978..17667770520 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -14,14 +14,6 @@ </Expand> </Type> - <Type Name="core::option::Option<*>"> - <DisplayString Condition="RUST$ENUM$DISR == 0x0">None</DisplayString> - <DisplayString Condition="RUST$ENUM$DISR == 0x1">Some({__0})</DisplayString> - <Expand> - <Item Name="[value]" ExcludeView="simple" Condition="RUST$ENUM$DISR == 1">__0</Item> - </Expand> - </Type> - <Type Name="core::option::Option<*>" Priority="MediumLow"> <DisplayString Condition="*(void**)this == nullptr">None</DisplayString> <DisplayString>Some({($T1 *)this})</DisplayString> @@ -30,15 +22,6 @@ </Expand> </Type> - <Type Name="core::result::Result<*>"> - <DisplayString Condition="RUST$ENUM$DISR == 0x0">Ok({__0})</DisplayString> - <DisplayString Condition="RUST$ENUM$DISR == 0x1">Err({(*($T2*) &__0)})</DisplayString> - <Expand> - <Item Name="[value]" Condition="RUST$ENUM$DISR == 0x0">__0</Item> - <Item Name="[value]" Condition="RUST$ENUM$DISR == 0x1">(*($T2*) &__0)</Item> - </Expand> - </Type> - <Type Name="core::ptr::non_null::NonNull<*>"> <DisplayString>{(void*) pointer}</DisplayString> <Expand> diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a14eefaf571..111827aacdf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -527,7 +527,7 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St } fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind { - let imported_from = cx.tcx.original_crate_name(did.krate); + let imported_from = cx.tcx.crate_name(did.krate); match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) { LoadedMacro::MacroDef(def, _) => { let matchers: Vec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index de88e249b67..3ae516bd6df 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -526,7 +526,6 @@ impl Item { crate fn is_crate(&self) -> bool { self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX) } - crate fn is_mod(&self) -> bool { self.type_() == ItemType::Module } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index ec04c94dc11..429863f3635 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -119,7 +119,7 @@ crate fn render<T: Print, S: Print>( {after_content}\ <div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \ data-search-index-js=\"{root_path}search-index{suffix}.js\" \ - data-search-js=\"{static_root_path}search{suffix}.js\"></div> + data-search-js=\"{static_root_path}search{suffix}.js\"></div>\ <script src=\"{static_root_path}main{suffix}.js\"></script>\ {extra_scripts}\ </body>\ @@ -235,6 +235,7 @@ crate fn redirect(url: &str) -> String { <html lang="en"> <head> <meta http-equiv="refresh" content="0;URL={url}"> + <title>Redirection</title> </head> <body> <p>Redirecting to <a href="{url}">{url}</a>...</p> diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 8676efd9fa8..d80b2db00ac 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -200,8 +200,15 @@ impl<'tcx> Context<'tcx> { ) }; let keywords = make_item_keywords(it); + let name; + let tyname_s = if it.is_crate() { + name = format!("{} crate", tyname); + name.as_str() + } else { + tyname.as_str() + }; let page = layout::Page { - css_class: tyname.as_str(), + css_class: tyname_s, root_path: &self.root_path(), static_root_path: self.shared.static_root_path.as_deref(), title: &title, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fa63286e4f5..10f5184e39a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1369,7 +1369,11 @@ fn render_impl( }) }) .map(|item| format!("{}.{}", item.type_(), name)); - write!(w, "<h4 id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,); + write!( + w, + "<div id=\"{}\" class=\"{}{} has-srclink\">", + id, item_type, in_trait_class, + ); w.write_str("<code>"); render_assoc_item( w, @@ -1388,13 +1392,17 @@ fn render_impl( ); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); write_srclink(cx, item, w); - w.write_str("</h4>"); + w.write_str("</div>"); } } clean::TypedefItem(ref tydef, _) => { let source_id = format!("{}.{}", ItemType::AssocType, name); let id = cx.derive_id(source_id.clone()); - write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class); + write!( + w, + "<div id=\"{}\" class=\"{}{} has-srclink\"><code>", + id, item_type, in_trait_class + ); assoc_type( w, item, @@ -1406,12 +1414,16 @@ fn render_impl( ); w.write_str("</code>"); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); - w.write_str("</h4>"); + w.write_str("</div>"); } clean::AssocConstItem(ref ty, ref default) => { let source_id = format!("{}.{}", item_type, name); let id = cx.derive_id(source_id.clone()); - write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class); + write!( + w, + "<div id=\"{}\" class=\"{}{} has-srclink\"><code>", + id, item_type, in_trait_class + ); assoc_const( w, item, @@ -1431,12 +1443,12 @@ fn render_impl( ); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); write_srclink(cx, item, w); - w.write_str("</h4>"); + w.write_str("</div>"); } clean::AssocTypeItem(ref bounds, ref default) => { let source_id = format!("{}.{}", item_type, name); let id = cx.derive_id(source_id.clone()); - write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class); + write!(w, "<div id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class,); assoc_type( w, item, @@ -1448,7 +1460,7 @@ fn render_impl( ); w.write_str("</code>"); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); - w.write_str("</h4>"); + w.write_str("</div>"); } clean::StrippedItem(..) => return, _ => panic!("can't make docs for trait item with name {:?}", item.name), @@ -1577,7 +1589,8 @@ fn render_impl( if let Some(use_absolute) = use_absolute { write!( w, - "{}<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">", + "{}<div id=\"{}\" class=\"impl has-srclink\"{}>\ + <code class=\"in-band\">", open_details(&mut close_tags, is_implementing_trait), id, aliases @@ -1604,7 +1617,8 @@ fn render_impl( } else { write!( w, - "{}<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">{}</code>", + "{}<div id=\"{}\" class=\"impl has-srclink\"{}>\ + <code class=\"in-band\">{}</code>", open_details(&mut close_tags, is_implementing_trait), id, aliases, @@ -1621,9 +1635,9 @@ fn render_impl( ); write_srclink(cx, &i.impl_item, w); if !toggled { - w.write_str("</h3>"); + w.write_str("</div>"); } else { - w.write_str("</h3></summary>"); + w.write_str("</div></summary>"); } if trait_.is_some() { @@ -1649,10 +1663,12 @@ fn render_impl( ); } } - w.write_str("<div class=\"impl-items\">"); - w.push_buffer(default_impl_items); - w.push_buffer(impl_items); - close_tags.insert_str(0, "</div>"); + if !default_impl_items.is_empty() || !impl_items.is_empty() { + w.write_str("<div class=\"impl-items\">"); + w.push_buffer(default_impl_items); + w.push_buffer(impl_items); + close_tags.insert_str(0, "</div>"); + } w.write_str(&close_tags); } @@ -1697,7 +1713,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { "<div class=\"block version\">\ <p>Version {}</p>\ </div>", - Escape(version) + Escape(version), ); } } @@ -1707,9 +1723,10 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { write!( buffer, "<a id=\"all-types\" href=\"all.html\"><p>See all {}'s items</p></a>", - it.name.as_ref().expect("crates always have a name") + it.name.as_ref().expect("crates always have a name"), ); } + match *it.kind { clean::StructItem(ref s) => sidebar_struct(cx, buffer, it, s), clean::TraitItem(ref t) => sidebar_trait(cx, buffer, it, t), @@ -1719,7 +1736,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { clean::TypedefItem(_, _) => sidebar_typedef(cx, buffer, it), clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items), clean::ForeignTypeItem => sidebar_foreign_type(cx, buffer, it), - _ => (), + _ => {} } // The sidebar is designed to display sibling functions, modules and @@ -1730,22 +1747,24 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { // as much HTML as possible in order to allow non-JS-enabled browsers // to navigate the documentation (though slightly inefficiently). - buffer.write_str("<p class=\"location\">"); - for (i, name) in cx.current.iter().take(parentlen).enumerate() { - if i > 0 { - buffer.write_str("::<wbr>"); + if !it.is_mod() { + buffer.write_str("<p class=\"location\">Other items in<br>"); + for (i, name) in cx.current.iter().take(parentlen).enumerate() { + if i > 0 { + buffer.write_str("::<wbr>"); + } + write!( + buffer, + "<a href=\"{}index.html\">{}</a>", + &cx.root_path()[..(cx.current.len() - i - 1) * 3], + *name + ); } - write!( - buffer, - "<a href=\"{}index.html\">{}</a>", - &cx.root_path()[..(cx.current.len() - i - 1) * 3], - *name - ); + buffer.write_str("</p>"); } - buffer.write_str("</p>"); // Sidebar refers to the enclosing module, not this module. - let relpath = if it.is_mod() { "../" } else { "" }; + let relpath = if it.is_mod() && parentlen != 0 { "./" } else { "" }; write!( buffer, "<div id=\"sidebar-vars\" data-name=\"{name}\" data-ty=\"{ty}\" data-relpath=\"{path}\">\ @@ -1754,17 +1773,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { ty = it.type_(), path = relpath ); - - if parentlen == 0 { - write!( - buffer, - "<script defer src=\"{}sidebar-items{}.js\"></script>", - relpath, cx.shared.resource_suffix - ); - } else { - write!(buffer, "<script defer src=\"{}sidebar-items.js\"></script>", relpath); - } - + write!(buffer, "<script defer src=\"{}sidebar-items.js\"></script>", relpath); // Closes sidebar-elems div. buffer.write_str("</div>"); } @@ -2272,8 +2281,8 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean: } } -fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { - match *ty { +fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) { + match ty { ItemType::ExternCrate | ItemType::Import => ("reexports", "Re-exports"), ItemType::Module => ("modules", "Modules"), ItemType::Struct => ("structs", "Structs"), @@ -2305,10 +2314,14 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { let mut sidebar = String::new(); + // Re-exports are handled a bit differently because they can be extern crates or imports. if items.iter().any(|it| { - it.type_() == ItemType::ExternCrate || (it.type_() == ItemType::Import && !it.is_stripped()) + it.name.is_some() + && (it.type_() == ItemType::ExternCrate + || (it.type_() == ItemType::Import && !it.is_stripped())) }) { - sidebar.push_str("<li><a href=\"#reexports\">Re-exports</a></li>"); + let (id, name) = item_ty_to_strs(ItemType::Import); + sidebar.push_str(&format!("<li><a href=\"#{}\">{}</a></li>", id, name)); } // ordering taken from item_module, reorder, where it prioritized elements in a certain order @@ -2335,13 +2348,9 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { ItemType::ForeignType, ItemType::Keyword, ] { - if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) { - let (short, name) = item_ty_to_strs(&myty); - sidebar.push_str(&format!( - "<li><a href=\"#{id}\">{name}</a></li>", - id = short, - name = name - )); + if items.iter().any(|it| !it.is_stripped() && it.type_() == myty && it.name.is_some()) { + let (id, name) = item_ty_to_strs(myty); + sidebar.push_str(&format!("<li><a href=\"#{}\">{}</a></li>", id, name)); } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 42d7e9c8c93..1c5d9a26441 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -75,7 +75,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, ); } } - write!(buf, "<a class=\"{}\" href=\"\">{}</a>", item.type_(), item.name.as_ref().unwrap()); + write!(buf, "<a class=\"{}\" href=\"#\">{}</a>", item.type_(), item.name.as_ref().unwrap()); write!( buf, "<button id=\"copy-path\" onclick=\"copy_path(this)\">\ @@ -263,7 +263,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl w.write_str("</table>"); } curty = myty; - let (short, name) = item_ty_to_strs(&myty.unwrap()); + let (short, name) = item_ty_to_strs(myty.unwrap()); write!( w, "<h2 id=\"{id}\" class=\"section-header\">\ @@ -585,12 +585,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra if toggled { write!(w, "<details class=\"rustdoc-toggle\" open><summary>"); } - write!(w, "<h3 id=\"{id}\" class=\"method\"><code>", id = id); + write!(w, "<div id=\"{}\" class=\"method has-srclink\"><code>", id); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx); w.write_str("</code>"); render_stability_since(w, m, t, cx.tcx()); write_srclink(cx, m, w); - w.write_str("</h3>"); + w.write_str("</div>"); if toggled { write!(w, "</summary>"); w.push_buffer(content); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 73ffec0dd4e..a4188e6b203 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -227,7 +227,6 @@ pub(super) fn write_shared( )?; write_minify("search.js", static_files::SEARCH_JS)?; write_minify("settings.js", static_files::SETTINGS_JS)?; - write_minify("sidebar-items.js", static_files::sidebar::ITEMS)?; if cx.shared.include_sources { write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?; diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a96b0c87108..1a15a444a70 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -561,41 +561,40 @@ function hideThemeButtonState() { } }()); - function addSidebarCrates(crates) { - // Draw a convenient sidebar of known crates if we have a listing - if (window.rootPath === "../" || window.rootPath === "./") { - var sidebar = document.getElementsByClassName("sidebar-elems")[0]; - if (sidebar) { - var div = document.createElement("div"); - div.className = "block crate"; - div.innerHTML = "<h3>Crates</h3>"; - var ul = document.createElement("ul"); - div.appendChild(ul); - - for (var i = 0; i < crates.length; ++i) { - var klass = "crate"; - if (window.rootPath !== "./" && crates[i] === window.currentCrate) { - klass += " current"; - } - var link = document.createElement("a"); - link.href = window.rootPath + crates[i] + "/index.html"; - link.className = klass; - link.textContent = crates[i]; - - var li = document.createElement("li"); - li.appendChild(link); - ul.appendChild(li); - } - sidebar.appendChild(div); - } - } - } - // delayed sidebar rendering. window.initSidebarItems = function(items) { var sidebar = document.getElementsByClassName("sidebar-elems")[0]; var current = window.sidebarCurrent; + function addSidebarCrates(crates) { + if (!hasClass(document.body, "crate")) { + // We only want to list crates on the crate page. + return; + } + // Draw a convenient sidebar of known crates if we have a listing + var div = document.createElement("div"); + div.className = "block crate"; + div.innerHTML = "<h3>Crates</h3>"; + var ul = document.createElement("ul"); + div.appendChild(ul); + + for (var i = 0; i < crates.length; ++i) { + var klass = "crate"; + if (window.rootPath !== "./" && crates[i] === window.currentCrate) { + klass += " current"; + } + var link = document.createElement("a"); + link.href = window.rootPath + crates[i] + "/index.html"; + link.className = klass; + link.textContent = crates[i]; + + var li = document.createElement("li"); + li.appendChild(link); + ul.appendChild(li); + } + sidebar.appendChild(div); + } + function block(shortty, longty) { var filtered = items[shortty]; if (!filtered) { @@ -634,28 +633,32 @@ function hideThemeButtonState() { ul.appendChild(li); } div.appendChild(ul); - if (sidebar) { - sidebar.appendChild(div); - } + sidebar.appendChild(div); } - block("primitive", "Primitive Types"); - block("mod", "Modules"); - block("macro", "Macros"); - block("struct", "Structs"); - block("enum", "Enums"); - block("union", "Unions"); - block("constant", "Constants"); - block("static", "Statics"); - block("trait", "Traits"); - block("fn", "Functions"); - block("type", "Type Definitions"); - block("foreigntype", "Foreign Types"); - block("keyword", "Keywords"); - block("traitalias", "Trait Aliases"); - - // `crates{version}.js` should always be loaded before this script, so we can use it safely. - addSidebarCrates(window.ALL_CRATES); + if (sidebar) { + var isModule = hasClass(document.body, "mod"); + if (!isModule) { + block("primitive", "Primitive Types"); + block("mod", "Modules"); + block("macro", "Macros"); + block("struct", "Structs"); + block("enum", "Enums"); + block("union", "Unions"); + block("constant", "Constants"); + block("static", "Statics"); + block("trait", "Traits"); + block("fn", "Functions"); + block("type", "Type Definitions"); + block("foreigntype", "Foreign Types"); + block("keyword", "Keywords"); + block("traitalias", "Trait Aliases"); + } + + // `crates{version}.js` should always be loaded before this script, so we can use + // it safely. + addSidebarCrates(window.ALL_CRATES); + } }; window.register_implementors = function(imp) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 2623ff27a25..d3f8a7aa67d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -117,8 +117,7 @@ h2 { h3 { font-size: 1.3em; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable), -h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant):not(.associatedtype) { +h1, h2, h3, h4 { font-weight: 500; margin: 20px 0 15px 0; padding-bottom: 6px; @@ -135,30 +134,38 @@ h1.fqn { h1.fqn > .in-band > a:hover { text-decoration: underline; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant):not(.associatedtype) { +h2, h3, h4 { border-bottom: 1px solid; } -h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant, h4.associatedtype { +.impl, .method, +.type, .associatedconstant, +.associatedtype { flex-basis: 100%; font-weight: 600; margin-top: 16px; margin-bottom: 10px; position: relative; } -h3.impl, h3.method, h4.method.trait-impl, h3.type, -h4.type.trait-impl, h4.associatedconstant.trait-impl, h4.associatedtype.trait-impl { +.impl, .method.trait-impl, +.type.trait-impl, +.associatedconstant.trait-impl, +.associatedtype.trait-impl { padding-left: 15px; } +div.impl-items > div { + padding-left: 0; +} + h1, h2, h3, h4, .sidebar, a.source, .search-input, .search-results .result-name, .content table td:first-child > a, -div.item-list .out-of-band, +div.item-list .out-of-band, span.since, #source-sidebar, #sidebar-toggle, details.rustdoc-toggle > summary::before, details.undocumented > summary::before, -.content ul.crate a.crate, +div.impl-items > div:not(.docblock):not(.item-info), +.content ul.crate a.crate, a.srclink, /* This selector is for the items listed in the "all items" page. */ #main > ul.docblock > li > a { font-family: "Fira Sans", Arial, sans-serif; @@ -304,17 +311,18 @@ nav.sub { border: none; } -.location a:first-child { +.location a:first-of-type { font-weight: 500; } +.location a:hover { + text-decoration: underline; +} .block { padding: 0; margin-bottom: 14px; } .block h2, .block h3 { - margin-top: 0; - margin-bottom: 8px; text-align: center; } .block ul, .block li { @@ -462,15 +470,7 @@ nav.sub { font-weight: normal; } -h3.impl > .out-of-band { - font-size: 21px; -} - -h4.method > .out-of-band { - font-size: 19px; -} - -h4 > code, h3 > code, .invisible > code { +.method > code, .trait-impl > code, .invisible > code { max-width: calc(100% - 41px); display: block; } @@ -543,7 +543,7 @@ h4 > code, h3 > code, .invisible > code { } .content .multi-column li { width: 100%; display: inline-block; } -.content .method { +.content > .methods > .method { font-size: 1em; position: relative; } @@ -555,7 +555,7 @@ h4 > code, h3 > code, .invisible > code { font-size: 0.8em; } -.content .methods > div:not(.notable-traits):not(.methods) { +.content .methods > div:not(.notable-traits):not(.method) { margin-left: 40px; margin-bottom: 15px; } @@ -564,9 +564,6 @@ h4 > code, h3 > code, .invisible > code { margin-left: 20px; margin-top: -34px; } -.content .docblock > .impl-items > h4 { - border-bottom: 0; -} .content .docblock >.impl-items .table-display { margin: 0; } @@ -688,7 +685,8 @@ a { text-decoration: underline; } -.invisible > .srclink, h4 > code + .srclink, h3 > code + .srclink { +.invisible > .srclink, +.method > code + .srclink { position: absolute; top: 0; right: 0; @@ -923,7 +921,7 @@ body.blur > :not(#help) { flex-grow: 1; } -.impl-items h4, h4.impl, h3.impl, .methods h3 { +.has-srclink { display: flex; flex-basis: 100%; font-size: 16px; @@ -1134,6 +1132,13 @@ a.test-arrow:hover{ margin: 0; } +.notable-traits .notable { + margin: 0; + margin-bottom: 13px; + font-size: 19px; + font-weight: 600; +} + .notable-traits .docblock code.content{ margin: 0; padding: 0; @@ -1197,12 +1202,6 @@ pre.rust { margin-left: 5px; } -h4 > .notable-traits { - position: absolute; - left: -44px; - top: 2px; -} - #all-types { text-align: center; border: 1px solid; @@ -1316,14 +1315,6 @@ h4 > .notable-traits { border-top: 1px solid; } - - -h3.notable { - margin: 0; - margin-bottom: 13px; - font-size: 19px; -} - kbd { display: inline-block; padding: 3px 5px; @@ -1615,10 +1606,6 @@ details.undocumented[open] > summary::before { padding: 0; } - .content h4 > .out-of-band { - position: inherit; - } - #search { margin-left: 0; } @@ -1638,7 +1625,7 @@ details.undocumented[open] > summary::before { z-index: 1; } - h4 > .notable-traits { + .notable-traits { position: absolute; left: -22px; top: 24px; diff --git a/src/librustdoc/html/static/sidebar-items.js b/src/librustdoc/html/static/sidebar-items.js deleted file mode 100644 index 256cd2740a0..00000000000 --- a/src/librustdoc/html/static/sidebar-items.js +++ /dev/null @@ -1,2 +0,0 @@ -/* global initSidebarItems */ -initSidebarItems({}); diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index fd47c085b84..d220d8708a1 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -10,8 +10,7 @@ body { color: #c5c5c5; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3, h4 { color: white; } h1.fqn { @@ -20,10 +19,10 @@ h1.fqn { h1.fqn a { color: #fff; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod) { +h2, h3, h4 { border-bottom-color: #5c6773; } -h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { +h4 { border: none; } @@ -407,6 +406,10 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: #5c6773; } +.notable-traits-tooltiptext .notable { + border-bottom-color: #5c6773; +} + #titles > button.selected { background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index d6e1a880a4e..6385a763f2e 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -3,15 +3,13 @@ body { color: #ddd; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3, h4 { color: #ddd; } h1.fqn { border-bottom-color: #d2d2d2; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod) { +h2, h3, h4 { border-bottom-color: #d2d2d2; } @@ -356,6 +354,10 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: #777; } +.notable-traits-tooltiptext .notable { + border-bottom-color: #d2d2d2; +} + #titles > button:not(.selected) { background-color: #252525; border-top-color: #252525; diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index c8151f1cf97..c19d5bfc317 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -5,15 +5,13 @@ body { color: black; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3, h4 { color: black; } h1.fqn { border-bottom-color: #D5D5D5; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), -h4:not(.method):not(.type):not(.tymethod) { +h2, h3, h4 { border-bottom-color: #DDDDDD; } @@ -348,6 +346,10 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: #999; } +.notable-traits-tooltiptext .notable { + border-bottom-color: #DDDDDD; +} + #titles > button:not(.selected) { background-color: #e6e6e6; border-top-color: #e6e6e6; diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 0e4fb086a15..ca7e5ef8150 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -141,7 +141,4 @@ crate mod noto_sans_kr { crate mod sidebar { /// File script to handle sidebar. crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); - - /// Top Level sidebar items script which will load a sidebar without items. - crate static ITEMS: &str = include_str!("static/sidebar-items.js"); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 191d8d5a2ea..b563c4f4799 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -9,6 +9,7 @@ use rustc_hir::Node; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; use rustc_span; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; @@ -76,7 +77,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &Spanned { span, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, &krate.item, - self.cx.tcx.crate_name, + self.cx.tcx.crate_name(LOCAL_CRATE), ); // Attach the crate's exported macros to the top-level module. // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index f2641404aae..e410180bfff 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -17,33 +17,33 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]] -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 12, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 14, // CHECK-SAME: baseType: [[VARIANT:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]], +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 44be71f3b9b..7edb07d224c 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -21,33 +21,33 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]] -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 18, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 18, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 17, // CHECK-SAME: baseType: [[VARIANT:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]], +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs new file mode 100644 index 00000000000..550cc66f389 --- /dev/null +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -0,0 +1,97 @@ +// only-cdb +// ignore-tidy-linelength +// compile-flags:-g + +// cdb-command: g + +// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb +// so the best we can do is to make sure we are generating the right debuginfo + +// cdb-command: dx -r2 a,! +// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some] +// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] +// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$] + +// cdb-command: dx -r2 b,! +// cdb-check:b,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some] +// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum] +// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$] + +// cdb-command: dx -r2 c,! +// cdb-check:c,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] +// cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum] +// cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] + +// cdb-command: dx -r2 d,! +// cdb-check:d,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] +// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] +// cdb-check: [+0x000] discriminant : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] + +// cdb-command: dx -r2 e,! +// cdb-check:e,! [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data] +// cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum] +// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$] + +// cdb-command: dx -r2 f,! +// cdb-check:f,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some] +// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] +// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$] + +// cdb-command: dx -r2 g,! +// cdb-check:g,! [Type: enum$<core::option::Option<u32*>, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some] +// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *] +// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$] + +// cdb-command: dx h +// cdb-check:h : Some [Type: enum$<core::option::Option<u32>>] +// cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option] +// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] + +// cdb-command: dx i +// cdb-check:i : None [Type: enum$<core::option::Option<u32>>] +// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option] + +// cdb-command: dx j +// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] + +// cdb-command: dx -r2 k,! +// cdb-check:k,! [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some] +// cdb-check: [+0x000] __0 [Type: alloc::string::String] +// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$] + +pub enum CStyleEnum { + Low = 2, + High = 16, +} + +pub enum NicheLayoutEnum { + Tag1, + Data { my_data: CStyleEnum }, + Tag2, +} + +fn main() { + let a = Some(CStyleEnum::Low); + let b = Option::<CStyleEnum>::None; + let c = NicheLayoutEnum::Tag1; + let d = NicheLayoutEnum::Data { my_data: CStyleEnum::High }; + let e = NicheLayoutEnum::Tag2; + let f = Some(&1u32); + let g = Option::<&'static u32>::None; + let h = Some(12u32); + let i = Option::<u32>::None; + let j = CStyleEnum::High; + let k = Some("IAMA optional string!".to_string()); + + zzz(); // #break +} + +fn zzz() { () } diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 1a99f841250..68e73b5f38d 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,6 +1,7 @@ // ignore-freebsd: gdb package too new // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) +// ignore-tidy-linelength // compile-flags:-g // min-gdb-version: 7.7 // min-lldb-version: 310 @@ -111,11 +112,11 @@ // NOTE: OsString doesn't have a .natvis entry yet. // cdb-command: dx some -// cdb-check:some : Some(8) [Type: [...]::Option<i16>] +// cdb-check:some : Some [Type: enum$<core::option::Option<i16>>] // cdb-command: dx none -// cdb-check:none : None [Type: [...]::Option<i64>] +// cdb-check:none : None [Type: enum$<core::option::Option<i64>>] // cdb-command: dx some_string -// cdb-check:some_string : Some("IAMA optional string!") [[...]::Option<[...]::String>] +// cdb-check:some_string [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>] #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml new file mode 100644 index 00000000000..388ca120d77 --- /dev/null +++ b/src/test/rustdoc-gui/sidebar.goml @@ -0,0 +1,56 @@ +goto: file://|DOC_PATH|/test_docs/index.html +assert: (".sidebar > .location", "Crate test_docs") +// In modules, we only have one "location" element. +assert: (".sidebar .location", 1) +assert: (".sidebar-elems > #all-types", "See all test_docs's items") +// We check that we have the crates list and that the "current" on is "test_docs". +assert: (".sidebar-elems > .crate > ul > li > a.current", "test_docs") +// And we're also supposed to have the list of items in the current module. +assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") +assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs") +assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums") +assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits") +assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions") +assert: (".sidebar-elems > .items > ul > li:nth-child(6)", "Keywords") +assert: ("#structs + table td > a", "Foo") +click: "#structs + table td > a" + +// PAGE: struct.Foo.html +assert: (".sidebar .location", 2) +// We check that there is no crate listed outside of the top level. +assert-false: ".sidebar-elems > .crate" +// We now go back to the crate page to click on the "lib2" crate link. +goto: file://|DOC_PATH|/test_docs/index.html +click: ".sidebar-elems > .crate > ul > li:first-child > a" + +// PAGE: lib2/index.html +goto: file://|DOC_PATH|/lib2/index.html +assert: (".sidebar > .location", "Crate lib2") +// We check that we have the crates list and that the "current" on is now "lib2". +assert: (".sidebar-elems > .crate > ul > li > a.current", "lib2") +// We now go to the "foobar" function page. +assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") +assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Functions") +assert: ("#functions + table td > a", "foobar") +click: "#functions + table td > a" + +// PAGE: fn.foobar.html +// In items containing no items (like functions or constants) and in modules, we have one +// "location" elements. +assert: (".sidebar .location", 1) +// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space. +assert: (".sidebar .sidebar-elems .location", "Other items inlib2") +// We check that we don't have the crate list. +assert-false: ".sidebar-elems > .crate" + +goto: ./module/index.html +assert: (".sidebar > .location", "Module module") +// We check that we don't have the crate list. +assert-false: ".sidebar-elems > .crate" + +goto: ./sub_module/sub_sub_module/index.html +assert: (".sidebar > .location", "Module sub_sub_module") +// We check that we don't have the crate list. +assert-false: ".sidebar-elems > .crate" +assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions") +assert: ("#functions + table td > a", "foo") diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2.rs new file mode 100644 index 00000000000..73384cbf906 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2.rs @@ -0,0 +1,11 @@ +pub mod module { + pub mod sub_module { + pub mod sub_sub_module { + pub fn foo() {} + } + pub fn bar() {} + } + pub fn whatever() {} +} + +pub fn foobar() {} diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 4b66b5271c5..9f95d9a994b 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -77,12 +77,12 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T } impl Foo { // @has async_fn/struct.Foo.html - // @has - '//h4[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>' + // @has - '//div[@class="method has-srclink"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>' pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {} // taken from `tokio` as an example of a method that was particularly bad before - // @has - '//h4[@class="method"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>" + // @has - '//div[@class="method has-srclink"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>" pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {} - // @has - '//h4[@class="method"]' "pub async fn mut_self(&mut self)" + // @has - '//div[@class="method has-srclink"]' "pub async fn mut_self(&mut self)" pub async fn mut_self(&mut self) {} } diff --git a/src/test/rustdoc/auto_aliases.rs b/src/test/rustdoc/auto_aliases.rs index 56e0770ab5c..01ea09a9461 100644 --- a/src/test/rustdoc/auto_aliases.rs +++ b/src/test/rustdoc/auto_aliases.rs @@ -1,6 +1,6 @@ #![feature(auto_traits)] -// @has auto_aliases/trait.Bar.html '//h3[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo' +// @has auto_aliases/trait.Bar.html '//div[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo' pub struct Foo; pub auto trait Bar {} diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs index f247ee637b9..6f0c15cb5ac 100644 --- a/src/test/rustdoc/blanket-reexport-item.rs +++ b/src/test/rustdoc/blanket-reexport-item.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.S.html '//h3[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T' +// @has foo/struct.S.html '//div[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T' pub struct S2 {} mod m { pub struct S {} diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index fb5c8517f6c..2761f92ef57 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -38,12 +38,12 @@ pub const unsafe fn bar_not_gated() -> u32 { 42 } pub struct Foo; impl Foo { - // @has 'foo/struct.Foo.html' '//h4[@id="method.gated"]/code' 'pub unsafe fn gated() -> u32' + // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/code' 'pub unsafe fn gated() -> u32' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] pub const unsafe fn gated() -> u32 { 42 } - // @has 'foo/struct.Foo.html' '//h4[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32' + // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32' // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.2.0")] diff --git a/src/test/rustdoc/const-fn.rs b/src/test/rustdoc/const-fn.rs index 9ea7343e075..28eba849ace 100644 --- a/src/test/rustdoc/const-fn.rs +++ b/src/test/rustdoc/const-fn.rs @@ -8,7 +8,7 @@ pub const fn bar() -> usize { } // @has foo/struct.Foo.html -// @has - '//*[@class="method"]' 'const fn new()' +// @has - '//*[@class="method has-srclink"]' 'const fn new()' pub struct Foo(usize); impl Foo { diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs index 77432ba1539..8f412aa8c40 100644 --- a/src/test/rustdoc/const-generics/add-impl.rs +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -8,7 +8,7 @@ pub struct Simd<T, const WIDTH: usize> { inner: T, } -// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3/code' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>' +// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//div/code' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>' impl Add for Simd<u8, 16> { type Output = Self; diff --git a/src/test/rustdoc/const-generics/const-generic-slice.rs b/src/test/rustdoc/const-generics/const-generic-slice.rs index 60d96770f7e..626a9e2b210 100644 --- a/src/test/rustdoc/const-generics/const-generic-slice.rs +++ b/src/test/rustdoc/const-generics/const-generic-slice.rs @@ -6,7 +6,7 @@ pub trait Array { } // @has foo/trait.Array.html -// @has - '//h3[@class="impl"]' 'impl<T, const N: usize> Array for [T; N]' +// @has - '//div[@class="impl has-srclink"]' 'impl<T, const N: usize> Array for [T; N]' impl <T, const N: usize> Array for [T; N] { type Item = T; } diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 21bf216c304..7c4c70432c7 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)' pub struct Bar<T, const N: usize>([T; N]); -// @has foo/struct.Foo.html '//h3[@id="impl"]/code' 'impl<const M: usize> Foo<M> where u8: Trait<M>' +// @has foo/struct.Foo.html '//div[@id="impl"]/code' 'impl<const M: usize> Foo<M> where u8: Trait<M>' impl<const M: usize> Foo<M> where u8: Trait<M> { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> { } } -// @has foo/struct.Bar.html '//h3[@id="impl"]/code' 'impl<const M: usize> Bar<u8, M>' +// @has foo/struct.Bar.html '//div[@id="impl"]/code' 'impl<const M: usize> Bar<u8, M>' impl<const M: usize> Bar<u8, M> { // @has - '//*[@id="method.hey"]' \ // 'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>' diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 04fb3395333..e4e504dd83b 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -9,20 +9,20 @@ pub enum Order { } // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>' -// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' -// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//div[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//div[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' pub struct VSet<T, const ORDER: Order> { inner: Vec<T>, } -// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, {Order::Sorted}>' +// @has foo/struct.VSet.html '//div[@id="impl"]/code' 'impl<T> VSet<T, {Order::Sorted}>' impl <T> VSet<T, {Order::Sorted}> { pub fn new() -> Self { Self { inner: Vec::new() } } } -// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, {Order::Unsorted}>' +// @has foo/struct.VSet.html '//div[@id="impl-1"]/code' 'impl<T> VSet<T, {Order::Unsorted}>' impl <T> VSet<T, {Order::Unsorted}> { pub fn new() -> Self { Self { inner: Vec::new() } @@ -31,7 +31,7 @@ impl <T> VSet<T, {Order::Unsorted}> { pub struct Escape<const S: &'static str>; -// @has foo/struct.Escape.html '//h3[@id="impl"]/code' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>' +// @has foo/struct.Escape.html '//div[@id="impl"]/code' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>' impl Escape<{ r#"<script>alert("Escape");</script>"# }> { pub fn f() {} } diff --git a/src/test/rustdoc/doc-assoc-item.rs b/src/test/rustdoc/doc-assoc-item.rs index 4d5c9f83e1e..4f15418650c 100644 --- a/src/test/rustdoc/doc-assoc-item.rs +++ b/src/test/rustdoc/doc-assoc-item.rs @@ -8,7 +8,7 @@ pub trait Bar { fn foo(foo: Self::Fuu); } -// @has doc_assoc_item/struct.Foo.html '//*[@class="impl"]' 'impl<T: Bar<Fuu = u32>> Foo<T>' +// @has doc_assoc_item/struct.Foo.html '//*[@class="impl has-srclink"]' 'impl<T: Bar<Fuu = u32>> Foo<T>' impl<T: Bar<Fuu = u32>> Foo<T> { pub fn new(t: T) -> Foo<T> { Foo { diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 1e644bb9739..15c3444606c 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,8 +1,8 @@ // @has issue_33054/impls/struct.Foo.html // @has - '//code' 'impl Foo' // @has - '//code' 'impl Bar for Foo' -// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -// @count - '//*[@id="main"]/details/summary/*[@class="impl"]' 1 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 +// @count - '//*[@id="main"]/details/summary/*[@class="impl has-srclink"]' 1 // @has issue_33054/impls/bar/trait.Bar.html // @has - '//code' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 diff --git a/src/test/rustdoc/empty-impls.rs b/src/test/rustdoc/empty-impls.rs index 86dec32e625..2eed1cc9d74 100644 --- a/src/test/rustdoc/empty-impls.rs +++ b/src/test/rustdoc/empty-impls.rs @@ -1,19 +1,19 @@ #![crate_name = "foo"] // @has foo/struct.Foo.html -// @has - '//div[@id="synthetic-implementations-list"]/h3[@id="impl-Send"]' 'impl Send for Foo' +// @has - '//div[@id="synthetic-implementations-list"]/div[@id="impl-Send"]' 'impl Send for Foo' pub struct Foo; pub trait EmptyTrait {} -// @has - '//div[@id="trait-implementations-list"]/h3[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo' +// @has - '//div[@id="trait-implementations-list"]/div[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo' impl EmptyTrait for Foo {} pub trait NotEmpty { fn foo(&self); } -// @has - '//div[@id="trait-implementations-list"]/details/summary/h3[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo' +// @has - '//div[@id="trait-implementations-list"]/details/summary/div[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo' impl NotEmpty for Foo { fn foo(&self) {} } diff --git a/src/test/rustdoc/ensure-src-link.rs b/src/test/rustdoc/ensure-src-link.rs index b7e7b11d27a..4b6270b26da 100644 --- a/src/test/rustdoc/ensure-src-link.rs +++ b/src/test/rustdoc/ensure-src-link.rs @@ -2,5 +2,5 @@ // This test ensures that the [src] link is present on traits items. -// @has foo/trait.Iterator.html '//h3[@id="method.zip"]/a[@class="srclink"]' "[src]" +// @has foo/trait.Iterator.html '//div[@id="method.zip"]/a[@class="srclink"]' "[src]" pub use std::iter::Iterator; diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs index 03a4d197499..96ced021041 100644 --- a/src/test/rustdoc/generic-impl.rs +++ b/src/test/rustdoc/generic-impl.rs @@ -2,10 +2,10 @@ use std::fmt; -// @!has foo/struct.Bar.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T' +// @!has foo/struct.Bar.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T' pub struct Bar; -// @has foo/struct.Foo.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T' +// @has foo/struct.Foo.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T' pub struct Foo; // @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString' diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index 90110babea7..e4039eecb71 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -5,7 +5,7 @@ pub auto trait AnAutoTrait {} pub struct Foo<T> { field: T } -// @has impl_parts/struct.Foo.html '//*[@class="impl"]//code' \ +// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//code' \ // "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync," // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//code' \ // "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync," diff --git a/src/test/rustdoc/inline_cross/issue-31948-1.rs b/src/test/rustdoc/inline_cross/issue-31948-1.rs index f47056223fe..390f0b845e0 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-1.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-1.rs @@ -5,8 +5,8 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_1/struct.Wobble.html -// @has - '//*[@class="impl"]//code' 'Bark for' -// @has - '//*[@class="impl"]//code' 'Woof for' +// @has - '//*[@class="impl has-srclink"]//code' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//code' 'Woof for' // @!has - '//*[@class="impl"]//code' 'Bar for' // @!has - '//*[@class="impl"]//code' 'Qux for' pub use rustdoc_nonreachable_impls::hidden::Wobble; diff --git a/src/test/rustdoc/inline_cross/issue-31948-2.rs b/src/test/rustdoc/inline_cross/issue-31948-2.rs index 282f0679e98..013e777440f 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-2.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-2.rs @@ -5,9 +5,9 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_2/struct.Wobble.html -// @has - '//*[@class="impl"]//code' 'Qux for' -// @has - '//*[@class="impl"]//code' 'Bark for' -// @has - '//*[@class="impl"]//code' 'Woof for' +// @has - '//*[@class="impl has-srclink"]//code' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//code' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//code' 'Woof for' // @!has - '//*[@class="impl"]//code' 'Bar for' pub use rustdoc_nonreachable_impls::hidden::Wobble; diff --git a/src/test/rustdoc/inline_cross/issue-31948.rs b/src/test/rustdoc/inline_cross/issue-31948.rs index d5725175e3f..82dcc2d2cc3 100644 --- a/src/test/rustdoc/inline_cross/issue-31948.rs +++ b/src/test/rustdoc/inline_cross/issue-31948.rs @@ -5,9 +5,9 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948/struct.Foo.html -// @has - '//*[@class="impl"]//code' 'Bark for' -// @has - '//*[@class="impl"]//code' 'Woof for' -// @!has - '//*[@class="impl"]//code' 'Bar for' +// @has - '//*[@class="impl has-srclink"]//code' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//code' 'Woof for' +// @!has - '//*[@class="impl has-srclink"]//code' 'Bar for' // @!has - '//*[@class="impl"]//code' 'Qux for' pub use rustdoc_nonreachable_impls::Foo; diff --git a/src/test/rustdoc/issue-21474.rs b/src/test/rustdoc/issue-21474.rs index 5de26abace6..43ce13fd9b1 100644 --- a/src/test/rustdoc/issue-21474.rs +++ b/src/test/rustdoc/issue-21474.rs @@ -7,5 +7,5 @@ mod inner { pub trait Blah { } // @count issue_21474/struct.What.html \ -// '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 +// '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 pub struct What; diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 2b25da77d7e..23d9e73b567 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//h3[@id='impl-MyTrait']//code" "impl<T> MyTrait for T where T: Debug" +// @has - "//div[@id='implementors-list']//div[@id='impl-MyTrait']//code" "impl<T> MyTrait for T where T: Debug" impl<T> MyTrait for T where T: fmt::Debug { fn my_string(&self) -> String { format!("{:?}", self) diff --git a/src/test/rustdoc/issue-33302.rs b/src/test/rustdoc/issue-33302.rs index 21356b513ee..1777744c0fc 100644 --- a/src/test/rustdoc/issue-33302.rs +++ b/src/test/rustdoc/issue-33302.rs @@ -23,7 +23,7 @@ macro_rules! make { } // @has issue_33302/struct.S.html \ - // '//h3[@class="impl"]' 'impl T<[i32; 16]> for S' + // '//div[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S' // @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]' // @has - '//*[@id="associatedconstant.D"]' 'const D: i32' impl T<[i32; ($n * $n)]> for S { @@ -31,7 +31,7 @@ macro_rules! make { } // @has issue_33302/struct.S.html \ - // '//h3[@class="impl"]' 'impl T<[i32; 16]> for S' + // '//div[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S' // @has - '//*[@id="associatedconstant.C-1"]' 'const C: (i32,)' // @has - '//*[@id="associatedconstant.D-1"]' 'const D: i32' impl T<(i32,)> for S { @@ -39,7 +39,7 @@ macro_rules! make { } // @has issue_33302/struct.S.html \ - // '//h3[@class="impl"]' 'impl T<(i32, i32)> for S' + // '//div[@class="impl has-srclink"]' 'impl T<(i32, i32)> for S' // @has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)' // @has - '//*[@id="associatedconstant.D-2"]' 'const D: i32' impl T<(i32, i32)> for S { diff --git a/src/test/rustdoc/issue-45584.rs b/src/test/rustdoc/issue-45584.rs index 8a5f0413826..86479e6fb2e 100644 --- a/src/test/rustdoc/issue-45584.rs +++ b/src/test/rustdoc/issue-45584.rs @@ -4,12 +4,12 @@ pub trait Bar<T, U> {} // @has 'foo/struct.Foo1.html' pub struct Foo1; -// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1" +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 +// @has - '//*[@class="impl has-srclink"]' "impl Bar<Foo1, &'static Foo1> for Foo1" impl Bar<Foo1, &'static Foo1> for Foo1 {} // @has 'foo/struct.Foo2.html' pub struct Foo2; -// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8" +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 +// @has - '//*[@class="impl has-srclink"]' "impl Bar<&'static Foo2, Foo2> for u8" impl Bar<&'static Foo2, Foo2> for u8 {} diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index 0820512e521..69774aa351f 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -14,7 +14,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> { // @has - '//code' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send' // @has - '//code' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Switch<B: Signal> { pub inner: <B as Signal2>::Item2, } diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index d018c948162..e01dae6c7f1 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -7,8 +7,8 @@ pub mod traits { } // @has issue_51236/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \ -// Owned<T> where <T as Owned<'static>>::Reader: Send" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> Send for Owned<T> where <T as Owned<'static>>::Reader: Send" pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>, } diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs index ddc14e68675..0b1f2f2c93f 100644 --- a/src/test/rustdoc/issue-53812.rs +++ b/src/test/rustdoc/issue-53812.rs @@ -12,9 +12,10 @@ macro_rules! array_impls { } } -// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]/h3[1]' 'MyStruct<[T; 0]>' -// @has - '//*[@id="implementors-list"]/h3[2]' 'MyStruct<[T; 1]>' -// @has - '//*[@id="implementors-list"]/h3[3]' 'MyStruct<[T; 2]>' -// @has - '//*[@id="implementors-list"]/h3[4]' 'MyStruct<[T; 3]>' -// @has - '//*[@id="implementors-list"]/h3[5]' 'MyStruct<[T; 10]>' +// @has issue_53812/trait.MyIterator.html +// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][1]' 'MyStruct<[T; 0]>' +// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][2]' 'MyStruct<[T; 1]>' +// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][3]' 'MyStruct<[T; 2]>' +// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][4]' 'MyStruct<[T; 3]>' +// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][5]' 'MyStruct<[T; 10]>' array_impls! { 10 3 2 1 0 } diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index 47da94a4ccf..5a94d36ed70 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -3,11 +3,11 @@ pub trait ScopeHandle<'scope> {} // @has issue_54705/struct.ScopeFutureContents.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \ -// Send for ScopeFutureContents<'scope, S> where S: Sync" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \ -// Sync for ScopeFutureContents<'scope, S> where S: Sync" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, { diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index d1877f39ba7..b664733487b 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,16 +1,18 @@ #![feature(negative_impls)] // @has issue_55321/struct.A.html -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Send for A" -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Sync for A" +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl !Send for A" +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl !Sync for A" pub struct A(); impl !Send for A {} impl !Sync for A {} // @has issue_55321/struct.B.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \ -// B<T>" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Sync for \ -// B<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Send for B<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Sync for B<T>" pub struct B<T: ?Sized>(A, Box<T>); diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index b932a3d3474..977596e0b90 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -17,8 +17,8 @@ impl<'a, T> MyTrait for Inner<'a, T> { } // @has issue_56822/struct.Parser.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a> Send for \ -// Parser<'a>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'a> Send for Parser<'a>" pub struct Parser<'a> { field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output } diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs index 79b8b70c545..e0417f1a4f4 100644 --- a/src/test/rustdoc/issue-60726.rs +++ b/src/test/rustdoc/issue-60726.rs @@ -26,10 +26,10 @@ where {} // @has issue_60726/struct.IntoIter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \ -// IntoIter<T>" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Sync for \ -// IntoIter<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Send for IntoIter<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Sync for IntoIter<T>" pub struct IntoIter<T>{ hello:DynTrait<FooInterface<T>>, } diff --git a/src/test/rustdoc/issue-76501.rs b/src/test/rustdoc/issue-76501.rs index d468f35e280..a90e0fea092 100644 --- a/src/test/rustdoc/issue-76501.rs +++ b/src/test/rustdoc/issue-76501.rs @@ -8,7 +8,8 @@ pub const fn bloop() -> i32 { pub struct Struct {} impl Struct { - // @has 'issue_76501/struct.Struct.html' '//*[@class="method"]' 'pub const fn blurp() -> i32' + // @has 'issue_76501/struct.Struct.html' '//*[@class="method has-srclink"]' \ + // 'pub const fn blurp() -> i32' /// A useless function that always returns 1. pub const fn blurp() -> i32 { 1 diff --git a/src/test/rustdoc/issue-78673.rs b/src/test/rustdoc/issue-78673.rs index d09141c3204..2e4bec2544c 100644 --- a/src/test/rustdoc/issue-78673.rs +++ b/src/test/rustdoc/issue-78673.rs @@ -7,8 +7,8 @@ pub trait AnAmazingTrait {} impl<T: Something> AnAmazingTrait for T {} // @has 'issue_78673/struct.MyStruct.html' -// @has - '//*[@class="impl"]' 'AnAmazingTrait for MyStruct' -// @!has - '//*[@class="impl"]' 'AnAmazingTrait for T' +// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for MyStruct' +// @!has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T' pub struct MyStruct; impl AnAmazingTrait for MyStruct {} @@ -16,8 +16,8 @@ impl AnAmazingTrait for MyStruct {} // generic structs may have _both_ specific and blanket impls that apply // @has 'issue_78673/struct.AnotherStruct.html' -// @has - '//*[@class="impl"]' 'AnAmazingTrait for AnotherStruct<()>' -// @has - '//*[@class="impl"]' 'AnAmazingTrait for T' +// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for AnotherStruct<()>' +// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T' pub struct AnotherStruct<T>(T); impl<T: Something> Something for AnotherStruct<T> {} diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs index 25e8b7912e7..652517c5c90 100644 --- a/src/test/rustdoc/keyword.rs +++ b/src/test/rustdoc/keyword.rs @@ -4,7 +4,8 @@ // @has foo/index.html '//h2[@id="keywords"]' 'Keywords' // @has foo/index.html '//a[@href="keyword.match.html"]' 'match' -// @has foo/index.html '//div[@class="block items"]//a/@href' '#keywords' +// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords' +// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' // @has foo/keyword.match.html '//span[@class="in-band"]' 'Keyword match' // @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!' diff --git a/src/test/rustdoc/mut-params.rs b/src/test/rustdoc/mut-params.rs index 1ef7e304fa2..f3ea6995839 100644 --- a/src/test/rustdoc/mut-params.rs +++ b/src/test/rustdoc/mut-params.rs @@ -5,7 +5,7 @@ pub struct Foo; -// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method"]' 2 +// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method has-srclink"]' 2 // @!has - '//*[@class="impl-items"]//*[@class="method"]' 'mut' impl Foo { pub fn foo(mut self) {} diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs index d76aac6906c..ee65a7d5f39 100644 --- a/src/test/rustdoc/negative-impl.rs +++ b/src/test/rustdoc/negative-impl.rs @@ -5,8 +5,10 @@ pub struct Alpha; // @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>" pub struct Bravo<B>(B); -// @matches negative_impl/struct.Alpha.html '//*[@class="impl"]//code' "impl !Send for Alpha" +// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//code' \ +// "impl !Send for Alpha" impl !Send for Alpha {} -// @matches negative_impl/struct.Bravo.html '//*[@class="impl"]//code' "impl<B> !Send for Bravo<B>" +// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//code' "\ +// impl<B> !Send for Bravo<B>" impl<B> !Send for Bravo<B> {} diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs index 5794322ba1d..2951f5128e0 100644 --- a/src/test/rustdoc/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive-generic-impl.rs @@ -2,4 +2,4 @@ include!("primitive/primitive-generic-impl.rs"); -// @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T' +// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T' diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs index 8e88b2b5901..fa7de0aff6a 100644 --- a/src/test/rustdoc/pub-method.rs +++ b/src/test/rustdoc/pub-method.rs @@ -10,8 +10,8 @@ pub fn bar() -> usize { } // @has foo/struct.Foo.html -// @has - '//*[@class="method"]' 'pub fn new()' -// @has - '//*[@class="method"]' 'fn not_pub()' +// @has - '//*[@class="method has-srclink"]' 'pub fn new()' +// @has - '//*[@class="method has-srclink"]' 'fn not_pub()' pub struct Foo(usize); impl Foo { diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs index 6219a2c3b90..d256fbe8de0 100644 --- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs @@ -6,9 +6,9 @@ // @has - '//*[@class="sidebar-title"][@href="#foreign-impls"]' 'Implementations on Foreign Types' // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types' // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32' -// @has - '//h3[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32' +// @has - '//div[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32' // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str" -// @has - '//h3[@id="impl-Foo-for-%26%27a%20str"]//code' "impl<'a> Foo for &'a str" +// @has - '//div[@id="impl-Foo-for-%26%27a%20str"]//code' "impl<'a> Foo for &'a str" pub trait Foo {} impl Foo for u32 {} diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs index 26d12817afc..6730c71e90f 100644 --- a/src/test/rustdoc/sized_trait.rs +++ b/src/test/rustdoc/sized_trait.rs @@ -1,17 +1,17 @@ #![crate_name = "foo"] // @has foo/struct.Bar.html -// @!has - '//h3[@id="impl-Sized"]' +// @!has - '//div[@id="impl-Sized"]' pub struct Bar { a: u16, } // @has foo/struct.Foo.html -// @!has - '//h3[@id="impl-Sized"]' +// @!has - '//div[@id="impl-Sized"]' pub struct Foo<T: ?Sized>(T); // @has foo/struct.Unsized.html -// @has - '//h3[@id="impl-Sized"]/code' 'impl !Sized for Unsized' +// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/spotlight-from-dependency.rs b/src/test/rustdoc/spotlight-from-dependency.rs index ed42c435945..864cb0c400b 100644 --- a/src/test/rustdoc/spotlight-from-dependency.rs +++ b/src/test/rustdoc/spotlight-from-dependency.rs @@ -3,7 +3,7 @@ use std::iter::Iterator; // @has foo/struct.Odd.html -// @has - '//h4[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd' +// @has - '//div[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd' pub struct Odd { current: usize, } diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs index a1d183df0f1..6f609e080d3 100644 --- a/src/test/rustdoc/src-links-auto-impls.rs +++ b/src/test/rustdoc/src-links-auto-impls.rs @@ -1,12 +1,12 @@ #![crate_name = "foo"] // @has foo/struct.Unsized.html -// @has - '//h3[@id="impl-Sized"]/code' 'impl !Sized for Unsized' -// @!has - '//h3[@id="impl-Sized"]/a[@class="srclink"]' '[src]' -// @has - '//h3[@id="impl-Sync"]/code' 'impl Sync for Unsized' -// @!has - '//h3[@id="impl-Sync"]/a[@class="srclink"]' '[src]' -// @has - '//h3[@id="impl-Any"]/code' 'impl<T> Any for T' -// @has - '//h3[@id="impl-Any"]/a[@class="srclink"]' '[src]' +// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized' +// @!has - '//div[@id="impl-Sized"]/a[@class="srclink"]' '[src]' +// @has - '//div[@id="impl-Sync"]/code' 'impl Sync for Unsized' +// @!has - '//div[@id="impl-Sync"]/a[@class="srclink"]' '[src]' +// @has - '//div[@id="impl-Any"]/code' 'impl<T> Any for T' +// @has - '//div[@id="impl-Any"]/a[@class="srclink"]' '[src]' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 0dd3a3f7a86..943596a0c85 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,8 +1,8 @@ // @has basic/struct.Foo.html // @has - '//code' 'impl<T> Send for Foo<T> where T: Send' // @has - '//code' 'impl<T> Sync for Foo<T> where T: Sync' -// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +// @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Foo<T> { field: T, } diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index d951a20e2de..0213142266f 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -20,8 +20,8 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a, T, K: \ -// ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static" pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter}; diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 05c88f10822..c2e9b6f4046 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -9,11 +9,11 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \ -// for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \ -// for Foo<'c, K> where K: Sync" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'c, K> Sync for Foo<'c, K> where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, } diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 88ddd57349a..91fe6c351c5 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,12 +1,12 @@ // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl<T> Sync for \ -// Foo<T> where T: Sync' +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// 'impl<T> Sync for Foo<T> where T: Sync' // -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \ // 'impl<T> Send for Foo<T>' // -// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4 +// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 +// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 4 pub struct Foo<T> { field: T, } diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index 53801542c95..16b36b56b68 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -3,11 +3,11 @@ pub struct Inner<T: Copy> { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \ -// Outer<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Send for Outer<T>" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> \ -// !Sync for Outer<T>" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> !Sync for Outer<T>" pub struct Outer<T: Copy> { inner_field: Inner<T>, } diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index d4d93a87ffc..a6cf5890dca 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -9,10 +9,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl<T> Send for \ -// Foo<T> where T: Copy' +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// 'impl<T> Send for Foo<T> where T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ // 'impl<T> Sync for Foo<T> where T: Sync' pub struct Foo<T> { inner_field: Inner<T>, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 3a23dc2cf95..5c744e3eb3c 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -9,8 +9,8 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \ -// Outer<T> where T: Copy + Send" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> Send for Outer<T> where T: Copy + Send" pub struct Outer<T> { inner_field: Inner<T>, } diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 060491e3cf1..baf9924b1ae 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -23,11 +23,12 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \ -// for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \ -// for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, 'c: 'static," +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \ +// 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, } diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index ecdbdf41b20..e96187e2c96 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> { // @has self_referential/struct.WriteAndThen.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<P1> Send for \ -// WriteAndThen<P1> where <P1 as Pattern>::Value: Send" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<P1> Send for WriteAndThen<P1> where <P1 as Pattern>::Value: Send" pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index a10e694c1b2..fc732a08ed4 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -3,8 +3,8 @@ pub trait OwnedTrait<'a> { } // @has static_region/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \ -// Owned<T> where <T as OwnedTrait<'static>>::Reader: Send" +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \ +// "impl<T> Send for Owned<T> where <T as OwnedTrait<'static>>::Reader: Send" pub struct Owned<T> where T: OwnedTrait<'static> { marker: <T as OwnedTrait<'static>>::Reader, } diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs index 2bb24a82193..d0dfb8759e6 100644 --- a/src/test/rustdoc/trait-attributes.rs +++ b/src/test/rustdoc/trait-attributes.rs @@ -2,7 +2,7 @@ pub trait Foo { - // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]' + // @has foo/trait.Foo.html '//div[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] fn foo(); } @@ -11,11 +11,11 @@ pub trait Foo { pub struct Bar; impl Bar { - // @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]' + // @has foo/struct.Bar.html '//div[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] pub fn bar() {} - // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]' + // @has foo/struct.Bar.html '//div[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]' #[must_use] pub fn bar2() {} } diff --git a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs index c6a9313e821..5b7c04c0d44 100644 --- a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs +++ b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs @@ -8,58 +8,58 @@ pub trait MyTrait { impl MyTrait for String { - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="type"]/@href' #associatedtype.Assoc - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-1"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1 type Assoc = (); - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1 const VALUE: u32 = 5; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function fn trait_function(&self) {} - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-1"]//a[@class="fnname"]/@href' #method.defaulted_override - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-1"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1 fn defaulted_override(&self) {} } impl MyTrait for Vec<u8> { - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="type"]/@href' #associatedtype.Assoc - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-2"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2 type Assoc = (); - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2 const VALUE: u32 = 5; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1 fn trait_function(&self) {} - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="fnname"]/@href' #method.defaulted_override - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2 + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-2"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2 fn defaulted_override(&self) {} } impl MyTrait for MyStruct { - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3 - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc type Assoc = bool; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3 - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE const VALUE: u32 = 20; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2 - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function fn trait_function(&self) {} - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3 - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override + // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3 + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override fn defaulted_override(&self) {} - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted - // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted + // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted } pub struct MyStruct; diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs index 7f834d3d5a5..21a7fdda769 100644 --- a/src/test/rustdoc/typedef.rs +++ b/src/test/rustdoc/typedef.rs @@ -9,8 +9,8 @@ impl MyStruct { } // @has typedef/type.MyAlias.html -// @has - '//*[@class="impl"]//code' 'impl MyAlias' -// @has - '//*[@class="impl"]//code' 'impl MyTrait for MyAlias' +// @has - '//*[@class="impl has-srclink"]//code' 'impl MyAlias' +// @has - '//*[@class="impl has-srclink"]//code' 'impl MyTrait for MyAlias' // @has - 'Alias docstring' // @has - '//*[@class="sidebar"]//p[@class="location"]' 'Type Definition MyAlias' // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods' diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 992cddfe72a..f204a27d7d3 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -11,7 +11,7 @@ pub fn charlie<C>() where C: MyTrait {} pub struct Delta<D>(D); -// @has foo/struct.Delta.html '//*[@class="impl"]//code' \ +// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//code' \ // "impl<D> Delta<D> where D: MyTrait" impl<D> Delta<D> where D: MyTrait { pub fn delta() {} @@ -19,7 +19,7 @@ impl<D> Delta<D> where D: MyTrait { pub struct Echo<E>(E); -// @has foo/struct.Echo.html '//*[@class="impl"]//code' \ +// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//code' \ // "impl<E> MyTrait for Echo<E> where E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ // "impl<E> MyTrait for Echo<E> where E: MyTrait" @@ -27,7 +27,7 @@ impl<E> MyTrait for Echo<E> where E: MyTrait {} pub enum Foxtrot<F> { Foxtrot1(F) } -// @has foo/enum.Foxtrot.html '//*[@class="impl"]//code' \ +// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//code' \ // "impl<F> MyTrait for Foxtrot<F> where F: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ // "impl<F> MyTrait for Foxtrot<F> where F: MyTrait" diff --git a/src/test/ui/const-generics/defaults/forward-declared.rs b/src/test/ui/const-generics/defaults/forward-declared.rs new file mode 100644 index 00000000000..09fc105320e --- /dev/null +++ b/src/test/ui/const-generics/defaults/forward-declared.rs @@ -0,0 +1,15 @@ +#![feature(const_generics_defaults)] + +struct Foo<const N: usize = M, const M: usize = 10>; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar<const N: usize = M, const M: usize = 10> {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +struct Foo2<const N: usize = N>; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar2<const N: usize = N> {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/forward-declared.stderr b/src/test/ui/const-generics/defaults/forward-declared.stderr new file mode 100644 index 00000000000..a6c4a7ae4ef --- /dev/null +++ b/src/test/ui/const-generics/defaults/forward-declared.stderr @@ -0,0 +1,27 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:3:29 + | +LL | struct Foo<const N: usize = M, const M: usize = 10>; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:6:27 + | +LL | enum Bar<const N: usize = M, const M: usize = 10> {} + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:9:30 + | +LL | struct Foo2<const N: usize = N>; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:12:28 + | +LL | enum Bar2<const N: usize = N> {} + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 3699a939e27..20af4f62e65 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -11,16 +11,16 @@ LL | #![deny(deprecated)] | ^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:21:9 + --> $DIR/deprecation-lint.rs:21:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:23:9 + --> $DIR/deprecation-lint.rs:23:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:25:9 @@ -29,16 +29,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:30:9 + --> $DIR/deprecation-lint.rs:30:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:32:9 + --> $DIR/deprecation-lint.rs:32:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text --> $DIR/deprecation-lint.rs:34:17 @@ -53,10 +53,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:40:17 + --> $DIR/deprecation-lint.rs:40:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text --> $DIR/deprecation-lint.rs:42:17 @@ -65,28 +65,28 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:44:17 + --> $DIR/deprecation-lint.rs:44:25 | LL | let _ = nested::DeprecatedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:48:17 + --> $DIR/deprecation-lint.rs:48:25 | LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:50:17 + --> $DIR/deprecation-lint.rs:50:31 | LL | ... let _ = nested::Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:52:17 + --> $DIR/deprecation-lint.rs:52:25 | LL | ... let _ = nested::DeprecatedTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:59:25 @@ -101,28 +101,28 @@ LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:65:9 + --> $DIR/deprecation-lint.rs:65:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:67:9 + --> $DIR/deprecation-lint.rs:67:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:69:9 + --> $DIR/deprecation-lint.rs:69:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:71:9 + --> $DIR/deprecation-lint.rs:71:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text --> $DIR/deprecation-lint.rs:81:10 @@ -173,10 +173,10 @@ LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text - --> $DIR/deprecation-lint.rs:162:9 + --> $DIR/deprecation-lint.rs:162:25 | LL | deprecated_mod::deprecated(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated`: text --> $DIR/deprecation-lint.rs:245:9 @@ -185,16 +185,16 @@ LL | deprecated(); | ^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:250:9 + --> $DIR/deprecation-lint.rs:250:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:252:9 + --> $DIR/deprecation-lint.rs:252:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_text`: text --> $DIR/deprecation-lint.rs:254:9 @@ -203,16 +203,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:259:9 + --> $DIR/deprecation-lint.rs:259:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:261:9 + --> $DIR/deprecation-lint.rs:261:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future`: text --> $DIR/deprecation-lint.rs:264:9 @@ -239,10 +239,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:274:17 + --> $DIR/deprecation-lint.rs:274:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text --> $DIR/deprecation-lint.rs:276:17 @@ -251,52 +251,52 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:278:17 + --> $DIR/deprecation-lint.rs:278:25 | LL | let _ = nested::DeprecatedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:283:17 + --> $DIR/deprecation-lint.rs:283:25 | LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:285:17 + --> $DIR/deprecation-lint.rs:285:31 | LL | ... let _ = nested::Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:287:17 + --> $DIR/deprecation-lint.rs:287:25 | LL | ... let _ = nested::DeprecatedTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:292:9 + --> $DIR/deprecation-lint.rs:292:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:294:9 + --> $DIR/deprecation-lint.rs:294:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:296:9 + --> $DIR/deprecation-lint.rs:296:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:298:9 + --> $DIR/deprecation-lint.rs:298:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` --> $DIR/deprecation-lint.rs:316:13 diff --git a/src/test/ui/deprecation/suggestion.fixed b/src/test/ui/deprecation/suggestion.fixed index eba72f88a89..1ba1821e6c1 100644 --- a/src/test/ui/deprecation/suggestion.fixed +++ b/src/test/ui/deprecation/suggestion.fixed @@ -1,9 +1,7 @@ // run-rustfix #![feature(staged_api)] - #![stable(since = "1.0.0", feature = "test")] - #![deny(deprecated)] #![allow(dead_code)] @@ -21,8 +19,21 @@ impl Foo { fn replacement(&self) {} } +mod bar { + #[rustc_deprecated( + since = "1.0.0", + reason = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + fn main() { let foo = Foo; - foo.replacement(); //~ ERROR use of deprecated + + bar::replacement(); //~ ERROR use of deprecated } diff --git a/src/test/ui/deprecation/suggestion.rs b/src/test/ui/deprecation/suggestion.rs index 8f9791c13e8..e40737d1957 100644 --- a/src/test/ui/deprecation/suggestion.rs +++ b/src/test/ui/deprecation/suggestion.rs @@ -1,9 +1,7 @@ // run-rustfix #![feature(staged_api)] - #![stable(since = "1.0.0", feature = "test")] - #![deny(deprecated)] #![allow(dead_code)] @@ -21,8 +19,21 @@ impl Foo { fn replacement(&self) {} } +mod bar { + #[rustc_deprecated( + since = "1.0.0", + reason = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + fn main() { let foo = Foo; - foo.deprecated(); //~ ERROR use of deprecated + + bar::deprecated(); //~ ERROR use of deprecated } diff --git a/src/test/ui/deprecation/suggestion.stderr b/src/test/ui/deprecation/suggestion.stderr index 8a7cb1def90..b95ca3a75e4 100644 --- a/src/test/ui/deprecation/suggestion.stderr +++ b/src/test/ui/deprecation/suggestion.stderr @@ -1,14 +1,20 @@ -error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement` - --> $DIR/suggestion.rs:27:9 +error: use of deprecated function `bar::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:38:10 | -LL | foo.deprecated(); - | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement` +LL | bar::deprecated(); + | ^^^^^^^^^^ help: replace the use of the deprecated function: `replacement` | note: the lint level is defined here - --> $DIR/suggestion.rs:7:9 + --> $DIR/suggestion.rs:5:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ -error: aborting due to previous error +error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:36:9 + | +LL | foo.deprecated(); + | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement` + +error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr index 94fc1a7b46d..4b082fcd359 100644 --- a/src/test/ui/lint/lint-stability-deprecated.stderr +++ b/src/test/ui/lint/lint-stability-deprecated.stderr @@ -11,16 +11,16 @@ LL | #![warn(deprecated)] | ^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:29:9 + --> $DIR/lint-stability-deprecated.rs:29:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:31:9 + --> $DIR/lint-stability-deprecated.rs:31:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:33:9 @@ -29,16 +29,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:38:9 + --> $DIR/lint-stability-deprecated.rs:38:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:40:9 + --> $DIR/lint-stability-deprecated.rs:40:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:42:9 @@ -47,16 +47,16 @@ LL | deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:47:9 + --> $DIR/lint-stability-deprecated.rs:47:16 | LL | ... Trait::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:49:9 + --> $DIR/lint-stability-deprecated.rs:49:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text --> $DIR/lint-stability-deprecated.rs:51:9 @@ -65,16 +65,16 @@ LL | deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:56:9 + --> $DIR/lint-stability-deprecated.rs:56:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:58:9 + --> $DIR/lint-stability-deprecated.rs:58:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text --> $DIR/lint-stability-deprecated.rs:108:17 @@ -101,16 +101,16 @@ LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:123:17 + --> $DIR/lint-stability-deprecated.rs:123:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:17 + --> $DIR/lint-stability-deprecated.rs:124:23 | LL | let _ = Enum::DeprecatedUnstableVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:128:17 @@ -143,52 +143,52 @@ LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:9 + --> $DIR/lint-stability-deprecated.rs:145:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:9 + --> $DIR/lint-stability-deprecated.rs:147:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:9 + --> $DIR/lint-stability-deprecated.rs:149:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:151:9 + --> $DIR/lint-stability-deprecated.rs:151:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:9 + --> $DIR/lint-stability-deprecated.rs:153:16 | LL | ... Trait::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:155:9 + --> $DIR/lint-stability-deprecated.rs:155:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:9 + --> $DIR/lint-stability-deprecated.rs:157:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:159:9 + --> $DIR/lint-stability-deprecated.rs:159:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text --> $DIR/lint-stability-deprecated.rs:187:10 @@ -203,10 +203,10 @@ LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:208:9 + --> $DIR/lint-stability-deprecated.rs:208:23 | LL | unstable_mod::deprecated(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text --> $DIR/lint-stability-deprecated.rs:330:9 @@ -215,16 +215,16 @@ LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:9 + --> $DIR/lint-stability-deprecated.rs:335:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:9 + --> $DIR/lint-stability-deprecated.rs:337:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:339:9 @@ -233,16 +233,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:9 + --> $DIR/lint-stability-deprecated.rs:344:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:346:9 + --> $DIR/lint-stability-deprecated.rs:346:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text --> $DIR/lint-stability-deprecated.rs:384:17 @@ -257,10 +257,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:395:17 + --> $DIR/lint-stability-deprecated.rs:395:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:399:17 @@ -269,28 +269,28 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:9 + --> $DIR/lint-stability-deprecated.rs:406:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:9 + --> $DIR/lint-stability-deprecated.rs:408:25 | LL | <Foo as Trait>::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:9 + --> $DIR/lint-stability-deprecated.rs:410:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:412:9 + --> $DIR/lint-stability-deprecated.rs:412:25 | LL | ... <Foo as Trait>::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text --> $DIR/lint-stability-deprecated.rs:439:9 diff --git a/src/test/ui/stability-attribute/generics-default-stability.stderr b/src/test/ui/stability-attribute/generics-default-stability.stderr index 99523f8eb64..c3e3f543d79 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.stderr +++ b/src/test/ui/stability-attribute/generics-default-stability.stderr @@ -169,10 +169,10 @@ LL | let _: Alias5<isize> = Alias5::Some(0); | ^^^^^^^^^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test - --> $DIR/generics-default-stability.rs:231:27 + --> $DIR/generics-default-stability.rs:231:34 | LL | let _: Enum4<isize> = Enum4::Some(1); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:231:12 @@ -193,10 +193,10 @@ LL | let _: Enum4<usize> = ENUM4; | ^^^^^^^^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test - --> $DIR/generics-default-stability.rs:237:27 + --> $DIR/generics-default-stability.rs:237:34 | LL | let _: Enum4<isize> = Enum4::Some(0); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:237:12 @@ -205,10 +205,10 @@ LL | let _: Enum4<isize> = Enum4::Some(0); | ^^^^^^^^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test - --> $DIR/generics-default-stability.rs:242:27 + --> $DIR/generics-default-stability.rs:242:34 | LL | let _: Enum5<isize> = Enum5::Some(1); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:242:12 @@ -229,10 +229,10 @@ LL | let _: Enum5<usize> = ENUM5; | ^^^^^^^^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test - --> $DIR/generics-default-stability.rs:249:27 + --> $DIR/generics-default-stability.rs:249:34 | LL | let _: Enum5<isize> = Enum5::Some(0); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:249:12 diff --git a/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs new file mode 100644 index 00000000000..d71747f9687 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_attribute] +pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream { + quote!( + fn f(_: &mut i32) {} + fn g() { + f(123); + } + ) +} diff --git a/src/test/ui/suggestions/suggest-ref-macro.rs b/src/test/ui/suggestions/suggest-ref-macro.rs new file mode 100644 index 00000000000..6f780f32a14 --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-macro.rs @@ -0,0 +1,29 @@ +// run-check +// aux-build:proc-macro-type-error.rs + +extern crate proc_macro_type_error; + +use proc_macro_type_error::hello; + +#[hello] //~ERROR mismatched types +fn abc() {} + +fn x(_: &mut i32) {} + +macro_rules! bla { + () => { + x(123); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 123 + }; + ($v:expr) => { + x($v) + } +} + +fn main() { + bla!(); + bla!(456); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 456 +} diff --git a/src/test/ui/suggestions/suggest-ref-macro.stderr b/src/test/ui/suggestions/suggest-ref-macro.stderr new file mode 100644 index 00000000000..147001f0c94 --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-macro.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | ^^^^^^^^ expected `&mut i32`, found integer + | + = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:15:11 + | +LL | x(123); + | ^^^ + | | + | expected `&mut i32`, found integer + | help: consider mutably borrowing here: `&mut 123` +... +LL | bla!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:26:10 + | +LL | bla!(456); + | ^^^ + | | + | expected `&mut i32`, found integer + | help: consider mutably borrowing here: `&mut 456` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/target-feature/wasm-safe.rs b/src/test/ui/target-feature/wasm-safe.rs new file mode 100644 index 00000000000..4b868684a52 --- /dev/null +++ b/src/test/ui/target-feature/wasm-safe.rs @@ -0,0 +1,44 @@ +// only-wasm32 +// check-pass + +#![feature(wasm_target_feature)] +#![allow(dead_code)] + +#[target_feature(enable = "nontrapping-fptoint")] +fn foo() {} + +#[target_feature(enable = "nontrapping-fptoint")] +extern "C" fn bar() {} + +trait A { + fn foo(); + fn bar(&self); +} + +struct B; + +impl B { + #[target_feature(enable = "nontrapping-fptoint")] + fn foo() {} + #[target_feature(enable = "nontrapping-fptoint")] + fn bar(&self) {} +} + +impl A for B { + #[target_feature(enable = "nontrapping-fptoint")] + fn foo() {} + #[target_feature(enable = "nontrapping-fptoint")] + fn bar(&self) {} +} + +fn no_features_enabled_on_this_function() { + bar(); + foo(); + B.bar(); + B::foo(); + <B as A>::foo(); + <B as A>::bar(&B); +} + +#[target_feature(enable = "nontrapping-fptoint")] +fn main() {} diff --git a/src/test/ui/thread-local-static.rs b/src/test/ui/thread-local-static.rs new file mode 100644 index 00000000000..c7fee9e6b4c --- /dev/null +++ b/src/test/ui/thread-local-static.rs @@ -0,0 +1,16 @@ +// edition:2018 + +#![feature(thread_local)] +#![feature(const_swap)] +#[thread_local] +static mut STATIC_VAR_2: [u32; 8] = [4; 8]; +const fn g(x: &mut [u32; 8]) { + //~^ ERROR mutable references are not allowed + std::mem::swap(x, &mut STATIC_VAR_2) + //~^ ERROR thread-local statics cannot be accessed + //~| ERROR mutable references are not allowed + //~| ERROR use of mutable static is unsafe + //~| constant functions cannot refer to statics +} + +fn main() {} diff --git a/src/test/ui/thread-local-static.stderr b/src/test/ui/thread-local-static.stderr new file mode 100644 index 00000000000..08bf593a5a7 --- /dev/null +++ b/src/test/ui/thread-local-static.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:7:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:9:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:9:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:9:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:9:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/src/tools/cargo b/src/tools/cargo -Subproject e931e4796b61de593aa1097649445e535c9c7ee +Subproject 0cecbd67323ca14a7eb6505900d0d7307b00355 diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index da5a0712c95..41af8e190dd 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -2493,6 +2493,7 @@ Released 2018-09-13 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic +[`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_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or @@ -2622,6 +2623,7 @@ Released 2018-09-13 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes +[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro @@ -2670,6 +2672,7 @@ Released 2018-09-13 [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl [`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings +[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment diff --git a/src/tools/clippy/COPYRIGHT b/src/tools/clippy/COPYRIGHT index 80d64472c70..238c919b69d 100644 --- a/src/tools/clippy/COPYRIGHT +++ b/src/tools/clippy/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 2014-2020 The Rust Project Developers +Copyright 2014-2021 The Rust Project Developers Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 848476a9d05..b003b15a11d 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -33,12 +33,13 @@ tempfile = { version = "3.1.0", optional = true } cargo_metadata = "0.12" compiletest_rs = { version = "0.6.0", features = ["tmp"] } tester = "0.9" -clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = { version = "1.0", features = ["derive"] } derive-new = "0.5" regex = "1.4" quote = "1" syn = { version = "1", features = ["full"] } +# This is used by the `collect-metadata` alias. +filetime = "0.2" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/tools/clippy/LICENSE-APACHE b/src/tools/clippy/LICENSE-APACHE index d821a4de2be..04169a42b8b 100644 --- a/src/tools/clippy/LICENSE-APACHE +++ b/src/tools/clippy/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2014-2020 The Rust Project Developers +Copyright 2014-2021 The Rust Project Developers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/tools/clippy/LICENSE-MIT b/src/tools/clippy/LICENSE-MIT index b7c70dd4026..90a2d3950d1 100644 --- a/src/tools/clippy/LICENSE-MIT +++ b/src/tools/clippy/LICENSE-MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-2020 The Rust Project Developers +Copyright (c) 2014-2021 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index 8c0c16c443d..6c556f579ca 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -147,6 +147,7 @@ Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml value` mapping eg. ```toml +avoid-breaking-exported-api = false blacklisted-names = ["toto", "tata", "titi"] cognitive-complexity-threshold = 30 ``` @@ -236,7 +237,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT ## License -Copyright 2014-2020 The Rust Project Developers +Copyright 2014-2021 The Rust Project Developers Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license diff --git a/src/tools/clippy/build.rs b/src/tools/clippy/build.rs index 018375dbada..b5484bec3c8 100644 --- a/src/tools/clippy/build.rs +++ b/src/tools/clippy/build.rs @@ -14,6 +14,6 @@ fn main() { ); println!( "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", - rustc_tools_util::get_channel().unwrap_or_default() + rustc_tools_util::get_channel() ); } diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml new file mode 100644 index 00000000000..cda8d17eed4 --- /dev/null +++ b/src/tools/clippy/clippy.toml @@ -0,0 +1 @@ +avoid-breaking-exported-api = false diff --git a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs index 5fbf4bdbd18..49d4350123f 100644 --- a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs @@ -3,9 +3,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::consts::{constant, Constant}; - use clippy_utils::comparisons::{normalize_comparison, Rel}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; use clippy_utils::ty::is_isize_or_usize; diff --git a/src/tools/clippy/clippy_lints/src/arithmetic.rs b/src/tools/clippy/clippy_lints/src/arithmetic.rs index c560f545d6a..24c2a972811 100644 --- a/src/tools/clippy/clippy_lints/src/arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/arithmetic.rs @@ -1,4 +1,4 @@ -use crate::consts::constant_simple; +use clippy_utils::consts::constant_simple; use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index c565e29d078..5235b2642d1 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet_opt; use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call}; @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { &format!("`assert!(false, {})` should probably be replaced", panic_message), None, &format!("use `panic!({})` or `unreachable!({})`", panic_message, panic_message), - ) + ); }; if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") { diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index c5b01461c1c..932cd58bf62 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -273,7 +273,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { 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) + check_attrs(cx, item.span, item.ident.name, attrs); } match item.kind { ItemKind::ExternCrate(..) | ItemKind::Use(..) => { @@ -343,13 +343,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { 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())) + 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())) + check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); } } } diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/bit_mask.rs index f7daf3dab49..991ed94572c 100644 --- a/src/tools/clippy/clippy_lints/src/bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/bit_mask.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::sugg::Sugg; use if_chain::if_chain; @@ -115,9 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for BitMask { if let ExprKind::Binary(cmp, left, right) = &e.kind { if cmp.node.is_comparison() { if let Some(cmp_opt) = fetch_int_literal(cx, right) { - check_compare(cx, left, cmp.node, cmp_opt, e.span) + check_compare(cx, left, cmp.node, cmp_opt, e.span); } else if let Some(cmp_val) = fetch_int_literal(cx, left) { - check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span) + check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span); } } } @@ -171,7 +171,7 @@ fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp } fetch_int_literal(cx, right) .or_else(|| fetch_int_literal(cx, left)) - .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span)) + .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span)); } } diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 67f0e0c7870..e72399af232 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { _: Span, _: HirId, ) { - NonminimalBoolVisitor { cx }.visit_body(body) + NonminimalBoolVisitor { cx }.visit_body(body); } } @@ -184,7 +184,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { Term(n) => { let terminal = self.terminals[n as usize]; if let Some(str) = simplify_not(self.cx, terminal) { - self.output.push_str(&str) + self.output.push_str(&str); } else { self.output.push('!'); let snip = snippet_opt(self.cx, terminal.span)?; @@ -452,7 +452,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { } match &e.kind { ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => { - self.bool_expr(e) + self.bool_expr(e); }, ExprKind::Unary(UnOp::Not, inner) => { if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs index 040e0ca8864..c9c111a2847 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{method_chain_args, sext}; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs index dae5c86bd44..6e950738239 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs @@ -92,7 +92,7 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); impl EarlyLintPass for CollapsibleIf { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { if !expr.span.from_expansion() { - check_if(cx, expr) + check_if(cx, expr); } } } diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index 2a61d58e653..b6999bef6e7 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { "`if` chain can be rewritten with `match`", None, "consider rewriting the `if` chain to use `cmp` and `match`", - ) + ); } } diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs deleted file mode 100644 index 7e87f53e3fb..00000000000 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ /dev/null @@ -1 +0,0 @@ -pub use clippy_utils::consts::*; diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index f956d171bfb..376a14b8181 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -476,7 +476,7 @@ fn emit_branches_sharing_code_lint( } suggestions.push(("end", span, suggestion.to_string())); - add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit() + add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit(); } let add_optional_msgs = |diag: &mut DiagnosticBuilder<'_>| { diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 6e883942680..759f7d4062d 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -181,9 +181,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { match stmt.kind { StmtKind::Local(local) => { if local.ty.is_some() { - self.ty_bounds.push(TyBound::Any) + self.ty_bounds.push(TyBound::Any); } else { - self.ty_bounds.push(TyBound::Nothing) + self.ty_bounds.push(TyBound::Nothing); } }, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 50ffc2e3f19..04f3d77464f 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -141,3 +141,22 @@ declare_deprecated_lint! { pub FILTER_MAP, "this lint has been replaced by `manual_filter_map`, a more specific lint" } + +declare_deprecated_lint! { + /// **What it does:** Nothing. This lint has been deprecated. + /// + /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which + /// enables the `enum_variant_names` lint for public items. + /// ``` + pub PUB_ENUM_VARIANT_NAMES, + "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items" +} + +declare_deprecated_lint! { + /// **What it does:** Nothing. This lint has been deprecated. + /// + /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which + /// enables the `wrong_self_conversion` lint for public items. + pub WRONG_PUB_SELF_CONVENTION, + "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items" +} diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs index 58543ae6e4e..4966638cb1b 100644 --- a/src/tools/clippy/clippy_lints/src/double_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/double_comparison.rs @@ -70,16 +70,16 @@ impl<'tcx> DoubleComparisons { #[rustfmt::skip] match (op, lkind, rkind) { (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => { - lint_double_comparison!(<=) + lint_double_comparison!(<=); }, (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => { - lint_double_comparison!(>=) + lint_double_comparison!(>=); }, (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => { - lint_double_comparison!(!=) + lint_double_comparison!(!=); }, (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { - lint_double_comparison!(==) + lint_double_comparison!(==); }, _ => (), }; diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs index 529807770f3..94b09bf7173 100644 --- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs +++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs @@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::paths; diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 8db5050a5ac..2eb8b1422ed 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -469,7 +469,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { let mut is_map_used = self.is_map_used; for arm in arms { if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard { - self.visit_non_tail_expr(guard) + self.visit_non_tail_expr(guard); } is_map_used |= self.visit_cond_arm(arm.body); } diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 7a98ae39d3a..021136ac5e0 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -1,7 +1,7 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that //! don't fit into an `i32` -use crate::consts::{miri_to_const, Constant}; +use clippy_utils::consts::{miri_to_const, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index 0ecc0bc3eb6..b1a105a51c1 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -3,8 +3,8 @@ use clippy_utils::camel_case; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::is_present_in_source; -use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; +use rustc_hir::{EnumDef, Item, ItemKind}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -40,36 +40,6 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Detects public enumeration variants that are - /// prefixed or suffixed by the same characters. - /// - /// **Why is this bad?** Public enumeration variant names should specify their variant, - /// not repeat the enumeration name. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// pub enum Cake { - /// BlackForestCake, - /// HummingbirdCake, - /// BattenbergCake, - /// } - /// ``` - /// Could be written as: - /// ```rust - /// pub enum Cake { - /// BlackForest, - /// Hummingbird, - /// Battenberg, - /// } - /// ``` - pub PUB_ENUM_VARIANT_NAMES, - pedantic, - "public enums where all variants share a prefix/postfix" -} - -declare_clippy_lint! { /// **What it does:** Detects type names that are prefixed or suffixed by the /// containing module's name. /// @@ -127,21 +97,22 @@ declare_clippy_lint! { pub struct EnumVariantNames { modules: Vec<(Symbol, String)>, threshold: u64, + avoid_breaking_exported_api: bool, } impl EnumVariantNames { #[must_use] - pub fn new(threshold: u64) -> Self { + pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self { Self { modules: Vec::new(), threshold, + avoid_breaking_exported_api, } } } impl_lint_pass!(EnumVariantNames => [ ENUM_VARIANT_NAMES, - PUB_ENUM_VARIANT_NAMES, MODULE_NAME_REPETITIONS, MODULE_INCEPTION ]); @@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize { } fn check_variant( - cx: &EarlyContext<'_>, + cx: &LateContext<'_>, threshold: u64, - def: &EnumDef, + def: &EnumDef<'_>, item_name: &str, item_name_chars: usize, span: Span, - lint: &'static Lint, ) { if (def.variants.len() as u64) < threshold { return; } - for var in &def.variants { + for var in def.variants { let name = var.ident.name.as_str(); if partial_match(item_name, &name) == item_name_chars && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) { - span_lint(cx, lint, var.span, "variant name starts with the enum's name"); + span_lint( + cx, + ENUM_VARIANT_NAMES, + var.span, + "variant name starts with the enum's name", + ); } if partial_rmatch(item_name, &name) == item_name_chars { - span_lint(cx, lint, var.span, "variant name ends with the enum's name"); + span_lint( + cx, + ENUM_VARIANT_NAMES, + var.span, + "variant name ends with the enum's name", + ); } } let first = &def.variants[0].ident.name.as_str(); let mut pre = &first[..camel_case::until(&*first)]; let mut post = &first[camel_case::from(&*first)..]; - for var in &def.variants { + for var in def.variants { let name = var.ident.name.as_str(); let pre_match = partial_match(pre, &name); @@ -226,7 +206,7 @@ fn check_variant( }; span_lint_and_help( cx, - lint, + ENUM_VARIANT_NAMES, span, &format!("all variants have the same {}fix: `{}`", what, value), None, @@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String { s } -impl EarlyLintPass for EnumVariantNames { - fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) { +impl LateLintPass<'_> for EnumVariantNames { + fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) { let last = self.modules.pop(); assert!(last.is_some()); } #[allow(clippy::similar_names)] - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { let item_name = item.ident.name.as_str(); let item_name_chars = item_name.chars().count(); let item_camel = to_camel_case(&item_name); @@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames { ); } } - if item.vis.kind.is_pub() { + if item.vis.node.is_pub() { let matching = partial_match(mod_camel, &item_camel); let rmatching = partial_rmatch(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); @@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.kind { - let lint = match item.vis.kind { - VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES, - _ => ENUM_VARIANT_NAMES, - }; - check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint); + if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) { + check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span); + } } self.modules.push((item.ident.name, item_camel)); } diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs index 90f391b5f5c..a3a8e748d99 100644 --- a/src/tools/clippy/clippy_lints/src/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/eq_op.rs @@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { vec![(left.span, lsnip), (right.span, rsnip)], ); }, - ) + ); } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()]) @@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { Applicability::MaybeIncorrect, // FIXME #2597 ); }, - ) + ); } else if !lcpy && rcpy && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()]) @@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { Applicability::MaybeIncorrect, // FIXME #2597 ); }, - ) + ); } }, // &foo == bar @@ -218,7 +218,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { Applicability::MaybeIncorrect, // FIXME #2597 ); }, - ) + ); } }, // foo == &bar @@ -236,7 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp { rsnip, Applicability::MaybeIncorrect, // FIXME #2597 ); - }) + }); } }, _ => {}, diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs index f95ca86a2d0..4aa9c25b1b0 100644 --- a/src/tools/clippy/clippy_lints/src/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs @@ -1,11 +1,10 @@ +use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use crate::consts::{constant_simple, Constant}; - declare_clippy_lint! { /// **What it does:** Checks for erasing operations, e.g., `x * 0`. /// diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 2f1aa53236d..8d066f305ee 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { for arg in args { // skip `foo(macro!())` if arg.span.ctxt() == expr.span.ctxt() { - check_closure(cx, arg) + check_closure(cx, arg); } } }, @@ -92,17 +92,19 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { let ex = &body.value; if ex.span.ctxt() != expr.span.ctxt() { - if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) { - // replace `|| vec![]` with `Vec::new` - span_lint_and_sugg( - cx, - REDUNDANT_CLOSURE, - expr.span, - "redundant closure", - "replace the closure with `Vec::new`", - "std::vec::Vec::new".into(), - Applicability::MachineApplicable, - ); + if decl.inputs.is_empty() { + if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) { + // replace `|| vec![]` with `Vec::new` + span_lint_and_sugg( + cx, + REDUNDANT_CLOSURE, + expr.span, + "redundant closure", + "replace the closure with `Vec::new`", + "std::vec::Vec::new".into(), + Applicability::MachineApplicable, + ); + } } // skip `foo(|| macro!())` return; @@ -188,9 +190,10 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a cx.tcx.impl_of_method(method_def_id).and_then(|_| { //a type may implicitly implement other type's methods (e.g. Deref) if match_types(expected_type_of_self, actual_type_of_self) { - return Some(get_type_name(cx, actual_type_of_self)); + Some(get_type_name(cx, actual_type_of_self)) + } else { + None } - None }) } diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs index 41acf55dd7d..5fdf5bc9e9d 100644 --- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs +++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { self.visit_expr(e); for arm in arms { if let Some(Guard::If(if_expr)) = arm.guard { - self.visit_expr(if_expr) + self.visit_expr(if_expr); } // make sure top level arm expressions aren't linted self.maybe_walk_expr(&*arm.body); diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 08f28cd54c5..e38384b01d4 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -1,4 +1,4 @@ -use crate::consts::{ +use clippy_utils::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 20288427b4a..7f4fb68cf2f 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -240,7 +240,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { } }, Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => { - self.mutates_static |= is_mutated_static(target) + self.mutates_static |= is_mutated_static(target); }, _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index b8ea6990866..af759a48e10 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -116,7 +116,7 @@ impl<'a, 'tcx> DerefVisitor<'a, 'tcx> { self.cx, NOT_UNSAFE_PTR_ARG_DEREF, ptr.span, - "this public function dereferences a raw pointer but is not marked `unsafe`", + "this public function might dereference a raw pointer but is not marked `unsafe`", ); } } diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs index aa5494d5a7d..a666fee1a4a 100644 --- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs @@ -4,7 +4,7 @@ use rustc_middle::lint::in_external_macro; use rustc_span::Span; use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::snippet; +use clippy_utils::source::snippet_opt; use super::TOO_MANY_LINES; @@ -13,15 +13,25 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<' return; } - let code_snippet = snippet(cx, body.value.span, ".."); + let code_snippet = match snippet_opt(cx, body.value.span) { + Some(s) => s, + _ => return, + }; let mut line_count: u64 = 0; let mut in_comment = false; let mut code_in_line; - // Skip the surrounding function decl. - let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1); - let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len()); - let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines(); + let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..)) + && code_snippet.as_bytes().first().copied() == Some(b'{') + && code_snippet.as_bytes().last().copied() == Some(b'}') + { + // Removing the braces from the enclosing block + &code_snippet[1..code_snippet.len() - 1] + } else { + &code_snippet + } + .trim() // Remove leading and trailing blank lines + .lines(); for mut line in function_lines { code_in_line = false; @@ -63,6 +73,6 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<' "this function has too many lines ({}/{})", line_count, too_many_lines_threshold ), - ) + ); } } diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 04730ace887..515b8887453 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { )); } } - }) + }); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index 366b3b46a8a..99c461930e4 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -6,7 +6,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use crate::consts::{constant_simple, Constant}; +use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{clip, unsext}; diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index 260a8f50157..f2f830ca5c0 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -67,7 +67,7 @@ fn lint_break(cx: &LateContext<'_>, break_span: Span, expr_span: Span) { "change `break` to `return` as shown", format!("return {}", snip), app, - ) + ); } #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 1c54599abc4..bfa284f333a 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -1,6 +1,6 @@ //! lint on indexing and slicing operations -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::higher; use rustc_ast::ast::RangeLimits; diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index afee20ce43e..6b887da2630 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for InfiniteIter { return; }, }; - span_lint(cx, lint, expr.span, msg) + span_lint(cx, lint, expr.span, msg); } } diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs index c67c02eefa5..37011f5578d 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs @@ -7,9 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; use rustc_target::abi::LayoutOf; -use crate::consts::{constant, Constant}; - use clippy_utils::comparisons::Rel; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet; use clippy_utils::{comparisons, sext}; @@ -177,7 +176,7 @@ fn upcast_comparison_bounds_err<'tcx>( }, Rel::Eq | Rel::Ne => unreachable!(), } { - err_upcast_comparison(cx, span, lhs, true) + err_upcast_comparison(cx, span, lhs, true); } else if match rel { Rel::Lt => { if invert { @@ -195,7 +194,7 @@ fn upcast_comparison_bounds_err<'tcx>( }, Rel::Eq | Rel::Ne => unreachable!(), } { - err_upcast_comparison(cx, span, lhs, false) + err_upcast_comparison(cx, span, lhs, false); } } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index bb57adff7be..583514b22f9 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -380,9 +380,9 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_> } } - check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to) + check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to); } else { - check_empty_expr(cx, span, method, lit, op) + check_empty_expr(cx, span, method, lit, op); } } diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 17e23781db7..e627b1385bc 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { None, "consider using an underscore-prefixed named \ binding or dropping explicitly with `std::mem::drop`" - ) + ); } else if init_ty.needs_drop(cx.tcx, cx.param_env) { span_lint_and_help( cx, @@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { None, "consider using an underscore-prefixed named \ binding or dropping explicitly with `std::mem::drop`" - ) + ); } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) { span_lint_and_help( cx, @@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { "non-binding let on an expression with `#[must_use]` type", None, "consider explicitly using expression value" - ) + ); } else if is_must_use_func_call(cx, init) { span_lint_and_help( cx, @@ -163,7 +163,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { "non-binding let on a result of a `#[must_use]` function", None, "consider explicitly using function result" - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 2c83409b402..e7dd3952b3a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -41,6 +41,9 @@ extern crate rustc_target; extern crate rustc_trait_selection; extern crate rustc_typeck; +#[macro_use] +extern crate clippy_utils; + use clippy_utils::parse_msrv; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; @@ -145,25 +148,9 @@ macro_rules! declare_clippy_lint { }; } -#[macro_export] -macro_rules! sym { - ( $($x:tt)* ) => { clippy_utils::sym!($($x)*) } -} - -#[macro_export] -macro_rules! unwrap_cargo_metadata { - ( $($x:tt)* ) => { clippy_utils::unwrap_cargo_metadata!($($x)*) } -} - -macro_rules! extract_msrv_attr { - ( $($x:tt)* ) => { clippy_utils::extract_msrv_attr!($($x)*); } -} - -mod consts; -#[macro_use] -mod utils; #[cfg(feature = "metadata-collector-lint")] mod deprecated_lints; +mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` mod absurd_extreme_comparisons; @@ -405,7 +392,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) { #[doc(hidden)] pub fn read_conf(sess: &Session) -> Conf { - use std::path::Path; let file_name = match utils::conf::lookup_conf_file() { Ok(Some(path)) => path, Ok(None) => return Conf::default(), @@ -416,16 +402,6 @@ pub fn read_conf(sess: &Session) -> Conf { }, }; - let file_name = if file_name.is_relative() { - sess.local_crate_source_file - .as_deref() - .and_then(Path::parent) - .unwrap_or_else(|| Path::new("")) - .join(file_name) - } else { - file_name - }; - let TryConf { conf, errors } = utils::conf::read(&file_name); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { @@ -505,6 +481,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::filter_map", "this lint has been replaced by `manual_filter_map`, a more specific lint", ); + store.register_removed( + "clippy::pub_enum_variant_names", + "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items", + ); + store.register_removed( + "clippy::wrong_pub_self_convention", + "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` // begin register lints, do not remove this comment, it’s used in `update_lints` @@ -618,7 +602,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: enum_variants::ENUM_VARIANT_NAMES, enum_variants::MODULE_INCEPTION, enum_variants::MODULE_NAME_REPETITIONS, - enum_variants::PUB_ENUM_VARIANT_NAMES, eq_op::EQ_OP, eq_op::OP_REF, erasing_op::ERASING_OP, @@ -779,6 +762,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: methods::MANUAL_FILTER_MAP, methods::MANUAL_FIND_MAP, methods::MANUAL_SATURATING_ARITHMETIC, + methods::MANUAL_STR_REPEAT, methods::MAP_COLLECT_RESULT_UNIT, methods::MAP_FLATTEN, methods::MAP_UNWRAP_OR, @@ -796,13 +780,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: methods::SKIP_WHILE_NEXT, methods::STRING_EXTEND_CHARS, methods::SUSPICIOUS_MAP, + methods::SUSPICIOUS_SPLITN, methods::UNINIT_ASSUMED_INIT, methods::UNNECESSARY_FILTER_MAP, methods::UNNECESSARY_FOLD, methods::UNNECESSARY_LAZY_EVALUATIONS, methods::UNWRAP_USED, methods::USELESS_ASREF, - methods::WRONG_PUB_SELF_CONVENTION, methods::WRONG_SELF_CONVENTION, methods::ZST_OFFSET, minmax::MIN_MAX, @@ -841,6 +825,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: needless_bool::BOOL_COMPARISON, needless_bool::NEEDLESS_BOOL, needless_borrow::NEEDLESS_BORROW, + needless_borrow::REF_BINDING_TO_REFERENCE, needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, needless_continue::NEEDLESS_CONTINUE, needless_for_each::NEEDLESS_FOR_EACH, @@ -995,291 +980,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ]); // end register lints, do not remove this comment, it’s used in `update_lints` - // all the internal lints - #[cfg(feature = "internal-lints")] - { - store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal); - store.register_early_pass(|| box utils::internal_lints::ProduceIce); - store.register_late_pass(|| box utils::inspector::DeepCodeInspector); - store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); - store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new()); - store.register_late_pass(|| box utils::internal_lints::IfChainStyle); - store.register_late_pass(|| box utils::internal_lints::InvalidPaths); - store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default()); - store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default()); - store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem); - store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass); - } - #[cfg(feature = "metadata-collector-lint")] - { - if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new()); - } - } - - store.register_late_pass(|| box utils::author::Author); - store.register_late_pass(|| box await_holding_invalid::AwaitHolding); - store.register_late_pass(|| box serde_api::SerdeApi); - let vec_box_size_threshold = conf.vec_box_size_threshold; - let type_complexity_threshold = conf.type_complexity_threshold; - store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold)); - store.register_late_pass(|| box booleans::NonminimalBool); - store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool); - store.register_late_pass(|| box eq_op::EqOp); - store.register_late_pass(|| box enum_clike::UnportableVariant); - store.register_late_pass(|| box float_literal::FloatLiteral); - let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; - store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold)); - store.register_late_pass(|| box ptr::Ptr); - store.register_late_pass(|| box ptr_eq::PtrEq); - store.register_late_pass(|| box needless_bool::NeedlessBool); - store.register_late_pass(|| box needless_bool::BoolComparison); - store.register_late_pass(|| box needless_for_each::NeedlessForEach); - store.register_late_pass(|| box approx_const::ApproxConstant); - store.register_late_pass(|| box misc::MiscLints); - store.register_late_pass(|| box eta_reduction::EtaReduction); - store.register_late_pass(|| box identity_op::IdentityOp); - store.register_late_pass(|| box erasing_op::ErasingOp); - store.register_late_pass(|| box mut_mut::MutMut); - store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed); - store.register_late_pass(|| box len_zero::LenZero); - store.register_late_pass(|| box attrs::Attributes); - store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions); - store.register_late_pass(|| box collapsible_match::CollapsibleMatch); - store.register_late_pass(|| box unicode::Unicode); - store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd); - store.register_late_pass(|| box strings::StringAdd); - store.register_late_pass(|| box implicit_return::ImplicitReturn); - store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub); - store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback); - store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor); - store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions); - store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports); - - let msrv = conf.msrv.as_ref().and_then(|s| { - parse_msrv(s, None, None).or_else(|| { - sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s)); - None - }) - }); - - store.register_late_pass(move || box methods::Methods::new(msrv)); - store.register_late_pass(move || box matches::Matches::new(msrv)); - store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv)); - store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv)); - store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv)); - store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv)); - store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv)); - store.register_late_pass(move || box mem_replace::MemReplace::new(msrv)); - store.register_late_pass(move || box ranges::Ranges::new(msrv)); - store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv)); - store.register_late_pass(move || box use_self::UseSelf::new(msrv)); - store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv)); - store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark); - store.register_late_pass(move || box casts::Casts::new(msrv)); - store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv)); - - store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount); - store.register_late_pass(|| box map_clone::MapClone); - store.register_late_pass(|| box map_err_ignore::MapErrIgnore); - store.register_late_pass(|| box shadow::Shadow); - store.register_late_pass(|| box unit_types::UnitTypes); - store.register_late_pass(|| box loops::Loops); - store.register_late_pass(|| box main_recursion::MainRecursion::default()); - store.register_late_pass(|| box lifetimes::Lifetimes); - store.register_late_pass(|| box entry::HashMapPass); - store.register_late_pass(|| box minmax::MinMaxPass); - store.register_late_pass(|| box open_options::OpenOptions); - store.register_late_pass(|| box zero_div_zero::ZeroDiv); - store.register_late_pass(|| box mutex_atomic::Mutex); - store.register_late_pass(|| box needless_update::NeedlessUpdate); - store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default()); - store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef); - store.register_late_pass(|| box no_effect::NoEffect); - store.register_late_pass(|| box temporary_assignment::TemporaryAssignment); - store.register_late_pass(|| box transmute::Transmute); - let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; - store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold)); - let too_large_for_stack = conf.too_large_for_stack; - store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack}); - store.register_late_pass(move || box vec::UselessVec{too_large_for_stack}); - store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented); - store.register_late_pass(|| box strings::StringLitAsBytes); - store.register_late_pass(|| box derive::Derive); - store.register_late_pass(|| box get_last_with_len::GetLastWithLen); - store.register_late_pass(|| box drop_forget_ref::DropForgetRef); - store.register_late_pass(|| box empty_enum::EmptyEnum); - store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons); - store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons); - store.register_late_pass(|| box regex::Regex::default()); - store.register_late_pass(|| box copies::CopyAndPaste); - store.register_late_pass(|| box copy_iterator::CopyIterator); - store.register_late_pass(|| box format::UselessFormat); - store.register_late_pass(|| box swap::Swap); - store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional); - store.register_late_pass(|| box new_without_default::NewWithoutDefault::default()); - let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>(); - store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone())); - let too_many_arguments_threshold = conf.too_many_arguments_threshold; - let too_many_lines_threshold = conf.too_many_lines_threshold; - store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold)); - let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>(); - store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone())); - store.register_late_pass(|| box neg_multiply::NegMultiply); - store.register_late_pass(|| box mem_discriminant::MemDiscriminant); - store.register_late_pass(|| box mem_forget::MemForget); - store.register_late_pass(|| box arithmetic::Arithmetic::default()); - store.register_late_pass(|| box assign_ops::AssignOps); - store.register_late_pass(|| box let_if_seq::LetIfSeq); - store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence); - store.register_late_pass(|| box missing_doc::MissingDoc::new()); - store.register_late_pass(|| box missing_inline::MissingInline); - store.register_late_pass(move || box exhaustive_items::ExhaustiveItems); - store.register_late_pass(|| box if_let_some_result::OkIfLet); - store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl); - store.register_late_pass(|| box unused_io_amount::UnusedIoAmount); - let enum_variant_size_threshold = conf.enum_variant_size_threshold; - store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)); - store.register_late_pass(|| box explicit_write::ExplicitWrite); - store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue); - let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( - conf.trivial_copy_size_limit, - conf.pass_by_value_size_limit, - &sess.target, - ); - store.register_late_pass(move || box pass_by_ref_or_value); - store.register_late_pass(|| box ref_option_ref::RefOptionRef); - store.register_late_pass(|| box try_err::TryErr); - store.register_late_pass(|| box bytecount::ByteCount); - store.register_late_pass(|| box infinite_iter::InfiniteIter); - store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody); - store.register_late_pass(|| box useless_conversion::UselessConversion::default()); - store.register_late_pass(|| box implicit_hasher::ImplicitHasher); - store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); - store.register_late_pass(|| box double_comparison::DoubleComparisons); - store.register_late_pass(|| box question_mark::QuestionMark); - store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings); - store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl); - store.register_late_pass(|| box map_unit_fn::MapUnit); - store.register_late_pass(|| box inherent_impl::MultipleInherentImpl); - store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); - store.register_late_pass(|| box unwrap::Unwrap); - store.register_late_pass(|| box duration_subsec::DurationSubsec); - store.register_late_pass(|| box indexing_slicing::IndexingSlicing); - store.register_late_pass(|| box non_copy_const::NonCopyConst); - store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast); - store.register_late_pass(|| box redundant_clone::RedundantClone); - store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); - store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy); - store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps); - store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); - store.register_late_pass(|| box transmuting_null::TransmutingNull); - store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite); - store.register_late_pass(|| box integer_division::IntegerDivision); - store.register_late_pass(|| box inherent_to_string::InherentToString); - let max_trait_bounds = conf.max_trait_bounds; - store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds)); - store.register_late_pass(|| box comparison_chain::ComparisonChain); - store.register_late_pass(|| box mut_key::MutableKeyType); - store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic); - store.register_early_pass(|| box reference::DerefAddrOf); - store.register_early_pass(|| box reference::RefInDeref); - store.register_early_pass(|| box double_parens::DoubleParens); - store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new()); - store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval); - store.register_early_pass(|| box if_not_else::IfNotElse); - store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse); - store.register_early_pass(|| box int_plus_one::IntPlusOne); - store.register_early_pass(|| box formatting::Formatting); - store.register_early_pass(|| box misc_early::MiscEarlyLints); - store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall); - store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall); - store.register_early_pass(|| box unused_unit::UnusedUnit); - store.register_late_pass(|| box returns::Return); - store.register_early_pass(|| box collapsible_if::CollapsibleIf); - store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); - store.register_early_pass(|| box precedence::Precedence); - store.register_early_pass(|| box needless_continue::NeedlessContinue); - store.register_early_pass(|| box redundant_else::RedundantElse); - store.register_late_pass(|| box create_dir::CreateDir); - store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType); - let cargo_ignore_publish = conf.cargo_ignore_publish; - store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish)); - store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); - store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies); - let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; - store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability)); - let literal_representation_threshold = conf.literal_representation_threshold; - store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold)); - let enum_variant_name_threshold = conf.enum_variant_name_threshold; - store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold)); - store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments); - let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; - store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive)); - store.register_late_pass(|| box default::Default::default()); - store.register_late_pass(|| box unused_self::UnusedSelf); - store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall); - store.register_late_pass(|| box exit::Exit); - store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome); - let array_size_threshold = conf.array_size_threshold; - store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold)); - store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold)); - store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic); - store.register_early_pass(|| box as_conversions::AsConversions); - store.register_late_pass(|| box let_underscore::LetUnderscore); - store.register_late_pass(|| box atomic_ordering::AtomicOrdering); - store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports); - let max_fn_params_bools = conf.max_fn_params_bools; - let max_struct_bools = conf.max_struct_bools; - store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); - store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); - let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; - store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); - store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); - store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); - store.register_late_pass(|| box unnamed_address::UnnamedAddress); - store.register_late_pass(|| box dereference::Dereferencing::default()); - store.register_late_pass(|| box option_if_let_else::OptionIfLetElse); - store.register_late_pass(|| box future_not_send::FutureNotSend); - store.register_late_pass(|| box if_let_mutex::IfLetMutex); - store.register_late_pass(|| box mut_mutex_lock::MutMutexLock); - store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); - store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); - store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero); - store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn); - let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; - store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { - single_char_binding_names_threshold, - }); - store.register_late_pass(|| box macro_use::MacroUseImports::default()); - store.register_late_pass(|| box map_identity::MapIdentity); - store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); - store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); - store.register_late_pass(|| box repeat_once::RepeatOnce); - store.register_late_pass(|| box unwrap_in_result::UnwrapInResult); - store.register_late_pass(|| box self_assignment::SelfAssignment); - store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr); - store.register_late_pass(|| box manual_ok_or::ManualOkOr); - store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); - store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned); - store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync); - let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>(); - store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods)); - store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax); - store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax); - store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops); - store.register_late_pass(|| box strings::StrToString); - store.register_late_pass(|| box strings::StringToString); - store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues); - store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default()); - store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons); - store.register_late_pass(|| box redundant_slicing::RedundantSlicing); - store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); - store.register_late_pass(|| box manual_map::ManualMap); - store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv)); - store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison); - store.register_late_pass(|| box unused_async::UnusedAsync); - store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(arithmetic::FLOAT_ARITHMETIC), LintId::of(arithmetic::INTEGER_ARITHMETIC), @@ -1310,7 +1010,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::FILETYPE_IS_FILE), LintId::of(methods::GET_UNWRAP), LintId::of(methods::UNWRAP_USED), - LintId::of(methods::WRONG_PUB_SELF_CONVENTION), LintId::of(misc::FLOAT_CMP_CONST), LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), @@ -1322,7 +1021,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(panic_unimplemented::UNIMPLEMENTED), LintId::of(panic_unimplemented::UNREACHABLE), LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH), - LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), LintId::of(shadow::SHADOW_REUSE), LintId::of(shadow::SHADOW_SAME), LintId::of(strings::STRING_ADD), @@ -1363,7 +1061,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(doc::MISSING_PANICS_DOC), LintId::of(empty_enum::EMPTY_ENUM), LintId::of(enum_variants::MODULE_NAME_REPETITIONS), - LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES), LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), @@ -1401,6 +1098,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), LintId::of(mut_mut::MUT_MUT), LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL), + LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE), LintId::of(needless_continue::NEEDLESS_CONTINUE), LintId::of(needless_for_each::NEEDLESS_FOR_EACH), LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), @@ -1412,6 +1110,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(ranges::RANGE_PLUS_ONE), LintId::of(redundant_else::REDUNDANT_ELSE), LintId::of(ref_option_ref::REF_OPTION_REF), + LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), LintId::of(shadow::SHADOW_UNRELATED), LintId::of(strings::STRING_ADD_ASSIGN), LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), @@ -1600,6 +1299,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::MANUAL_FILTER_MAP), LintId::of(methods::MANUAL_FIND_MAP), LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), + LintId::of(methods::MANUAL_STR_REPEAT), LintId::of(methods::MAP_COLLECT_RESULT_UNIT), LintId::of(methods::NEW_RET_NO_SELF), LintId::of(methods::OK_EXPECT), @@ -1615,6 +1315,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::SKIP_WHILE_NEXT), LintId::of(methods::STRING_EXTEND_CHARS), LintId::of(methods::SUSPICIOUS_MAP), + LintId::of(methods::SUSPICIOUS_SPLITN), LintId::of(methods::UNINIT_ASSUMED_INIT), LintId::of(methods::UNNECESSARY_FILTER_MAP), LintId::of(methods::UNNECESSARY_FOLD), @@ -1644,6 +1345,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), LintId::of(needless_bool::BOOL_COMPARISON), LintId::of(needless_bool::NEEDLESS_BOOL), + LintId::of(needless_borrow::NEEDLESS_BORROW), LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), LintId::of(needless_update::NEEDLESS_UPDATE), @@ -1690,7 +1392,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), - LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), LintId::of(swap::ALMOST_SWAPPED), @@ -1827,6 +1528,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(misc_early::REDUNDANT_PATTERN), LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(needless_borrow::NEEDLESS_BORROW), LintId::of(neg_multiply::NEG_MULTIPLY), LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), @@ -1843,7 +1545,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(returns::LET_AND_RETURN), LintId::of(returns::NEEDLESS_RETURN), LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), LintId::of(try_err::TRY_ERR), @@ -1991,6 +1692,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), LintId::of(methods::CLONE_DOUBLE_REF), LintId::of(methods::ITERATOR_STEP_BY_ZERO), + LintId::of(methods::SUSPICIOUS_SPLITN), LintId::of(methods::UNINIT_ASSUMED_INIT), LintId::of(methods::ZST_OFFSET), LintId::of(minmax::MIN_MAX), @@ -2035,6 +1737,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(loops::NEEDLESS_COLLECT), LintId::of(methods::EXPECT_FUN_CALL), LintId::of(methods::ITER_NTH), + LintId::of(methods::MANUAL_STR_REPEAT), LintId::of(methods::OR_FUN_CALL), LintId::of(methods::SINGLE_CHAR_PATTERN), LintId::of(misc::CMP_OWNED), @@ -2066,14 +1769,304 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), LintId::of(mutex_atomic::MUTEX_INTEGER), - LintId::of(needless_borrow::NEEDLESS_BORROW), LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE), LintId::of(regex::TRIVIAL_REGEX), LintId::of(strings::STRING_LIT_AS_BYTES), + LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(transmute::USELESS_TRANSMUTE), LintId::of(use_self::USE_SELF), ]); + + #[cfg(feature = "metadata-collector-lint")] + { + if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { + store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new()); + return; + } + } + + // all the internal lints + #[cfg(feature = "internal-lints")] + { + store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal); + store.register_early_pass(|| box utils::internal_lints::ProduceIce); + store.register_late_pass(|| box utils::inspector::DeepCodeInspector); + store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); + store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new()); + store.register_late_pass(|| box utils::internal_lints::IfChainStyle); + store.register_late_pass(|| box utils::internal_lints::InvalidPaths); + store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default()); + store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default()); + store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem); + store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass); + } + + store.register_late_pass(|| box utils::author::Author); + store.register_late_pass(|| box await_holding_invalid::AwaitHolding); + store.register_late_pass(|| box serde_api::SerdeApi); + let vec_box_size_threshold = conf.vec_box_size_threshold; + let type_complexity_threshold = conf.type_complexity_threshold; + store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold)); + store.register_late_pass(|| box booleans::NonminimalBool); + store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool); + store.register_late_pass(|| box eq_op::EqOp); + store.register_late_pass(|| box enum_clike::UnportableVariant); + store.register_late_pass(|| box float_literal::FloatLiteral); + let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; + store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold)); + store.register_late_pass(|| box ptr::Ptr); + store.register_late_pass(|| box ptr_eq::PtrEq); + store.register_late_pass(|| box needless_bool::NeedlessBool); + store.register_late_pass(|| box needless_bool::BoolComparison); + store.register_late_pass(|| box needless_for_each::NeedlessForEach); + store.register_late_pass(|| box approx_const::ApproxConstant); + store.register_late_pass(|| box misc::MiscLints); + store.register_late_pass(|| box eta_reduction::EtaReduction); + store.register_late_pass(|| box identity_op::IdentityOp); + store.register_late_pass(|| box erasing_op::ErasingOp); + store.register_late_pass(|| box mut_mut::MutMut); + store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed); + store.register_late_pass(|| box len_zero::LenZero); + store.register_late_pass(|| box attrs::Attributes); + store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions); + store.register_late_pass(|| box collapsible_match::CollapsibleMatch); + store.register_late_pass(|| box unicode::Unicode); + store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd); + store.register_late_pass(|| box strings::StringAdd); + store.register_late_pass(|| box implicit_return::ImplicitReturn); + store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub); + store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback); + store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor); + store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions); + store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports); + + let msrv = conf.msrv.as_ref().and_then(|s| { + parse_msrv(s, None, None).or_else(|| { + sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s)); + None + }) + }); + + let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; + store.register_late_pass(move || box methods::Methods::new(avoid_breaking_exported_api, msrv)); + store.register_late_pass(move || box matches::Matches::new(msrv)); + store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv)); + store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv)); + store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv)); + store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv)); + store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv)); + store.register_late_pass(move || box mem_replace::MemReplace::new(msrv)); + store.register_late_pass(move || box ranges::Ranges::new(msrv)); + store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv)); + store.register_late_pass(move || box use_self::UseSelf::new(msrv)); + store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv)); + store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark); + store.register_late_pass(move || box casts::Casts::new(msrv)); + store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv)); + + store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount); + store.register_late_pass(|| box map_clone::MapClone); + store.register_late_pass(|| box map_err_ignore::MapErrIgnore); + store.register_late_pass(|| box shadow::Shadow); + store.register_late_pass(|| box unit_types::UnitTypes); + store.register_late_pass(|| box loops::Loops); + store.register_late_pass(|| box main_recursion::MainRecursion::default()); + store.register_late_pass(|| box lifetimes::Lifetimes); + store.register_late_pass(|| box entry::HashMapPass); + store.register_late_pass(|| box minmax::MinMaxPass); + store.register_late_pass(|| box open_options::OpenOptions); + store.register_late_pass(|| box zero_div_zero::ZeroDiv); + store.register_late_pass(|| box mutex_atomic::Mutex); + store.register_late_pass(|| box needless_update::NeedlessUpdate); + store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default()); + store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef); + store.register_late_pass(|| box no_effect::NoEffect); + store.register_late_pass(|| box temporary_assignment::TemporaryAssignment); + store.register_late_pass(|| box transmute::Transmute); + let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; + store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold)); + let too_large_for_stack = conf.too_large_for_stack; + store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack}); + store.register_late_pass(move || box vec::UselessVec{too_large_for_stack}); + store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented); + store.register_late_pass(|| box strings::StringLitAsBytes); + store.register_late_pass(|| box derive::Derive); + store.register_late_pass(|| box get_last_with_len::GetLastWithLen); + store.register_late_pass(|| box drop_forget_ref::DropForgetRef); + store.register_late_pass(|| box empty_enum::EmptyEnum); + store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons); + store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons); + store.register_late_pass(|| box regex::Regex::default()); + store.register_late_pass(|| box copies::CopyAndPaste); + store.register_late_pass(|| box copy_iterator::CopyIterator); + store.register_late_pass(|| box format::UselessFormat); + store.register_late_pass(|| box swap::Swap); + store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional); + store.register_late_pass(|| box new_without_default::NewWithoutDefault::default()); + let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>(); + store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone())); + let too_many_arguments_threshold = conf.too_many_arguments_threshold; + let too_many_lines_threshold = conf.too_many_lines_threshold; + store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold)); + let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>(); + store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone())); + store.register_late_pass(|| box neg_multiply::NegMultiply); + store.register_late_pass(|| box mem_discriminant::MemDiscriminant); + store.register_late_pass(|| box mem_forget::MemForget); + store.register_late_pass(|| box arithmetic::Arithmetic::default()); + store.register_late_pass(|| box assign_ops::AssignOps); + store.register_late_pass(|| box let_if_seq::LetIfSeq); + store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence); + store.register_late_pass(|| box missing_doc::MissingDoc::new()); + store.register_late_pass(|| box missing_inline::MissingInline); + store.register_late_pass(move || box exhaustive_items::ExhaustiveItems); + store.register_late_pass(|| box if_let_some_result::OkIfLet); + store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl); + store.register_late_pass(|| box unused_io_amount::UnusedIoAmount); + let enum_variant_size_threshold = conf.enum_variant_size_threshold; + store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)); + store.register_late_pass(|| box explicit_write::ExplicitWrite); + store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue); + let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( + conf.trivial_copy_size_limit, + conf.pass_by_value_size_limit, + conf.avoid_breaking_exported_api, + &sess.target, + ); + store.register_late_pass(move || box pass_by_ref_or_value); + store.register_late_pass(|| box ref_option_ref::RefOptionRef); + store.register_late_pass(|| box try_err::TryErr); + store.register_late_pass(|| box bytecount::ByteCount); + store.register_late_pass(|| box infinite_iter::InfiniteIter); + store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody); + store.register_late_pass(|| box useless_conversion::UselessConversion::default()); + store.register_late_pass(|| box implicit_hasher::ImplicitHasher); + store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); + store.register_late_pass(|| box double_comparison::DoubleComparisons); + store.register_late_pass(|| box question_mark::QuestionMark); + store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings); + store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl); + store.register_late_pass(|| box map_unit_fn::MapUnit); + store.register_late_pass(|| box inherent_impl::MultipleInherentImpl); + store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd); + store.register_late_pass(|| box unwrap::Unwrap); + store.register_late_pass(|| box duration_subsec::DurationSubsec); + store.register_late_pass(|| box indexing_slicing::IndexingSlicing); + store.register_late_pass(|| box non_copy_const::NonCopyConst); + store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast); + store.register_late_pass(|| box redundant_clone::RedundantClone); + store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit); + store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy); + store.register_late_pass(move || box unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)); + store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants); + store.register_late_pass(|| box transmuting_null::TransmutingNull); + store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite); + store.register_late_pass(|| box integer_division::IntegerDivision); + store.register_late_pass(|| box inherent_to_string::InherentToString); + let max_trait_bounds = conf.max_trait_bounds; + store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds)); + store.register_late_pass(|| box comparison_chain::ComparisonChain); + store.register_late_pass(|| box mut_key::MutableKeyType); + store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic); + store.register_early_pass(|| box reference::DerefAddrOf); + store.register_early_pass(|| box reference::RefInDeref); + store.register_early_pass(|| box double_parens::DoubleParens); + store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new()); + store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval); + store.register_early_pass(|| box if_not_else::IfNotElse); + store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse); + store.register_early_pass(|| box int_plus_one::IntPlusOne); + store.register_early_pass(|| box formatting::Formatting); + store.register_early_pass(|| box misc_early::MiscEarlyLints); + store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall); + store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall); + store.register_early_pass(|| box unused_unit::UnusedUnit); + store.register_late_pass(|| box returns::Return); + store.register_early_pass(|| box collapsible_if::CollapsibleIf); + store.register_early_pass(|| box items_after_statements::ItemsAfterStatements); + store.register_early_pass(|| box precedence::Precedence); + store.register_early_pass(|| box needless_continue::NeedlessContinue); + store.register_early_pass(|| box redundant_else::RedundantElse); + store.register_late_pass(|| box create_dir::CreateDir); + store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType); + let cargo_ignore_publish = conf.cargo_ignore_publish; + store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish)); + store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions); + store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies); + let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; + store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability)); + let literal_representation_threshold = conf.literal_representation_threshold; + store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold)); + let enum_variant_name_threshold = conf.enum_variant_name_threshold; + store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api)); + store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments); + let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; + store.register_late_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(avoid_breaking_exported_api, upper_case_acronyms_aggressive)); + store.register_late_pass(|| box default::Default::default()); + store.register_late_pass(|| box unused_self::UnusedSelf); + store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall); + store.register_late_pass(|| box exit::Exit); + store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome); + let array_size_threshold = conf.array_size_threshold; + store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold)); + store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold)); + store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic); + store.register_early_pass(|| box as_conversions::AsConversions); + store.register_late_pass(|| box let_underscore::LetUnderscore); + store.register_late_pass(|| box atomic_ordering::AtomicOrdering); + store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports); + let max_fn_params_bools = conf.max_fn_params_bools; + let max_struct_bools = conf.max_struct_bools; + store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); + store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); + let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; + store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); + store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); + store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); + store.register_late_pass(|| box unnamed_address::UnnamedAddress); + store.register_late_pass(|| box dereference::Dereferencing::default()); + store.register_late_pass(|| box option_if_let_else::OptionIfLetElse); + store.register_late_pass(|| box future_not_send::FutureNotSend); + store.register_late_pass(|| box if_let_mutex::IfLetMutex); + store.register_late_pass(|| box mut_mutex_lock::MutMutexLock); + store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); + store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); + store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero); + store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn); + let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; + store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { + single_char_binding_names_threshold, + }); + store.register_late_pass(|| box macro_use::MacroUseImports::default()); + store.register_late_pass(|| box map_identity::MapIdentity); + store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch); + store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive); + store.register_late_pass(|| box repeat_once::RepeatOnce); + store.register_late_pass(|| box unwrap_in_result::UnwrapInResult); + store.register_late_pass(|| box self_assignment::SelfAssignment); + store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr); + store.register_late_pass(|| box manual_ok_or::ManualOkOr); + store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); + store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned); + store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync); + let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>(); + store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods)); + store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax); + store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax); + store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops); + store.register_late_pass(|| box strings::StrToString); + store.register_late_pass(|| box strings::StringToString); + store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues); + store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default()); + store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons); + store.register_late_pass(|| box redundant_slicing::RedundantSlicing); + store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); + store.register_late_pass(|| box manual_map::ManualMap); + store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv)); + store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison); + store.register_late_pass(|| box unused_async::UnusedAsync); + } #[rustfmt::skip] diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 116ad072837..5ae68ba5b2f 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -205,7 +205,7 @@ fn could_use_elision<'tcx>( output_visitor.visit_ty(ty); } for lt in named_generics { - input_visitor.visit_generic_param(lt) + input_visitor.visit_generic_param(lt); } if input_visitor.abort() || output_visitor.abort() { @@ -463,7 +463,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { // `'b` in `'a: 'b` is useless unless used elsewhere in // a non-lifetime bound if let GenericParamKind::Type { .. } = param.kind { - walk_generic_param(self, param) + walk_generic_param(self, param); } } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index e93b2e36b86..e0c5578bd60 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -231,7 +231,7 @@ impl EarlyLintPass for LiteralDigitGrouping { } if let ExprKind::Lit(ref lit) = expr.kind { - self.check_lit(cx, lit) + self.check_lit(cx, lit); } } } @@ -294,7 +294,7 @@ impl LiteralDigitGrouping { } }; if should_warn { - warning_type.display(num_lit.format(), cx, lit.span) + warning_type.display(num_lit.format(), cx, lit.span); } } } @@ -424,7 +424,7 @@ impl EarlyLintPass for DecimalLiteralRepresentation { } if let ExprKind::Lit(ref lit) = expr.kind { - self.check_lit(cx, lit) + self.check_lit(cx, lit); } } } @@ -446,7 +446,7 @@ impl DecimalLiteralRepresentation { let hex = format!("{:#X}", val); let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false); let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| { - warning_type.display(num_lit.format(), cx, lit.span) + warning_type.display(num_lit.format(), cx, lit.span); }); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index ce02ad013be..f0327b5d777 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -43,7 +43,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m "to write this more concisely, try", format!("&{}{}", muta, object), applicability, - ) + ); } /// Returns `true` if the type of expr is one that provides `IntoIterator` impls diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index 1425d50f560..d07b5a93b67 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -88,10 +88,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { if let ty::BorrowKind::MutBorrow = bk { if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)) + self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); } if Some(id) == self.hir_id_high { - self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)) + self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); } } } @@ -100,10 +100,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)) + self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); } if Some(id) == self.hir_id_high { - self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)) + self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs index d3406780888..eb82c9c27c3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs @@ -1,5 +1,5 @@ use super::NEEDLESS_COLLECT; -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_type_diagnostic_item; @@ -116,9 +116,10 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo // Suggest replacing iter_call with iter_replacement, and removing stmt let mut span = MultiSpan::from_span(collect_span); span.push_span_label(iter_call.span, "the iterator could be used here instead".into()); - span_lint_and_then( + span_lint_hir_and_then( cx, super::NEEDLESS_COLLECT, + init_expr.hir_id, span, NEEDLESS_COLLECT_MSG, |diag| { diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index cb2c83e9029..0f6cd5de761 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -35,7 +35,7 @@ pub(super) fn check<'tcx>( "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})", item_str, vec_str, item_str ), - ) + ); } if !matches!(pat.kind, PatKind::Wild) { diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 4db6644b9d7..2f7360210ba 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -80,10 +80,10 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { } }, ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => { - *state = IncrementVisitorVarState::DontWarn + *state = IncrementVisitorVarState::DontWarn; }, ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => { - *state = IncrementVisitorVarState::DontWarn + *state = IncrementVisitorVarState::DontWarn; }, _ => (), } @@ -207,7 +207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { } }, ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => { - self.state = InitializeVisitorState::DontWarn + self.state = InitializeVisitorState::DontWarn; }, _ => (), } @@ -292,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { return; } } - walk_pat(self, pat) + walk_pat(self, pat); } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 55404b87ec9..5f9ebad25e8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -1,5 +1,5 @@ use super::WHILE_IMMUTABLE_CONDITION; -use crate::consts::constant; +use clippy_utils::consts::constant; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::usage::mutated_variables; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 914b583186c..66479ae264e 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -212,9 +212,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { let mut suggestions = vec![]; for ((root, span), path) in used { if path.len() == 1 { - suggestions.push((span, format!("{}::{}", root, path[0]))) + suggestions.push((span, format!("{}::{}", root, path[0]))); } else { - suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")))) + suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")))); } } @@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { "remove the attribute and import the macro directly, try", help, Applicability::MaybeIncorrect, - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 23428524dee..61b5fe81fa9 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { kind_word, snippet(cx, pattern.span, "..")))] .into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))), - ) + ); }); } } diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs index 2f579edd6ad..18038dd7819 100644 --- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs @@ -1,4 +1,4 @@ -use crate::consts::constant_simple; +use clippy_utils::consts::constant_simple; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs index 99c35ae3bbf..e1f80ab025c 100644 --- a/src/tools/clippy/clippy_lints/src/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/map_clone.rs @@ -125,7 +125,7 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) { "remove the `map` call", String::new(), Applicability::MachineApplicable, - ) + ); } fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { @@ -142,7 +142,7 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { snippet_with_applicability(cx, root, "..", &mut applicability) ), applicability, - ) + ); } else { span_lint_and_sugg( cx, @@ -155,6 +155,6 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) { snippet_with_applicability(cx, root, "..", &mut applicability) ), applicability, - ) + ); } } diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index fcd37687010..cd3e3b97928 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, miri_to_const, Constant}; +use clippy_utils::consts::{constant, miri_to_const, Constant}; use clippy_utils::diagnostics::{ multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, }; @@ -1144,7 +1144,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) "try this", suggestions.join(" | "), Applicability::MaybeIncorrect, - ) + ); }, }; } @@ -1242,7 +1242,7 @@ fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp cast, ), applicability, - ) + ); } } } @@ -1494,7 +1494,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A "consider using the scrutinee and body instead", sugg, applicability, - ) + ); } else { span_lint_and_sugg( cx, @@ -1747,7 +1747,7 @@ mod redundant_pattern_match { match match_source { MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms), MatchSource::IfLetDesugar { contains_else_clause } => { - find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause) + find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause); }, MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, &arms[0], "while", false), _ => {}, @@ -1876,7 +1876,7 @@ mod redundant_pattern_match { { self.res = true; } else { - self.visit_expr(self_arg) + self.visit_expr(self_arg); } } args.iter().for_each(|arg| self.visit_expr(arg)); diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs index a735c616f6e..aca96e06ef2 100644 --- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs +++ b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use std::iter; declare_clippy_lint! { /// **What it does:** Checks for calls of `mem::discriminant()` on a non-enum type. @@ -67,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { } } - let derefs: String = iter::repeat('*').take(derefs_needed).collect(); + let derefs = "*".repeat(derefs_needed); diag.span_suggestion( param.span, "try dereferencing", diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs index 287bff886bf..da428a7b487 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs @@ -135,7 +135,7 @@ pub(crate) trait BindInsteadOfMap { .into_iter() .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())), ), - ) + ); }); true } diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index ce2e8fa8b10..1a32af5dc7a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -8,7 +8,6 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, adjustment::Adjust}; use rustc_span::symbol::{sym, Symbol}; -use std::iter; use super::CLONE_DOUBLE_REF; use super::CLONE_ON_COPY; @@ -54,8 +53,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, ty = inner; n += 1; } - let refs: String = iter::repeat('&').take(n + 1).collect(); - let derefs: String = iter::repeat('*').take(n).collect(); + let refs = "&".repeat(n + 1); + let derefs = "*".repeat(n); let explicit = format!("<{}{}>::clone({})", refs, ty, snip); diag.span_suggestion( expr.span, diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs index ecec6da3aa0..f5b4b6bf8ea 100644 --- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -41,5 +41,5 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, "try", "copied".into(), Applicability::MachineApplicable, - ) + ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs index 12d560653ed..32d40d97bf4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs +++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs @@ -30,5 +30,5 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg "try", "filter_map".into(), Applicability::MachineApplicable, - ) + ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 28d0e8cd4ae..b4188d9ed30 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -37,6 +37,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp } fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String { + fn strip_angle_brackets(s: &str) -> Option<&str> { + s.strip_prefix('<')?.strip_suffix('>') + } + let call_site = expr.span.source_callsite(); if_chain! { if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site); @@ -44,23 +48,32 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) - if let Some((_, elements)) = snippet_split.split_last(); then { - // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`) - if let Some(type_specifier) = snippet_split.iter().find(|e| e.starts_with('<') && e.ends_with('>')) { - // remove the type specifier from the path elements - let without_ts = elements.iter().filter_map(|e| { - if e == type_specifier { None } else { Some((*e).to_string()) } - }).collect::<Vec<_>>(); - // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`) - format!("{}{}", without_ts.join("::"), type_specifier) - } else { - // type is not explicitly specified so wildcards are needed - // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>` - let ty_str = ty.to_string(); - let start = ty_str.find('<').unwrap_or(0); - let end = ty_str.find('>').unwrap_or_else(|| ty_str.len()); - let nb_wildcard = ty_str[start..end].split(',').count(); - let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1)); - format!("{}<{}>", elements.join("::"), wildcards) + if_chain! { + if let [type_specifier, _] = snippet_split.as_slice(); + if let Some(type_specifier) = strip_angle_brackets(type_specifier); + if let Some((type_specifier, ..)) = type_specifier.split_once(" as "); + then { + type_specifier.to_string() + } else { + // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`) + if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) { + // remove the type specifier from the path elements + let without_ts = elements.iter().filter_map(|e| { + if e == type_specifier { None } else { Some((*e).to_string()) } + }).collect::<Vec<_>>(); + // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`) + format!("{}{}", without_ts.join("::"), type_specifier) + } else { + // type is not explicitly specified so wildcards are needed + // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>` + let ty_str = ty.to_string(); + let start = ty_str.find('<').unwrap_or(0); + let end = ty_str.find('>').unwrap_or_else(|| ty_str.len()); + let nb_wildcard = ty_str[start..end].split(',').count(); + let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1)); + format!("{}<{}>", elements.join("::"), wildcards) + } + } } } else { ty.to_string() diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs index 52d7c15332e..68d906c3ea3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; use clippy_utils::source::snippet_with_applicability; diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs index 06b12998b1a..64c09214a76 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_trait_method; use rustc_hir as hir; diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs new file mode 100644 index 00000000000..919e2628c52 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs @@ -0,0 +1,99 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::sugg::Sugg; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type}; +use clippy_utils::{is_expr_path_def_path, paths}; +use if_chain::if_chain; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, LangItem}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty, TyS}; +use rustc_span::symbol::sym; +use std::borrow::Cow; + +use super::MANUAL_STR_REPEAT; + +enum RepeatKind { + String, + Char(char), +} + +fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> { + if let ty::Adt(_, subs) = ty.kind() { + subs.types().next() + } else { + None + } +} + +fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> { + if let ExprKind::Lit(lit) = &e.kind { + match lit.node { + LitKind::Str(..) => Some(RepeatKind::String), + LitKind::Char(c) => Some(RepeatKind::Char(c)), + _ => None, + } + } else { + let ty = cx.typeck_results().expr_ty(e); + if is_type_diagnostic_item(cx, ty, sym::string_type) + || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, TyS::is_str)) + || (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, TyS::is_str)) + { + Some(RepeatKind::String) + } else { + let ty = ty.peel_refs(); + (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::string_type)).then(|| RepeatKind::String) + } + } +} + +pub(super) fn check( + cx: &LateContext<'_>, + collect_expr: &Expr<'_>, + take_expr: &Expr<'_>, + take_self_arg: &Expr<'_>, + take_arg: &Expr<'_>, +) { + if_chain! { + if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind; + if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::string_type); + if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id); + if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id); + if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if cx.tcx.trait_of_item(collect_id) == Some(iter_trait_id); + if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id); + if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg); + let ctxt = collect_expr.span.ctxt(); + if ctxt == take_expr.span.ctxt(); + if ctxt == take_self_arg.span.ctxt(); + then { + let mut app = Applicability::MachineApplicable; + let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0; + + let val_str = match repeat_kind { + RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return, + RepeatKind::Char('\'') => r#""'""#.into(), + RepeatKind::Char('"') => r#""\"""#.into(), + RepeatKind::Char(_) => + match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) { + Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])), + s @ Cow::Borrowed(_) => s, + }, + RepeatKind::String => + Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app).maybe_par().to_string().into(), + }; + + span_lint_and_sugg( + cx, + MANUAL_STR_REPEAT, + collect_expr.span, + "manual implementation of `str::repeat` using iterators", + "try this", + format!("{}.repeat({})", val_str, count_snip), + app + ) + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index e0d29682146..c8ae972f18c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -32,6 +32,7 @@ mod iter_nth_zero; mod iter_skip_next; mod iterator_step_by_zero; mod manual_saturating_arithmetic; +mod manual_str_repeat; mod map_collect_result_unit; mod map_flatten; mod map_unwrap_or; @@ -48,6 +49,7 @@ mod single_char_push_string; mod skip_while_next; mod string_extend_chars; mod suspicious_map; +mod suspicious_splitn; mod uninit_assumed_init; mod unnecessary_filter_map; mod unnecessary_fold; @@ -61,7 +63,7 @@ mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; -use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, paths, return_ty}; +use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, meets_msrv, msrvs, paths, return_ty}; use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::def::Res; @@ -283,30 +285,6 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** This is the same as - /// [`wrong_self_convention`](#wrong_self_convention), but for public items. - /// - /// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention). - /// - /// **Known problems:** Actually *renaming* the function may break clients if - /// the function is part of the public interface. In that case, be mindful of - /// the stability guarantees you've given your users. - /// - /// **Example:** - /// ```rust - /// # struct X; - /// impl<'a> X { - /// pub fn as_str(self) -> &'a str { - /// "foo" - /// } - /// } - /// ``` - pub WRONG_PUB_SELF_CONVENTION, - restriction, - "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention" -} - -declare_clippy_lint! { /// **What it does:** Checks for usage of `ok().expect(..)`. /// /// **Why is this bad?** Because you usually call `expect()` on the `Result` @@ -1657,14 +1635,69 @@ declare_clippy_lint! { "replace `.iter().count()` with `.len()`" } +declare_clippy_lint! { + /// **What it does:** Checks for calls to [`splitn`] + /// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and + /// related functions with either zero or one splits. + /// + /// **Why is this bad?** These calls don't actually split the value and are + /// likely to be intended as a different number. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // Bad + /// let s = ""; + /// for x in s.splitn(1, ":") { + /// // use x + /// } + /// + /// // Good + /// let s = ""; + /// for x in s.splitn(2, ":") { + /// // use x + /// } + /// ``` + pub SUSPICIOUS_SPLITN, + correctness, + "checks for `.splitn(0, ..)` and `.splitn(1, ..)`" +} + +declare_clippy_lint! { + /// **What it does:** Checks for manual implementations of `str::repeat` + /// + /// **Why is this bad?** These are both harder to read, as well as less performant. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // Bad + /// let x: String = std::iter::repeat('x').take(10).collect(); + /// + /// // Good + /// let x: String = "x".repeat(10); + /// ``` + pub MANUAL_STR_REPEAT, + perf, + "manual implementation of `str::repeat`" +} + pub struct Methods { + avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>, } impl Methods { #[must_use] - pub fn new(msrv: Option<RustcVersion>) -> Self { - Self { msrv } + pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Self { + Self { + avoid_breaking_exported_api, + msrv, + } } } @@ -1673,7 +1706,6 @@ impl_lint_pass!(Methods => [ EXPECT_USED, SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION, - WRONG_PUB_SELF_CONVENTION, OK_EXPECT, MAP_UNWRAP_OR, RESULT_MAP_OR_INTO_OPTION, @@ -1726,7 +1758,9 @@ impl_lint_pass!(Methods => [ MAP_COLLECT_RESULT_UNIT, FROM_ITER_INSTEAD_OF_COLLECT, INSPECT_FOR_EACH, - IMPLICIT_CLONE + IMPLICIT_CLONE, + SUSPICIOUS_SPLITN, + MANUAL_STR_REPEAT ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -1838,11 +1872,13 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } } - if sig.decl.implicit_self.has_implicit_self() { + if sig.decl.implicit_self.has_implicit_self() + && !(self.avoid_breaking_exported_api + && cx.access_levels.is_exported(impl_item.hir_id())) + { wrong_self_convention::check( cx, &name, - item.vis.node.is_pub(), self_ty, first_arg_ty, first_arg.pat.span, @@ -1915,7 +1951,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods { wrong_self_convention::check( cx, &item.ident.name.as_str(), - false, self_ty, first_arg_ty, first_arg_span, @@ -1951,7 +1986,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio if let Some((name, [recv, args @ ..], span)) = method_call!(expr) { match (name, args) { ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => { - zst_offset::check(cx, expr, recv) + zst_offset::check(cx, expr, recv); }, ("and_then", [arg]) => { let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg); @@ -1969,6 +2004,11 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio Some(("map", [m_recv, m_arg], _)) => { map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv); }, + Some(("take", [take_self_arg, take_arg], _)) => { + if meets_msrv(msrv, &msrvs::STR_REPEAT) { + manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg); + } + }, _ => {}, }, ("count", []) => match method_call!(recv) { @@ -2012,7 +2052,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv), ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv), ("filter", [f_arg]) => { - filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false) + filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false); }, ("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true), _ => {}, @@ -2044,6 +2084,9 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio unnecessary_lazy_eval::check(cx, expr, recv, arg, "or"); } }, + ("splitn" | "splitn_mut" | "rsplitn" | "rsplitn_mut", [count_arg, _]) => { + suspicious_splitn::check(cx, name, expr, recv, count_arg); + }, ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => { implicit_clone::check(cx, name, expr, recv, span); @@ -2058,7 +2101,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", [m_recv, m_arg], span)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span) + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); }, _ => {}, }, @@ -2073,7 +2116,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) { if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call!(recv) { - search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span) + search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs new file mode 100644 index 00000000000..a271df60572 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -0,0 +1,56 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_note; +use if_chain::if_chain; +use rustc_ast::LitKind; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUSPICIOUS_SPLITN; + +pub(super) fn check( + cx: &LateContext<'_>, + method_name: &str, + expr: &Expr<'_>, + self_arg: &Expr<'_>, + count_arg: &Expr<'_>, +) { + if_chain! { + if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg); + if count <= 1; + if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); + if let Some(impl_id) = cx.tcx.impl_of_method(call_id); + let lang_items = cx.tcx.lang_items(); + if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id); + then { + // Ignore empty slice and string literals when used with a literal count. + if (matches!(self_arg.kind, ExprKind::Array([])) + || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) + ) && matches!(count_arg.kind, ExprKind::Lit(_)) + { + return; + } + + let (msg, note_msg) = if count == 0 { + (format!("`{}` called with `0` splits", method_name), + "the resulting iterator will always return `None`") + } else { + (format!("`{}` called with `1` split", method_name), + if lang_items.slice_impl() == Some(impl_id) { + "the resulting iterator will always return the entire slice followed by `None`" + } else { + "the resulting iterator will always return the entire string followed by `None`" + }) + }; + + span_lint_and_note( + cx, + SUSPICIOUS_SPLITN, + expr.span, + &msg, + None, + note_msg, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index 75517c48a21..4c4034437da 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -87,7 +87,7 @@ pub(super) fn check( ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true), ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false), ast::LitKind::Int(1, _) => { - check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false) + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false); }, _ => (), } diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs index 1773c26c251..a2e09e5ecec 100644 --- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs +++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs @@ -6,7 +6,6 @@ use rustc_middle::ty::TyS; use rustc_span::source_map::Span; use std::fmt; -use super::WRONG_PUB_SELF_CONVENTION; use super::WRONG_SELF_CONVENTION; #[rustfmt::skip] @@ -21,9 +20,9 @@ const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [ // Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types). // Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv - (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), + (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Ref]), - (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), + (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Value]), ]; @@ -85,18 +84,12 @@ impl fmt::Display for Convention { pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, item_name: &str, - is_pub: bool, self_ty: &'tcx TyS<'tcx>, first_arg_ty: &'tcx TyS<'tcx>, first_arg_span: Span, implements_trait: bool, is_trait_item: bool, ) { - let lint = if is_pub { - WRONG_PUB_SELF_CONVENTION - } else { - WRONG_SELF_CONVENTION - }; if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| { convs .iter() @@ -142,7 +135,7 @@ pub(super) fn check<'tcx>( span_lint_and_help( cx, - lint, + WRONG_SELF_CONVENTION, first_arg_span, &format!( "{} usually take {}", diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs index 45948f4d926..ff3473b744e 100644 --- a/src/tools/clippy/clippy_lints/src/minmax.rs +++ b/src/tools/clippy/clippy_lints/src/minmax.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant_simple, Constant}; +use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{match_def_path, match_trait_method, paths}; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index b5d2549242b..804c04fe1b8 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -17,7 +17,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{ExpnKind, Span}; use rustc_span::symbol::sym; -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::sugg::Sugg; use clippy_utils::{ expr_path_res, get_item_name, get_parent_expr, higher, in_constant, is_diag_trait_item, is_integer_const, @@ -355,8 +355,10 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints { if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; if let Some(sugg) = Sugg::hir_opt(cx, a); then { - span_lint_and_then(cx, + span_lint_hir_and_then( + cx, SHORT_CIRCUIT_STATEMENT, + expr.hir_id, stmt.span, "boolean short circuit operator in statement may be clearer using an explicit test", |diag| { diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs index dd38316fa25..050b6805b7c 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs @@ -310,7 +310,7 @@ impl EarlyLintPass for MiscEarlyLints { if in_external_macro(cx.sess(), expr.span) { return; } - double_neg::check(cx, expr) + double_neg::check(cx, expr); } } @@ -334,15 +334,15 @@ impl MiscEarlyLints { }; unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer"); if lit_snip.starts_with("0x") { - mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip) + mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip); } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { - /* nothing to do */ + // nothing to do } else if value != 0 && lit_snip.starts_with('0') { - zero_prefixed_literal::check(cx, lit, &lit_snip) + zero_prefixed_literal::check(cx, lit, &lit_snip); } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { let suffix = float_ty.name_str(); - unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float") + unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float"); } } } diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index dfab3e8a931..ec1572c26c2 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -93,9 +93,9 @@ impl MissingDoc { return; } - let has_doc = attrs.iter().any(|a| { - a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta()) - }); + let has_doc = attrs + .iter() + .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())); if !has_doc { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs index 64e9dc85466..1414fdc1b11 100644 --- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sext; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index cea6fce1195..6efe8ffcde0 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap(); let substs = cx.typeck_results().node_substs(e.hir_id); let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); - check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method") + check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method"); }, _ => (), } diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs index 7dfe12cd4eb..25645a0e7a2 100644 --- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs +++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> { _ if !self.found => self.expr_span = Some(expr.span), _ => return, } - walk_expr(self, expr) + walk_expr(self, expr); } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index 3e2b2782ed5..fe3c4455be5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -121,7 +121,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { match &p.ty.kind { TyKind::Path(None, path) => { if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind { - check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl) + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl); } }, TyKind::Rptr(lifetime, mut_ty) => { @@ -129,7 +129,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { if let TyKind::Path(None, path) = &mut_ty.ty.kind; if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind; then { - check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl) + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl); } } }, diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index dd458198637..3b3736fd3a1 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { } if is_else_clause(cx.tcx, e) { - snip = snip.blockify() + snip = snip.blockify(); } span_lint_and_sugg( @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison { |h: Sugg<'_>| !h, "equality checks against false can be replaced by a negation", )); - check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal) + check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal); }, BinOpKind::Ne => { let true_case = Some(( @@ -152,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison { "inequality checks against true can be replaced by a negation", )); let false_case = Some((|h| h, "inequality checks against false are unnecessary")); - check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal) + check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal); }, BinOpKind::Lt => check_comparison( cx, @@ -251,22 +251,22 @@ fn check_comparison<'a, 'tcx>( snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability) ), applicability, - ) + ); } } match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => left_true.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, right_side, applicability, m, h) + suggest_bool_comparison(cx, e, right_side, applicability, m, h); }), (Other, Bool(true)) => right_true.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, left_side, applicability, m, h) + suggest_bool_comparison(cx, e, left_side, applicability, m, h); }), (Bool(false), Other) => left_false.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, right_side, applicability, m, h) + suggest_bool_comparison(cx, e, right_side, applicability, m, h); }), (Other, Bool(false)) => right_false.map_or((), |(h, m)| { - suggest_bool_comparison(cx, e, left_side, applicability, m, h) + suggest_bool_comparison(cx, e, left_side, applicability, m, h); }), (Other, Other) => no_literal.map_or((), |(h, m)| { let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability); @@ -279,7 +279,7 @@ fn check_comparison<'a, 'tcx>( "try simplifying it as shown", h(left_side, right_side).to_string(), applicability, - ) + ); }), _ => (), } diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs index eef3c16730b..dd1dfa2bdfb 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs @@ -3,16 +3,18 @@ //! This lint is **warn** by default use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_automatically_derived; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context}; +use clippy_utils::{get_parent_expr, in_macro, path_to_local}; use if_chain::if_chain; +use rustc_ast::util::parser::PREC_POSTFIX; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; -use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, Item, Mutability, Pat, PatKind}; +use rustc_hir::{BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::def_id::LocalDefId; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for address of operations (`&`) that are going to @@ -32,20 +34,70 @@ declare_clippy_lint! { /// let x: &i32 = &5; /// ``` pub NEEDLESS_BORROW, - nursery, + style, "taking a reference that is going to be automatically dereferenced" } +declare_clippy_lint! { + /// **What it does:** Checks for `ref` bindings which create a reference to a reference. + /// + /// **Why is this bad?** The address-of operator at the use site is clearer about the need for a reference. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// // Bad + /// let x = Some(""); + /// if let Some(ref x) = x { + /// // use `x` here + /// } + /// + /// // Good + /// let x = Some(""); + /// if let Some(x) = x { + /// // use `&x` here + /// } + /// ``` + pub REF_BINDING_TO_REFERENCE, + pedantic, + "`ref` binding to a reference" +} + +impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE]); #[derive(Default)] pub struct NeedlessBorrow { - derived_item: Option<LocalDefId>, + /// The body the first local was found in. Used to emit lints when the traversal of the body has + /// been finished. Note we can't lint at the end of every body as they can be nested within each + /// other. + current_body: Option<BodyId>, + /// The list of locals currently being checked by the lint. + /// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted. + /// This is needed for or patterns where one of the branches can be linted, but another can not + /// be. + /// + /// e.g. `m!(x) | Foo::Bar(ref x)` + ref_locals: FxIndexMap<HirId, Option<RefPat>>, } -impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW]); +struct RefPat { + /// Whether every usage of the binding is dereferenced. + always_deref: bool, + /// The spans of all the ref bindings for this local. + spans: Vec<Span>, + /// The applicability of this suggestion. + app: Applicability, + /// All the replacements which need to be made. + replacements: Vec<(Span, String)>, +} impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if e.span.from_expansion() || self.derived_item.is_some() { + if let Some(local) = path_to_local(e) { + self.check_local_usage(cx, e, local); + } + + if e.span.from_expansion() { return; } if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind { @@ -85,50 +137,131 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow { } } } + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { - if pat.span.from_expansion() || self.derived_item.is_some() { - return; + if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind { + if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) { + // This binding id has been seen before. Add this pattern to the list of changes. + if let Some(prev_pat) = opt_prev_pat { + if in_macro(pat.span) { + // Doesn't match the context of the previous pattern. Can't lint here. + *opt_prev_pat = None; + } else { + prev_pat.spans.push(pat.span); + prev_pat.replacements.push(( + pat.span, + snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app) + .0 + .into(), + )); + } + } + return; + } + + if_chain! { + if !in_macro(pat.span); + if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind(); + // only lint immutable refs, because borrowed `&mut T` cannot be moved out + if let ty::Ref(_, _, Mutability::Not) = *tam.kind(); + then { + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0; + self.current_body = self.current_body.or(cx.enclosing_body); + self.ref_locals.insert( + id, + Some(RefPat { + always_deref: true, + spans: vec![pat.span], + app, + replacements: vec![(pat.span, snip.into())], + }), + ); + } + } } - if_chain! { - if let PatKind::Binding(BindingAnnotation::Ref, .., name, _) = pat.kind; - if let ty::Ref(_, tam, mutbl) = *cx.typeck_results().pat_ty(pat).kind(); - if mutbl == Mutability::Not; - if let ty::Ref(_, _, mutbl) = *tam.kind(); - // only lint immutable refs, because borrowed `&mut T` cannot be moved out - if mutbl == Mutability::Not; - then { + } + + fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + if Some(body.id()) == self.current_body { + for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) { + let replacements = pat.replacements; + let app = pat.app; span_lint_and_then( cx, - NEEDLESS_BORROW, - pat.span, + if pat.always_deref { + NEEDLESS_BORROW + } else { + REF_BINDING_TO_REFERENCE + }, + pat.spans, "this pattern creates a reference to a reference", |diag| { - if let Some(snippet) = snippet_opt(cx, name.span) { - diag.span_suggestion( - pat.span, - "change this to", - snippet, - Applicability::MachineApplicable, - ); - } - } - ) + diag.multipart_suggestion("try this", replacements, app); + }, + ); } + self.current_body = None; } } - - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let attrs = cx.tcx.hir().attrs(item.hir_id()); - if is_automatically_derived(attrs) { - debug_assert!(self.derived_item.is_none()); - self.derived_item = Some(item.def_id); - } - } - - fn check_item_post(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let Some(id) = self.derived_item { - if item.def_id == id { - self.derived_item = None; +} +impl NeedlessBorrow { + fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, local: HirId) { + if let Some(outer_pat) = self.ref_locals.get_mut(&local) { + if let Some(pat) = outer_pat { + // Check for auto-deref + if !matches!( + cx.typeck_results().expr_adjustments(e), + [ + Adjustment { + kind: Adjust::Deref(_), + .. + }, + Adjustment { + kind: Adjust::Deref(_), + .. + }, + .. + ] + ) { + match get_parent_expr(cx, e) { + // Field accesses are the same no matter the number of references. + Some(Expr { + kind: ExprKind::Field(..), + .. + }) => (), + Some(&Expr { + span, + kind: ExprKind::Unary(UnOp::Deref, _), + .. + }) if !in_macro(span) => { + // Remove explicit deref. + let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0; + pat.replacements.push((span, snip.into())); + }, + Some(parent) if !in_macro(parent.span) => { + // Double reference might be needed at this point. + if parent.precedence().order() == PREC_POSTFIX { + // Parentheses would be needed here, don't lint. + *outer_pat = None; + } else { + pat.always_deref = false; + let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0; + pat.replacements.push((e.span, format!("&{}", snip))); + } + }, + _ if !in_macro(e.span) => { + // Double reference might be needed at this point. + pat.always_deref = false; + let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app); + pat.replacements.push((e.span, format!("&{}", snip))); + }, + // Edge case for macros. The span of the identifier will usually match the context of the + // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc + // macros + _ => *outer_pat = None, + } + } } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs index 079b6642d58..a723a472a25 100644 --- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -142,10 +142,10 @@ impl<'tcx> Visitor<'tcx> for RetCollector { match expr.kind { ExprKind::Ret(..) => { if self.loop_depth > 0 && !self.ret_in_loop { - self.ret_in_loop = true + self.ret_in_loop = true; } - self.spans.push(expr.span) + self.spans.push(expr.span); }, ExprKind::Loop(..) => { diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 0704173a011..c824f6f54b5 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { types produces code that is hard to read and refactor, please \ consider using the `partial_cmp` method instead, to make it \ clear that the two values could be incomparable" - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index 34fd012572f..d5e1ea6d242 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -1,3 +1,4 @@ +use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; @@ -5,8 +6,6 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use crate::consts::{self, Constant}; - declare_clippy_lint! { /// **What it does:** Checks for multiplication by -1 as a form of negation. /// diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index cfcaf509471..b2206a82208 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::has_drop; use rustc_errors::Applicability; @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Semi(expr) = stmt.kind { if has_no_effect(cx, expr) { - span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect"); + span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect"); } else if let Some(reduced) = reduce_expression(cx, expr) { let mut snippet = String::new(); for e in reduced { @@ -106,14 +106,15 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { return; } } - span_lint_and_sugg( + span_lint_hir_and_then( cx, UNNECESSARY_OPERATION, + expr.hir_id, stmt.span, "statement can be reduced", - "replace it with", - snippet, - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion(stmt.span, "replace it with", snippet, Applicability::MachineApplicable); + }, ); } } diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 4c8bceaf2cb..5292af5f076 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -126,6 +126,7 @@ const ALLOWED_TO_BE_SIMILAR: &[&[&str]] = &[ &["args", "arms"], &["qpath", "path"], &["lit", "lint"], + &["wparam", "lparam"], ]; struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>); diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs index 9efe45336bf..fded48038e3 100644 --- a/src/tools/clippy/clippy_lints/src/open_options.rs +++ b/src/tools/clippy/clippy_lints/src/open_options.rs @@ -123,7 +123,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], "the method `create` is called more than once", ); } else { - create = true + create = true; } create_arg = create_arg || (arg == Argument::True); }, @@ -136,7 +136,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], "the method `append` is called more than once", ); } else { - append = true + append = true; } append_arg = append_arg || (arg == Argument::True); }, @@ -149,7 +149,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], "the method `truncate` is called more than once", ); } else { - truncate = true + truncate = true; } truncate_arg = truncate_arg || (arg == Argument::True); }, @@ -162,7 +162,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], "the method `read` is called more than once", ); } else { - read = true + read = true; } read_arg = read_arg || (arg == Argument::True); }, @@ -175,7 +175,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], "the method `write` is called more than once", ); } else { - write = true + write = true; } write_arg = write_arg || (arg == Argument::True); }, diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 6b64846c24d..f6a70478559 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -102,10 +102,16 @@ declare_clippy_lint! { pub struct PassByRefOrValue { ref_min_size: u64, value_max_size: u64, + avoid_breaking_exported_api: bool, } impl<'tcx> PassByRefOrValue { - pub fn new(ref_min_size: Option<u64>, value_max_size: u64, target: &Target) -> Self { + pub fn new( + ref_min_size: Option<u64>, + value_max_size: u64, + avoid_breaking_exported_api: bool, + target: &Target, + ) -> Self { let ref_min_size = ref_min_size.unwrap_or_else(|| { let bit_width = u64::from(target.pointer_width); // Cap the calculated bit width at 32-bits to reduce @@ -120,10 +126,14 @@ impl<'tcx> PassByRefOrValue { Self { ref_min_size, value_max_size, + avoid_breaking_exported_api, } } fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) { + if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) { + return; + } let fn_def_id = cx.tcx.hir().local_def_id(hir_id); let fn_sig = cx.tcx.fn_sig(fn_def_id); @@ -184,7 +194,6 @@ impl<'tcx> PassByRefOrValue { } if_chain! { - if !cx.access_levels.is_exported(hir_id); if is_copy(cx, ty); if !is_self_ty(input); if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index b0674f90678..12c44436874 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -211,7 +211,7 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { ]; if_chain! { - if let ExprKind::Call(ref fun, ref args) = expr.kind; + if let ExprKind::Call(fun, args) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>(); diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 30bee213900..d66bac52243 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -88,7 +88,7 @@ impl QuestionMark { "replace it with", replacement_str, applicability, - ) + ); } } } @@ -129,7 +129,7 @@ impl QuestionMark { "replace it with", replacement, applicability, - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index 7169f96eaf1..ae5f0627fd6 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; 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 92921bedf4d..8f56a21ac5b 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -57,7 +57,7 @@ impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor { self.found_return = true; } - ast_visit::walk_expr(self, ex) + ast_visit::walk_expr(self, ex); } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index e091095de13..05f9e01acb4 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { Applicability::MachineApplicable, ); }, - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index 4b5306de58e..75151167454 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant, Constant}; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/repeat_once.rs b/src/tools/clippy/clippy_lints/src/repeat_once.rs index 560a5e7c920..b479c40bca6 100644 --- a/src/tools/clippy/clippy_lints/src/repeat_once.rs +++ b/src/tools/clippy/clippy_lints/src/repeat_once.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant_context, Constant}; +use clippy_utils::consts::{constant_context, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::in_macro; use clippy_utils::source::snippet; diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index b565c77aaec..251d527c265 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { } else { RetReplacement::Empty }; - check_final_expr(cx, &body.value, Some(body.value.span), replacement) + check_final_expr(cx, &body.value, Some(body.value.span), replacement); }, FnKind::ItemFn(..) | FnKind::Method(..) => { if let ExprKind::Block(block, _) = body.value.kind { @@ -241,7 +241,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa if let Some(snippet) = snippet_opt(cx, inner_span) { diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable); } - }) + }); }, None => match replacement { RetReplacement::Empty => { diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs index 553987a426b..16e4d73851f 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -8,11 +8,11 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// **What it does:** Looks for blocks of expressions and fires if the last expression returns `()` - /// but is not followed by a semicolon. + /// **What it does:** Looks for blocks of expressions and fires if the last expression returns + /// `()` but is not followed by a semicolon. /// - /// **Why is this bad?** The semicolon might be optional but when - /// extending the block with new code, it doesn't require a change in previous last line. + /// **Why is this bad?** The semicolon might be optional but when extending the block with new + /// code, it doesn't require a change in previous last line. /// /// **Known problems:** None. /// @@ -30,7 +30,7 @@ declare_clippy_lint! { /// } /// ``` pub SEMICOLON_IF_NOTHING_RETURNED, - restriction, + pedantic, "add a semicolon if nothing is returned" } diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index d6101bd5e36..ac3f7ebd14b 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -120,7 +120,7 @@ fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Bo let mut bindings = Vec::with_capacity(decl.inputs.len()); for arg in iter_input_pats(decl, body) { if let PatKind::Binding(.., ident, _) = arg.pat.kind { - bindings.push((ident.name, ident.span)) + bindings.push((ident.name, ident.span)); } } check_expr(cx, &body.value, &mut bindings); @@ -156,7 +156,7 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: & .. } = *local; if let Some(t) = *ty { - check_ty(cx, t, bindings) + check_ty(cx, t, bindings); } if let Some(o) = *init { check_expr(cx, o, bindings); @@ -324,14 +324,14 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut } match expr.kind { ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => { - check_expr(cx, e, bindings) + check_expr(cx, e, bindings); }, ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings), // ExprKind::Call // ExprKind::MethodCall ExprKind::Array(v) | ExprKind::Tup(v) => { for e in v { - check_expr(cx, e, bindings) + check_expr(cx, e, bindings); } }, ExprKind::If(cond, then, ref otherwise) => { @@ -374,7 +374,7 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<( TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings), TyKind::Tup(tup) => { for t in tup { - check_ty(cx, t, bindings) + check_ty(cx, t, bindings); } }, TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings), diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index a45bb102389..1eaad438237 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -70,7 +70,7 @@ fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) { for item in items { track_uses( cx, - &item, + item, &mut imports_reused_with_self, &mut single_use_usages, &mut macros, @@ -117,7 +117,7 @@ fn track_uses( match &item.kind { ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => { - check_mod(cx, &items); + check_mod(cx, items); }, ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { macros.push(item.ident.name); diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index a9ae2b77119..e5c58d70b60 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -158,7 +158,7 @@ impl SlowVectorInit { ) { match initialization { InitializationType::Extend(e) | InitializationType::Resize(e) => { - Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization") + Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization"); }, }; } @@ -290,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { fn visit_block(&mut self, block: &'tcx Block<'_>) { if self.initialization_found { if let Some(s) = block.stmts.get(0) { - self.visit_stmt(s) + self.visit_stmt(s); } self.initialization_found = false; diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 4272935bc31..bb707f78fcc 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -59,7 +59,7 @@ declare_clippy_lint! { /// } /// ``` pub SUSPICIOUS_OPERATION_GROUPINGS, - style, + nursery, "groupings of binary operations that look suspiciously like typos" } @@ -266,7 +266,7 @@ fn emit_suggestion(cx: &EarlyContext<'_>, span: Span, sugg: String, applicabilit "did you mean", sugg, applicability, - ) + ); } fn ident_swap_sugg( @@ -475,7 +475,7 @@ impl Add for IdentLocation { impl AddAssign for IdentLocation { fn add_assign(&mut self, other: Self) { - *self = *self + other + *self = *self + other; } } @@ -506,7 +506,7 @@ impl Add for IdentDifference { impl AddAssign for IdentDifference { fn add_assign(&mut self, other: Self) { - *self = *self + other + *self = *self + other; } } diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index b0589b0512e..74a94db1800 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -3,6 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::{in_macro, SpanlessHash}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, TyKind, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; @@ -100,7 +101,7 @@ impl TraitBounds { hasher.hash_ty(ty); hasher.finish() }; - let mut map = FxHashMap::default(); + let mut map: UnhashMap<u64, Vec<&GenericBound<'_>>> = UnhashMap::default(); let mut applicability = Applicability::MaybeIncorrect; for bound in gen.where_clause.predicates { if_chain! { diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs index 888ecab1046..b57d158293d 100644 --- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant_context, Constant}; +use clippy_utils::consts::{constant_context, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{is_expr_path_def_path, paths}; use if_chain::if_chain; diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index d9b47a699dc..70b9e8adef8 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -306,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { match item.kind { TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { - self.check_ty(cx, ty, CheckTyContext::default()) + self.check_ty(cx, ty, CheckTyContext::default()); }, TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()), TraitItemKind::Type(..) => (), @@ -433,7 +433,7 @@ impl Types { }, TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => { context.is_nested_call = true; - self.check_ty(cx, ty, context) + self.check_ty(cx, ty, context); }, TyKind::Tup(tys) => { context.is_nested_call = true; diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs index d81e31f5a21..45291a120ed 100644 --- a/src/tools/clippy/clippy_lints/src/unicode.rs +++ b/src/tools/clippy/clippy_lints/src/unicode.rs @@ -71,7 +71,7 @@ impl LateLintPass<'_> for Unicode { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { if let ExprKind::Lit(ref lit) = expr.kind { if let LitKind::Str(_, _) = lit.node { - check_str(cx, lit.span, expr.hir_id) + check_str(cx, lit.span, expr.hir_id); } } } @@ -82,7 +82,7 @@ fn escape<T: Iterator<Item = char>>(s: T) -> String { for c in s { if c as u32 > 0x7F { for d in c.escape_unicode() { - result.push(d) + result.push(d); } } else { result.push(c); diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index f2f1410aed7..a85ffa6aa95 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -8,7 +8,7 @@ use rustc_hir::LangItem::{OptionSome, ResultOk}; use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -52,7 +52,19 @@ declare_clippy_lint! { "functions that only return `Ok` or `Some`" } -declare_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]); +pub struct UnnecessaryWraps { + avoid_breaking_exported_api: bool, +} + +impl_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]); + +impl UnnecessaryWraps { + pub fn new(avoid_breaking_exported_api: bool) -> Self { + Self { + avoid_breaking_exported_api, + } + } +} impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { fn check_fn( @@ -66,13 +78,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { ) { // Abort if public function/method or closure. match fn_kind { - FnKind::ItemFn(.., visibility) | FnKind::Method(.., Some(visibility)) => { - if visibility.node.is_pub() { + FnKind::ItemFn(..) | FnKind::Method(..) => { + if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) { return; } }, FnKind::Closure => return, - FnKind::Method(..) => (), } // Abort if the method is implementing a trait or of it a trait method. diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index c27a6d4e347..ee082d30d93 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) { let mut call = call; - while let hir::ExprKind::MethodCall(ref path, _, ref args, _) = call.kind { + while let hir::ExprKind::MethodCall(path, _, args, _) = call.kind { if matches!(&*path.ident.as_str(), "or" | "or_else" | "ok") { call = &args[0]; } else { diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 4ac2ec55b98..0b58c6c0917 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use itertools::Itertools; -use rustc_ast::ast::{Item, ItemKind, VisibilityKind}; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_hir::{Item, ItemKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Ident; @@ -38,12 +38,14 @@ declare_clippy_lint! { #[derive(Default)] pub struct UpperCaseAcronyms { + avoid_breaking_exported_api: bool, upper_case_acronyms_aggressive: bool, } impl UpperCaseAcronyms { - pub fn new(aggressive: bool) -> Self { + pub fn new(avoid_breaking_exported_api: bool, aggressive: bool) -> Self { Self { + avoid_breaking_exported_api, upper_case_acronyms_aggressive: aggressive, } } @@ -72,7 +74,7 @@ fn correct_ident(ident: &str) -> String { ident } -fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) { +fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) { let span = ident.span; let ident = &ident.as_str(); let corrected = correct_ident(ident); @@ -92,27 +94,31 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) { "consider making the acronym lowercase, except the initial letter", corrected, Applicability::MaybeIncorrect, - ) + ); } } -impl EarlyLintPass for UpperCaseAcronyms { - fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) { +impl LateLintPass<'_> for UpperCaseAcronyms { + fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros - if !in_external_macro(cx.sess(), it.span) && !matches!(it.vis.kind, VisibilityKind::Public) { - if matches!( - it.kind, - ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) - ) { + if in_external_macro(cx.sess(), it.span) + || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.hir_id())) + { + return; + } + match it.kind { + ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => { check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive); - } else if let ItemKind::Enum(ref enumdef, _) = it.kind { + }, + ItemKind::Enum(ref enumdef, _) => { // check enum variants seperately because again we only want to lint on private enums and // the fn check_variant does not know about the vis of the enum of its variants enumdef .variants .iter() .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive)); - } + }, + _ => {}, } } } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 2ad6fa77f48..254b104bdef 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -356,7 +356,7 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) { self.types_to_skip.push(hir_ty.hir_id); - walk_ty(self, hir_ty) + walk_ty(self, hir_ty); } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { @@ -385,7 +385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> { } } - walk_ty(self, hir_ty) + walk_ty(self, hir_ty); } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index e70f8a09ebe..39ef170ae36 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -292,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { LitKind::Str(ref text, _) => { let str_pat = self.next("s"); println!(" if let LitKind::Str(ref {}, _) = {}.node;", str_pat, lit_pat); - println!(" if {}.as_str() == {:?}", str_pat, &*text.as_str()) + println!(" if {}.as_str() == {:?}", str_pat, &*text.as_str()); }, } }, diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index fd2dddb3b96..0e33ae740d9 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -122,7 +122,9 @@ macro_rules! define_Conf { // N.B., this macro is parsed by util/lintlib.py define_Conf! { - /// Lint: CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports + /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. Suppress lints whenever the suggested change would cause breakage for other crates. + (avoid_breaking_exported_api: bool = true), + /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports (msrv: Option<String> = None), /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses (blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), @@ -208,15 +210,13 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> { .map_or_else(|| PathBuf::from("."), PathBuf::from); loop { for config_file_name in &CONFIG_FILE_NAMES { - let config_file = current.join(config_file_name); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `clippy.toml`. - Ok(ref md) if !md.is_dir() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't - // find the project file yet, and continue searching. - Err(e) if e.kind() != io::ErrorKind::NotFound => return Err(e), - _ => {}, + if let Ok(config_file) = current.join(config_file_name).canonicalize() { + match fs::metadata(&config_file) { + Err(e) if e.kind() == io::ErrorKind::NotFound => {}, + Err(e) => return Err(e), + Ok(md) if md.is_dir() => {}, + Ok(_) => return Ok(Some(config_file)), + } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index ee7be24eae8..b1523e032af 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant_simple, Constant}; +use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::ty::match_type; @@ -1100,7 +1100,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle { IF_CHAIN_STYLE, if_chain_local_span(cx, local, if_chain_span), "`let` expression should be inside `then { .. }`", - ) + ); } } @@ -1141,7 +1141,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle { if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span) && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span) { - span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`") + span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`"); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index e9fa043b20f..46af03663b8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -379,7 +379,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector { /// } /// ``` fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) { - if let ItemKind::Static(ref ty, Mutability::Not, _) = item.kind { + if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { // Normal lint if_chain! { // item validation @@ -489,7 +489,7 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { .hir() .attrs(item.hir_id()) .iter() - .filter_map(|ref x| x.doc_str().map(|sym| sym.as_str().to_string())) + .filter_map(|x| x.doc_str().map(|sym| sym.as_str().to_string())) .reduce(|mut acc, sym| { acc.push_str(&sym); acc.push('\n'); @@ -596,7 +596,7 @@ fn extract_emission_info<'hir>( let mut multi_part = false; for arg in args { - let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(&arg)); + let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)); if match_type(cx, arg_ty, &paths::LINT) { // If we found the lint arg, extract the lint name @@ -671,7 +671,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> { if let ExprKind::Path(qpath) = &expr.kind; if let QPath::Resolved(_, path) = qpath; - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&expr)); + let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); if match_type(self.cx, expr_ty, &paths::LINT); then { if let hir::def::Res::Def(DefKind::Static, _) = path.res { @@ -730,7 +730,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&expr)); + let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); if_chain! { if match_type(self.cx, expr_ty, &paths::APPLICABILITY); @@ -818,7 +818,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { .any(|func_path| match_function_call(self.cx, fn_expr, func_path).is_some()); if found_function { // These functions are all multi part suggestions - self.add_single_span_suggestion() + self.add_single_span_suggestion(); } }, ExprKind::MethodCall(path, _path_span, arg, _arg_span) => { diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index febd4b6ff7b..1d5b7c98d31 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -1,5 +1,5 @@ -use crate::consts::{constant, Constant}; use crate::rustc_target::abi::LayoutOf; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs index ec209b30951..3ab68df2b6d 100644 --- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs +++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for VerboseFileReads { "use of `File::read_to_string`", None, "consider using `fs::read_to_string` instead", - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index d0e79efa70d..5229a705865 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -300,7 +300,7 @@ impl EarlyLintPass for Write { Applicability::MachineApplicable, ); }, - ) + ); } } } else if mac.path == sym!(writeln) { diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs index 350b1cf25ff..a1ea743ba80 100644 --- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs +++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs @@ -1,4 +1,4 @@ -use crate::consts::{constant_simple, Constant}; +use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index c0584e1e226..0318c483959 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -115,7 +115,7 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' for attr in get_attr(sess, attrs, name) { if let Some(ref value) = attr.value_str() { if let Ok(value) = FromStr::from_str(&value.as_str()) { - f(value) + f(value); } else { sess.span_err(attr.span, "not a number"); } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 2a305d8bcbe..0d7fdeeb920 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -229,25 +229,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> { match e.kind { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), - ExprKind::Block(ref block, _) => self.block(block), + ExprKind::Block(block, _) => self.block(block), ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))), - ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec), - ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), - ExprKind::Repeat(ref value, _) => { + ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec), + ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple), + ExprKind::Repeat(value, _) => { let n = match self.typeck_results.expr_ty(e).kind() { ty::Array(_, n) => n.try_eval_usize(self.lcx.tcx, self.lcx.param_env)?, _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) }, - ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op { + ExprKind::Unary(op, operand) => self.expr(operand).and_then(|o| match op { UnOp::Not => self.constant_not(&o, self.typeck_results.expr_ty(e)), UnOp::Neg => self.constant_negate(&o, self.typeck_results.expr_ty(e)), UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }), }), - ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), - ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right), - ExprKind::Call(ref callee, ref args) => { + ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), + ExprKind::Binary(op, left, right) => self.binop(op, left, right), + ExprKind::Call(callee, args) => { // We only handle a few const functions for now. if_chain! { if args.is_empty(); @@ -273,8 +273,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } }, - ExprKind::Index(ref arr, ref index) => self.index(arr, index), - ExprKind::AddrOf(_, _, ref inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))), + ExprKind::Index(arr, index) => self.index(arr, index), + ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))), // TODO: add other expressions. _ => None, } @@ -349,7 +349,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { ) .ok() .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?; - let result = miri_to_const(&result); + let result = miri_to_const(result); if result.is_some() { self.needed_resolution = true; } diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index a4efae54894..7c94474cb35 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -167,7 +167,7 @@ pub fn span_lint_hir_and_then( cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, - sp: Span, + sp: impl Into<MultiSpan>, msg: &str, f: impl FnOnce(&mut DiagnosticBuilder<'_>), ) { @@ -223,7 +223,7 @@ pub fn multispan_sugg<I>(diag: &mut DiagnosticBuilder<'_>, help_msg: &str, sugg: where I: IntoIterator<Item = (Span, String)>, { - multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg) + multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg); } /// Create a suggestion made from several `span → replacement`. diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 0c0e4d3b4ce..8be36756b33 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -58,7 +58,7 @@ pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> { } match expr.kind { - hir::ExprKind::Call(ref path, ref args) + hir::ExprKind::Call(path, args) if matches!( path.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, _)) @@ -70,7 +70,7 @@ pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> { limits: ast::RangeLimits::Closed, }) }, - hir::ExprKind::Struct(ref path, ref fields, None) => match path { + hir::ExprKind::Struct(path, fields, None) => match path { hir::QPath::LangItem(hir::LangItem::RangeFull, _) => Some(Range { start: None, end: None, @@ -112,7 +112,7 @@ pub fn is_from_for_desugar(local: &hir::Local<'_>) -> bool { // } // ``` if_chain! { - if let Some(ref expr) = local.init; + if let Some(expr) = local.init; if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.kind; then { return true; @@ -140,14 +140,14 @@ pub fn for_loop<'tcx>( expr: &'tcx hir::Expr<'tcx>, ) -> Option<(&hir::Pat<'_>, &'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>, Span)> { if_chain! { - if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.kind; - if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.kind; + if let hir::ExprKind::Match(iterexpr, arms, hir::MatchSource::ForLoopDesugar) = expr.kind; + if let hir::ExprKind::Call(_, iterargs) = iterexpr.kind; if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(); - if let hir::ExprKind::Loop(ref block, ..) = arms[0].body.kind; + if let hir::ExprKind::Loop(block, ..) = arms[0].body.kind; if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; - if let hir::StmtKind::Local(ref local) = let_stmt.kind; - if let hir::StmtKind::Expr(ref expr) = body.kind; + if let hir::StmtKind::Local(local) = let_stmt.kind; + if let hir::StmtKind::Expr(expr) = body.kind; then { return Some((&*local.pat, &iterargs[0], expr, arms[0].span)); } @@ -182,7 +182,7 @@ pub enum VecArgs<'a> { /// from `vec!`. pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<VecArgs<'e>> { if_chain! { - if let hir::ExprKind::Call(ref fun, ref args) = expr.kind; + if let hir::ExprKind::Call(fun, args) = expr.kind; if let hir::ExprKind::Path(ref qpath) = fun.kind; if is_expn_of(fun.span, "vec").is_some(); if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); @@ -194,8 +194,8 @@ pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<Ve else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { // `vec![a, b, c]` case if_chain! { - if let hir::ExprKind::Box(ref boxed) = args[0].kind; - if let hir::ExprKind::Array(ref args) = boxed.kind; + if let hir::ExprKind::Box(boxed) = args[0].kind; + if let hir::ExprKind::Array(args) = boxed.kind; then { return Some(VecArgs::Vec(&*args)); } @@ -227,7 +227,7 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx /// compared fn ast_matchblock(matchblock_expr: &'tcx Expr<'tcx>) -> Option<Vec<&Expr<'_>>> { if_chain! { - if let ExprKind::Match(ref headerexpr, _, _) = &matchblock_expr.kind; + if let ExprKind::Match(headerexpr, _, _) = &matchblock_expr.kind; if let ExprKind::Tup([lhs, rhs]) = &headerexpr.kind; if let ExprKind::AddrOf(BorrowKind::Ref, _, lhs) = lhs.kind; if let ExprKind::AddrOf(BorrowKind::Ref, _, rhs) = rhs.kind; @@ -238,12 +238,12 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx None } - if let ExprKind::Block(ref block, _) = e.kind { + if let ExprKind::Block(block, _) = e.kind { if block.stmts.len() == 1 { - if let StmtKind::Semi(ref matchexpr) = block.stmts.get(0)?.kind { + if let StmtKind::Semi(matchexpr) = block.stmts.get(0)?.kind { // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`) if_chain! { - if let ExprKind::If(ref clause, _, _) = matchexpr.kind; + if let ExprKind::If(clause, _, _) = matchexpr.kind; if let ExprKind::Unary(UnOp::Not, condition) = clause.kind; then { return Some(vec![condition]); @@ -252,8 +252,8 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`) if_chain! { - if let ExprKind::Block(ref matchblock,_) = matchexpr.kind; - if let Some(ref matchblock_expr) = matchblock.expr; + if let ExprKind::Block(matchblock,_) = matchexpr.kind; + if let Some(matchblock_expr) = matchblock.expr; then { return ast_matchblock(matchblock_expr); } @@ -261,7 +261,7 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx } } else if let Some(matchblock_expr) = block.expr { // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`) - return ast_matchblock(&matchblock_expr); + return ast_matchblock(matchblock_expr); } } None diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 3b01158acd9..a21ad42c061 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -2,20 +2,19 @@ use crate::consts::{constant_context, constant_simple}; use crate::differing_macro_contexts; use crate::source::snippet_opt; use rustc_ast::ast::InlineAsmTemplatePiece; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::fx::FxHasher; use rustc_hir::def::Res; use rustc_hir::HirIdMap; use rustc_hir::{ - BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprField, ExprKind, FnRetTy, GenericArg, - GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, - PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, + BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId, + InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt, + StmtKind, Ty, TyKind, TypeBinding, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; -use rustc_middle::ich::StableHashingContextProvider; use rustc_middle::ty::TypeckResults; use rustc_span::Symbol; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; /// Type used to check whether two ast are the same. This is different from the /// operator @@ -95,12 +94,12 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> { impl HirEqInterExpr<'_, '_, '_> { pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { - (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { + (&StmtKind::Local(l), &StmtKind::Local(r)) => { // This additional check ensures that the type of the locals are equivalent even if the init // expression or type have some inferred parts. if let Some(typeck) = self.inner.maybe_typeck_results { - let l_ty = typeck.pat_ty(&l.pat); - let r_ty = typeck.pat_ty(&r.pat); + let l_ty = typeck.pat_ty(l.pat); + let r_ty = typeck.pat_ty(r.pat); if !rustc_middle::ty::TyS::same_type(l_ty, r_ty) { return false; } @@ -110,11 +109,9 @@ impl HirEqInterExpr<'_, '_, '_> { // these only get added if the init and type is equal. both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) - && self.eq_pat(&l.pat, &r.pat) - }, - (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => { - self.eq_expr(l, r) + && self.eq_pat(l.pat, r.pat) }, + (&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r), _ => false, } } @@ -165,12 +162,18 @@ impl HirEqInterExpr<'_, '_, '_> { left.eq(right) }, _ => { - over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r)) + over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r)) && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r)) }, } } + pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool { + let cx = self.inner.cx; + let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value); + eval_const(left) == eval_const(right) + } + #[allow(clippy::similar_names)] pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { if !self.inner.allow_side_effects && differing_macro_contexts(left.span, right.span) { @@ -192,20 +195,20 @@ impl HirEqInterExpr<'_, '_, '_> { &reduce_exprkind(self.inner.cx, &left.kind), &reduce_exprkind(self.inner.cx, &right.kind), ) { - (&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => { + (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => { lb == rb && l_mut == r_mut && self.eq_expr(le, re) }, (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) }, - (&ExprKind::Assign(ref ll, ref lr, _), &ExprKind::Assign(ref rl, ref rr, _)) => { + (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => { self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => { + (&ExprKind::AssignOp(ref lo, ll, lr), &ExprKind::AssignOp(ref ro, rl, rr)) => { self.inner.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, - (&ExprKind::Block(ref l, _), &ExprKind::Block(ref r, _)) => self.eq_block(l, r), - (&ExprKind::Binary(l_op, ref ll, ref lr), &ExprKind::Binary(r_op, ref rl, ref rr)) => { + (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r), + (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) @@ -215,58 +218,50 @@ impl HirEqInterExpr<'_, '_, '_> { both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) && both(le, re, |l, r| self.eq_expr(l, r)) }, - (&ExprKind::Box(ref l), &ExprKind::Box(ref r)) => self.eq_expr(l, r), + (&ExprKind::Box(l), &ExprKind::Box(r)) => self.eq_expr(l, r), (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => { self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) - | (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => { + (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) | (&ExprKind::Type(lx, lt), &ExprKind::Type(rx, rt)) => { self.eq_expr(lx, rx) && self.eq_ty(lt, rt) }, - (&ExprKind::Field(ref l_f_exp, ref l_f_ident), &ExprKind::Field(ref r_f_exp, ref r_f_ident)) => { + (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => { l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, - (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => { - self.eq_expr(la, ra) && self.eq_expr(li, ri) - }, - (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => { + (&ExprKind::Index(la, li), &ExprKind::Index(ra, ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri), + (&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => { self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node, - (&ExprKind::Loop(ref lb, ref ll, ref lls, _), &ExprKind::Loop(ref rb, ref rl, ref rls, _)) => { + (&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name) }, - (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => { + (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => { ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| { - self.eq_pat(&l.pat, &r.pat) + self.eq_pat(l.pat, r.pat) && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r)) - && self.eq_expr(&l.body, &r.body) + && self.eq_expr(l.body, r.body) }) }, (&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => { self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => { - let mut celcx = constant_context(self.inner.cx, self.inner.cx.tcx.typeck_body(ll_id.body)); - let ll = celcx.expr(&self.inner.cx.tcx.hir().body(ll_id.body).value); - let mut celcx = constant_context(self.inner.cx, self.inner.cx.tcx.typeck_body(rl_id.body)); - let rl = celcx.expr(&self.inner.cx.tcx.hir().body(rl_id.body).value); - - self.eq_expr(le, re) && ll == rl + (&ExprKind::Repeat(le, ref ll_id), &ExprKind::Repeat(re, ref rl_id)) => { + self.eq_expr(le, re) && self.eq_body(ll_id.body, rl_id.body) }, (&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r), - (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => { + (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => { self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_expr_field(l, r)) }, (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), - (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re), + (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r), - (&ExprKind::DropTemps(ref le), &ExprKind::DropTemps(ref re)) => self.eq_expr(le, re), + (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re), _ => false, }; is_eq || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right)) @@ -277,7 +272,7 @@ impl HirEqInterExpr<'_, '_, '_> { } fn eq_expr_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool { - left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr) + left.ident.name == right.ident.name && self.eq_expr(left.expr, right.expr) } fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool { @@ -290,6 +285,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool { match (left, right) { + (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), _ => false, @@ -308,11 +304,11 @@ impl HirEqInterExpr<'_, '_, '_> { /// Checks whether two patterns are the same. fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool { match (&left.kind, &right.kind) { - (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), - (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => { + (&PatKind::Box(l), &PatKind::Box(r)) => self.eq_pat(l, r), + (&PatKind::Struct(ref lp, la, ..), &PatKind::Struct(ref rp, ra, ..)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r)) }, - (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { + (&PatKind::TupleStruct(ref lp, la, ls), &PatKind::TupleStruct(ref rp, ra, rs)) => { self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs }, (&PatKind::Binding(lb, li, _, ref lp), &PatKind::Binding(rb, ri, _, ref rp)) => { @@ -323,15 +319,13 @@ impl HirEqInterExpr<'_, '_, '_> { eq }, (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r), - (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), - (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => { - ls == rs && over(l, r, |l, r| self.eq_pat(l, r)) - }, + (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r), + (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => { both(ls, rs, |a, b| self.eq_expr(a, b)) && both(le, re, |a, b| self.eq_expr(a, b)) && (li == ri) }, - (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re), - (&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => { + (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re), + (&PatKind::Slice(ls, ref li, le), &PatKind::Slice(rs, ref ri, re)) => { over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r)) && both(li, ri, |l, r| self.eq_pat(l, r)) @@ -344,10 +338,10 @@ impl HirEqInterExpr<'_, '_, '_> { #[allow(clippy::similar_names)] fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool { match (left, right) { - (&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => { + (&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => { both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath) }, - (&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => { + (&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => { self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) }, (&QPath::LangItem(llang_item, _), &QPath::LangItem(rlang_item, _)) => llang_item == rlang_item, @@ -359,14 +353,14 @@ impl HirEqInterExpr<'_, '_, '_> { match (left.res, right.res) { (Res::Local(l), Res::Local(r)) => l == r || self.locals.get(&l) == Some(&r), (Res::Local(_), _) | (_, Res::Local(_)) => false, - _ => over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)), + _ => over(left.segments, right.segments, |l, r| self.eq_path_segment(l, r)), } } fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool { if !(left.parenthesized || right.parenthesized) { - over(&left.args, &right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work - && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r)) + over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work + && over(left.bindings, right.bindings, |l, r| self.eq_type_binding(l, r)) } else if left.parenthesized && right.parenthesized { over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r)) && both(&Some(&left.bindings[0].ty()), &Some(&right.bindings[0].ty()), |l, r| { @@ -390,12 +384,9 @@ impl HirEqInterExpr<'_, '_, '_> { #[allow(clippy::similar_names)] fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { match (&left.kind, &right.kind) { - (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => { - let cx = self.inner.cx; - let eval_const = - |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value); - self.eq_ty(lt, rt) && eval_const(ll_id.body) == eval_const(rl_id.body) + (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), + (&TyKind::Array(lt, ref ll_id), &TyKind::Array(rt, ref rl_id)) => { + self.eq_ty(lt, rt) && self.eq_body(ll_id.body, rl_id.body) }, (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => { l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty) @@ -404,14 +395,14 @@ impl HirEqInterExpr<'_, '_, '_> { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) }, (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r), - (&TyKind::Tup(ref l), &TyKind::Tup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), + (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), (&TyKind::Infer, &TyKind::Infer) => true, _ => false, } } fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool { - left.ident.name == right.ident.name && self.eq_ty(&left.ty(), &right.ty()) + left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty()) } } @@ -519,7 +510,7 @@ pub struct SpanlessHash<'a, 'tcx> { /// Context used to evaluate constant expressions. cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, - s: StableHasher, + s: FxHasher, } impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { @@ -527,7 +518,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { Self { cx, maybe_typeck_results: cx.maybe_typeck_results(), - s: StableHasher::new(), + s: FxHasher::default(), } } @@ -540,17 +531,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_stmt(s); } - if let Some(ref e) = b.expr { + if let Some(e) = b.expr { self.hash_expr(e); } - match b.rules { - BlockCheckMode::DefaultBlock => 0, - BlockCheckMode::UnsafeBlock(_) => 1, - BlockCheckMode::PushUnsafeBlock(_) => 2, - BlockCheckMode::PopUnsafeBlock(_) => 3, - } - .hash(&mut self.s); + std::mem::discriminant(&b.rules).hash(&mut self.s); } #[allow(clippy::many_single_char_names, clippy::too_many_lines)] @@ -561,21 +546,16 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { // const hashing may result in the same hash as some unrelated node, so add a sort of // discriminant depending on which path we're choosing next - simple_const.is_some().hash(&mut self.s); - - if let Some(e) = simple_const { - return e.hash(&mut self.s); + simple_const.hash(&mut self.s); + if simple_const.is_some() { + return; } std::mem::discriminant(&e.kind).hash(&mut self.s); match e.kind { - ExprKind::AddrOf(kind, m, ref e) => { - match kind { - BorrowKind::Ref => 0, - BorrowKind::Raw => 1, - } - .hash(&mut self.s); + ExprKind::AddrOf(kind, m, e) => { + std::mem::discriminant(&kind).hash(&mut self.s); m.hash(&mut self.s); self.hash_expr(e); }, @@ -584,22 +564,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(i.ident.name); } }, - ExprKind::Assign(ref l, ref r, _) => { + ExprKind::Assign(l, r, _) => { self.hash_expr(l); self.hash_expr(r); }, - ExprKind::AssignOp(ref o, ref l, ref r) => { - o.node - .hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + ExprKind::AssignOp(ref o, l, r) => { + std::mem::discriminant(&o.node).hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); }, - ExprKind::Block(ref b, _) => { + ExprKind::Block(b, _) => { self.hash_block(b); }, - ExprKind::Binary(op, ref l, ref r) => { - op.node - .hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + ExprKind::Binary(op, l, r) => { + std::mem::discriminant(&op.node).hash(&mut self.s); self.hash_expr(l); self.hash_expr(r); }, @@ -607,39 +585,35 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { if let Some(i) = i.label { self.hash_name(i.ident.name); } - if let Some(ref j) = *j { + if let Some(j) = *j { self.hash_expr(&*j); } }, - ExprKind::Box(ref e) | ExprKind::DropTemps(ref e) | ExprKind::Yield(ref e, _) => { + ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { self.hash_expr(e); }, - ExprKind::Call(ref fun, args) => { + ExprKind::Call(fun, args) => { self.hash_expr(fun); self.hash_exprs(args); }, - ExprKind::Cast(ref e, ref ty) | ExprKind::Type(ref e, ref ty) => { + ExprKind::Cast(e, ty) | ExprKind::Type(e, ty) => { self.hash_expr(e); self.hash_ty(ty); }, ExprKind::Closure(cap, _, eid, _, _) => { - match cap { - CaptureBy::Value => 0, - CaptureBy::Ref => 1, - } - .hash(&mut self.s); + std::mem::discriminant(&cap).hash(&mut self.s); // closures inherit TypeckResults self.hash_expr(&self.cx.tcx.hir().body(eid).value); }, - ExprKind::Field(ref e, ref f) => { + ExprKind::Field(e, ref f) => { self.hash_expr(e); self.hash_name(f.name); }, - ExprKind::Index(ref a, ref i) => { + ExprKind::Index(a, i) => { self.hash_expr(a); self.hash_expr(i); }, - ExprKind::InlineAsm(ref asm) => { + ExprKind::InlineAsm(asm) => { for piece in asm.template { match piece { InlineAsmTemplatePiece::String(s) => s.hash(&mut self.s), @@ -694,22 +668,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Lit(ref l) => { l.node.hash(&mut self.s); }, - ExprKind::Loop(ref b, ref i, ..) => { + ExprKind::Loop(b, ref i, ..) => { self.hash_block(b); if let Some(i) = *i { self.hash_name(i.ident.name); } }, - ExprKind::If(ref cond, ref then, ref else_opt) => { - let c: fn(_, _, _) -> _ = ExprKind::If; - c.hash(&mut self.s); + ExprKind::If(cond, then, ref else_opt) => { self.hash_expr(cond); - self.hash_expr(&**then); - if let Some(ref e) = *else_opt { + self.hash_expr(then); + if let Some(e) = *else_opt { self.hash_expr(e); } }, - ExprKind::Match(ref e, arms, ref s) => { + ExprKind::Match(e, arms, ref s) => { self.hash_expr(e); for arm in arms { @@ -717,39 +689,39 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { if let Some(ref e) = arm.guard { self.hash_guard(e); } - self.hash_expr(&arm.body); + self.hash_expr(arm.body); } s.hash(&mut self.s); }, - ExprKind::MethodCall(ref path, ref _tys, args, ref _fn_span) => { + ExprKind::MethodCall(path, ref _tys, args, ref _fn_span) => { self.hash_name(path.ident.name); self.hash_exprs(args); }, ExprKind::ConstBlock(ref l_id) => { self.hash_body(l_id.body); }, - ExprKind::Repeat(ref e, ref l_id) => { + ExprKind::Repeat(e, ref l_id) => { self.hash_expr(e); self.hash_body(l_id.body); }, ExprKind::Ret(ref e) => { - if let Some(ref e) = *e { + if let Some(e) = *e { self.hash_expr(e); } }, ExprKind::Path(ref qpath) => { self.hash_qpath(qpath); }, - ExprKind::Struct(ref path, fields, ref expr) => { + ExprKind::Struct(path, fields, ref expr) => { self.hash_qpath(path); for f in fields { self.hash_name(f.ident.name); - self.hash_expr(&f.expr); + self.hash_expr(f.expr); } - if let Some(ref e) = *expr { + if let Some(e) = *expr { self.hash_expr(e); } }, @@ -759,8 +731,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Array(v) => { self.hash_exprs(v); }, - ExprKind::Unary(lop, ref le) => { - lop.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + ExprKind::Unary(lop, le) => { + std::mem::discriminant(&lop).hash(&mut self.s); self.hash_expr(le); }, } @@ -773,19 +745,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } pub fn hash_name(&mut self, n: Symbol) { - n.as_str().hash(&mut self.s); + n.hash(&mut self.s); } pub fn hash_qpath(&mut self, p: &QPath<'_>) { match *p { - QPath::Resolved(_, ref path) => { + QPath::Resolved(_, path) => { self.hash_path(path); }, - QPath::TypeRelative(_, ref path) => { + QPath::TypeRelative(_, path) => { self.hash_name(path.ident.name); }, QPath::LangItem(lang_item, ..) => { - lang_item.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + std::mem::discriminant(&lang_item).hash(&mut self.s); }, } // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); @@ -795,7 +767,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { PatKind::Binding(ann, _, _, pat) => { - ann.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + std::mem::discriminant(&ann).hash(&mut self.s); if let Some(pat) = pat { self.hash_pat(pat); } @@ -815,11 +787,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { if let Some(e) = e { self.hash_expr(e); } - i.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s); + std::mem::discriminant(&i).hash(&mut self.s); }, - PatKind::Ref(pat, m) => { + PatKind::Ref(pat, mu) => { self.hash_pat(pat); - m.hash(&mut self.s); + std::mem::discriminant(&mu).hash(&mut self.s); }, PatKind::Slice(l, m, r) => { for pat in l { @@ -838,7 +810,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(f.ident.name); self.hash_pat(f.pat); } - e.hash(&mut self.s) + e.hash(&mut self.s); }, PatKind::Tuple(pats, e) => { for pat in pats { @@ -864,6 +836,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { _ => { for seg in path.segments { self.hash_name(seg.ident.name); + self.hash_generic_args(seg.args().args); } }, } @@ -875,7 +848,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &b.kind { StmtKind::Local(local) => { self.hash_pat(local.pat); - if let Some(ref init) = local.init { + if let Some(init) = local.init { self.hash_expr(init); } }, @@ -888,7 +861,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_guard(&mut self, g: &Guard<'_>) { match g { - Guard::If(ref expr) | Guard::IfLet(_, ref expr) => { + Guard::If(expr) | Guard::IfLet(_, expr) => { self.hash_expr(expr); }, } @@ -921,25 +894,24 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_body(anon_const.body); }, TyKind::Ptr(ref mut_ty) => { - self.hash_ty(&mut_ty.ty); + self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, TyKind::Rptr(lifetime, ref mut_ty) => { self.hash_lifetime(lifetime); - self.hash_ty(&mut_ty.ty); + self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, TyKind::BareFn(bfn) => { bfn.unsafety.hash(&mut self.s); bfn.abi.hash(&mut self.s); for arg in bfn.decl.inputs { - self.hash_ty(&arg); + self.hash_ty(arg); } + std::mem::discriminant(&bfn.decl.output).hash(&mut self.s); match bfn.decl.output { - FnRetTy::DefaultReturn(_) => { - ().hash(&mut self.s); - }, - FnRetTy::Return(ref ty) => { + FnRetTy::DefaultReturn(_) => {}, + FnRetTy::Return(ty) => { self.hash_ty(ty); }, } @@ -950,24 +922,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); } }, - TyKind::Path(ref qpath) => match qpath { - QPath::Resolved(ref maybe_ty, ref path) => { - if let Some(ref ty) = maybe_ty { - self.hash_ty(ty); - } - for segment in path.segments { - segment.ident.name.hash(&mut self.s); - self.hash_generic_args(segment.args().args); - } - }, - QPath::TypeRelative(ref ty, ref segment) => { - self.hash_ty(ty); - segment.ident.name.hash(&mut self.s); - }, - QPath::LangItem(lang_item, ..) => { - lang_item.hash(&mut self.s); - }, - }, + TyKind::Path(ref qpath) => self.hash_qpath(qpath), TyKind::OpaqueDef(_, arg_list) => { self.hash_generic_args(arg_list); }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 82250151aab..769836aaf18 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -63,7 +63,7 @@ use std::hash::BuildHasherDefault; use if_chain::if_chain; use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unhash::UnhashMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -328,7 +328,7 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) /// Checks if an expression references a variable of the given name. pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool { - if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind { + if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind { if let [p] = path.segments { return p.ident.name == var; } @@ -338,8 +338,8 @@ pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool { pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> { match *path { - QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"), - QPath::TypeRelative(_, ref seg) => seg, + QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"), + QPath::TypeRelative(_, seg) => seg, QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"), } } @@ -367,8 +367,8 @@ pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx h pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { match *path { - QPath::Resolved(_, ref path) => path.segments.get(0), - QPath::TypeRelative(_, ref seg) => Some(seg), + QPath::Resolved(_, path) => path.segments.get(0), + QPath::TypeRelative(_, seg) => Some(seg), QPath::LangItem(..) => None, } } @@ -388,8 +388,8 @@ pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment /// ``` pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { match *path { - QPath::Resolved(_, ref path) => match_path(path, segments), - QPath::TypeRelative(ref ty, ref segment) => match ty.kind { + QPath::Resolved(_, path) => match_path(path, segments), + QPath::TypeRelative(ty, segment) => match ty.kind { TyKind::Path(ref inner_path) => { if let [prefix @ .., end] = segments { if match_qpath(inner_path, prefix) { @@ -457,7 +457,7 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool { /// If the expression is a path to a local, returns the canonical `HirId` of the local. pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> { - if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind { + if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind { if let Res::Local(id) = path.res { return Some(id); } @@ -661,13 +661,13 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec let mut matched = Vec::with_capacity(methods.len()); for method_name in methods.iter().rev() { // method chains are stored last -> first - if let ExprKind::MethodCall(ref path, _, ref args, _) = current.kind { + if let ExprKind::MethodCall(path, _, args, _) = current.kind { if path.ident.name.as_str() == *method_name { if args.iter().any(|e| e.span.from_expansion()) { return None; } - matched.push(&**args); // build up `matched` backwards - current = &args[0] // go to parent expression + matched.push(args); // build up `matched` backwards + current = &args[0]; // go to parent expression } else { return None; } @@ -712,7 +712,7 @@ pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> { match pat.kind { PatKind::Binding(.., ref spname, _) => Some(spname.name), PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), - PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p), + PatKind::Box(p) | PatKind::Ref(p, _) => get_pat_name(&*p), _ => None, } } @@ -854,7 +854,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio kind: ImplItemKind::Fn(_, eid), .. }) => match cx.tcx.hir().body(eid).value.kind { - ExprKind::Block(ref block, _) => Some(block), + ExprKind::Block(block, _) => Some(block), _ => None, }, _ => None, @@ -1028,7 +1028,7 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> /// Checks if an expression is constructing a tuple-like enum variant or struct pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ExprKind::Call(ref fun, _) = expr.kind { + if let ExprKind::Call(fun, _) = expr.kind { if let ExprKind::Path(ref qp) = fun.kind { let res = cx.qpath_res(qp, fun.hir_id); return match res { @@ -1058,21 +1058,21 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { match pat.kind { PatKind::Wild => false, PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), - PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), + PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), - PatKind::Or(ref pats) => { + PatKind::Or(pats) => { // TODO: should be the honest check, that pats is exhaustive set are_refutable(cx, pats.iter().map(|pat| &**pat)) }, - PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), - PatKind::Struct(ref qpath, ref fields, _) => { + PatKind::Tuple(pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), + PatKind::Struct(ref qpath, fields, _) => { is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat)) }, - PatKind::TupleStruct(ref qpath, ref pats, _) => { + PatKind::TupleStruct(ref qpath, pats, _) => { is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat)) }, - PatKind::Slice(ref head, ref middle, ref tail) => { + PatKind::Slice(head, ref middle, tail) => { match &cx.typeck_results().node_type(pat.hir_id).kind() { rustc_ty::Slice(..) => { // [..] is the only irrefutable slice pattern. @@ -1094,9 +1094,9 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { /// the function once on the given pattern. pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) { if let PatKind::Or(pats) = pat.kind { - pats.iter().copied().for_each(f) + pats.iter().copied().for_each(f); } else { - f(pat) + f(pat); } } @@ -1111,7 +1111,7 @@ pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return /// themselves. pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { - while let ExprKind::Block(ref block, ..) = expr.kind { + while let ExprKind::Block(block, ..) = expr.kind { match (block.stmts.is_empty(), block.expr.as_ref()) { (true, Some(e)) => expr = e, _ => break, @@ -1130,7 +1130,7 @@ pub fn is_self(slf: &Param<'_>) -> bool { pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool { if_chain! { - if let TyKind::Path(QPath::Resolved(None, ref path)) = slf.kind; + if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind; if let Res::SelfTy(..) = path.res; then { return true @@ -1148,7 +1148,7 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { if_chain! { - if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pat.kind; + if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind; if is_lang_ctor(cx, path, ResultOk); if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind; if path_to_local_id(arm.body, hir_id); @@ -1167,7 +1167,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc } } - if let ExprKind::Match(_, ref arms, ref source) = expr.kind { + if let ExprKind::Match(_, arms, ref source) = expr.kind { // desugared from a `?` operator if let MatchSource::TryDesugar = *source { return Some(expr); @@ -1254,12 +1254,12 @@ pub fn match_function_call<'tcx>( path: &[&str], ) -> Option<&'tcx [Expr<'tcx>]> { if_chain! { - if let ExprKind::Call(ref fun, ref args) = expr.kind; + if let ExprKind::Call(fun, args) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); if match_def_path(cx, fun_def_id, path); then { - return Some(&args) + return Some(args) } }; None @@ -1316,15 +1316,15 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, let mut conds = Vec::new(); let mut blocks: Vec<&Block<'_>> = Vec::new(); - while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind { - conds.push(&**cond); - if let ExprKind::Block(ref block, _) = then_expr.kind { + while let ExprKind::If(cond, then_expr, ref else_expr) = expr.kind { + conds.push(cond); + if let ExprKind::Block(block, _) = then_expr.kind { blocks.push(block); } else { panic!("ExprKind::If node is not an ExprKind::Block"); } - if let Some(ref else_expr) = *else_expr { + if let Some(else_expr) = *else_expr { expr = else_expr; } else { break; @@ -1333,8 +1333,8 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, // final `else {..}` if !blocks.is_empty() { - if let ExprKind::Block(ref block, _) = expr.kind { - blocks.push(&**block); + if let ExprKind::Block(block, _) = expr.kind { + blocks.push(block); } } @@ -1383,7 +1383,7 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { // check if expr is calling method or function with #[must_use] attribute pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { - ExprKind::Call(ref path, _) => if_chain! { + ExprKind::Call(path, _) => if_chain! { if let ExprKind::Path(ref qpath) = path.kind; if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id); then { @@ -1396,7 +1396,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some()) + did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some()) } /// Gets the node where an expression is either used, or it's type is unified with another branch. @@ -1572,14 +1572,16 @@ where Hash: Fn(&T) -> u64, Eq: Fn(&T, &T) -> bool, { - if exprs.len() == 2 && eq(&exprs[0], &exprs[1]) { - return vec![(&exprs[0], &exprs[1])]; + match exprs { + [a, b] if eq(a, b) => return vec![(a, b)], + _ if exprs.len() <= 2 => return vec![], + _ => {}, } let mut match_expr_list: Vec<(&T, &T)> = Vec::new(); - let mut map: FxHashMap<_, Vec<&_>> = - FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default()); + let mut map: UnhashMap<u64, Vec<&_>> = + UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default()); for expr in exprs { match map.entry(hash(expr)) { diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 00df04c0144..4a9c4fd0276 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -26,4 +26,5 @@ msrv_aliases! { 1,34,0 { TRY_FROM } 1,30,0 { ITERATOR_FIND_MAP } 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST } + 1,16,0 { STR_REPEAT } } diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs index 268bc5b3205..546706d51d7 100644 --- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs +++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs @@ -52,7 +52,7 @@ impl<'a> NumericLiteral<'a> { pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> { if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { - let (unsuffixed, suffix) = split_suffix(&src, lit_kind); + let (unsuffixed, suffix) = split_suffix(src, lit_kind); let float = matches!(lit_kind, LitKind::Float(..)); Some(NumericLiteral::new(unsuffixed, suffix, float)) } else { diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs index 5885cc83560..791688cd194 100644 --- a/src/tools/clippy/clippy_utils/src/ptr.rs +++ b/src/tools/clippy/clippy_utils/src/ptr.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { if self.abort { return; } - if let ExprKind::MethodCall(ref seg, _, ref args, _) = expr.kind { + if let ExprKind::MethodCall(seg, _, args, _) = expr.kind { if args.len() == 1 && match_var(&args[0], self.name) { if seg.ident.name.as_str() == "capacity" { self.abort = true; @@ -79,5 +79,5 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { } fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> { - get_pat_name(&arg.pat) + get_pat_name(arg.pat) } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index a08dcf19e5b..0e6ead675c2 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -255,7 +255,7 @@ fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'t cursor = proj_base; match elem { ProjectionElem::Field(..) => { - let base_ty = Place::ty_from(place.local, &proj_base, body, tcx).ty; + let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No union field accesses in `const fn` if def.is_union() { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 0c950661757..efc0ec50fdc 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -2,7 +2,7 @@ #![deny(clippy::missing_docs_in_private_items)] use crate::higher; -use crate::source::{snippet, snippet_opt, snippet_with_macro_callsite}; +use crate::source::{snippet, snippet_opt, snippet_with_context, snippet_with_macro_callsite}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ast, token}; use rustc_ast_pretty::pprust::token_kind_to_string; @@ -10,7 +10,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_span::source_map::{CharPos, Span}; -use rustc_span::{BytePos, Pos}; +use rustc_span::{BytePos, Pos, SyntaxContext}; use std::borrow::Cow; use std::convert::TryInto; use std::fmt::Display; @@ -90,6 +90,29 @@ impl<'a> Sugg<'a> { Self::hir_from_snippet(expr, snippet) } + /// Same as `hir`, but first walks the span up to the given context. This will result in the + /// macro call, rather then the expansion, if the span is from a child context. If the span is + /// not from a child context, it will be used directly instead. + /// + /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR + /// node would result in `box []`. If given the context of the address of expression, this + /// function will correctly get a snippet of `vec![]`. + pub fn hir_with_context( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + ctxt: SyntaxContext, + default: &'a str, + applicability: &mut Applicability, + ) -> Self { + let (snippet, in_macro) = snippet_with_context(cx, expr.span, ctxt, default, applicability); + + if in_macro { + Sugg::NonParen(snippet) + } else { + Self::hir_from_snippet(expr, snippet) + } + } + /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*` /// function variants of `Sugg`, since these use different snippet functions. fn hir_from_snippet(expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self { @@ -684,7 +707,7 @@ impl<T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder if let Some(non_whitespace_offset) = non_whitespace_offset { remove_span = remove_span - .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large"))) + .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large"))); } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index c36e215f184..a92d3be5d3c 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -142,21 +142,18 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), - ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), - ty::Slice(ref ty) - | ty::Array(ref ty, _) - | ty::RawPtr(ty::TypeAndMut { ref ty, .. }) - | ty::Ref(_, ref ty, _) => { + ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did)).is_some(), + ty::Foreign(ref did) => must_use_attr(cx.tcx.get_attrs(*did)).is_some(), + ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) }, - ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), + ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(ref def_id, _) => { for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() { - if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { + if must_use_attr(cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { return true; } } @@ -166,7 +163,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Dynamic(binder, _) => { for predicate in binder.iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() { + if must_use_attr(cx.tcx.get_attrs(trait_ref.def_id)).is_some() { return true; } } @@ -305,7 +302,7 @@ pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bo /// Returns the base type for HIR references and pointers. pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { match ty.kind { - TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty), + TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty), _ => ty, } } diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index 650b70c63af..2c55021ac88 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -59,7 +59,7 @@ impl<'tcx> MutVarsDelegate { //FIXME: This causes false negatives. We can't get the `NodeId` from //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the //`while`-body, not just the ones in the condition. - self.skip = true + self.skip = true; }, _ => {}, } @@ -71,12 +71,12 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate { fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { - self.update(&cmt) + self.update(cmt); } } fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) { - self.update(&cmt) + self.update(cmt); } fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {} diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index ecdc666b5f6..ce00106dd4d 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -87,7 +87,7 @@ where } fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) { - intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt) + intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt); } fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) { @@ -189,34 +189,21 @@ impl<'v> Visitor<'v> for LocalUsedVisitor<'v> { } } +/// A type which can be visited. pub trait Visitable<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V); + /// Calls the corresponding `visit_*` function on the visitor. + fn visit<V: Visitor<'tcx>>(self, visitor: &mut V); } -impl Visitable<'tcx> for &'tcx Expr<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V) { - v.visit_expr(self) - } -} -impl Visitable<'tcx> for &'tcx Block<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V) { - v.visit_block(self) - } -} -impl<'tcx> Visitable<'tcx> for &'tcx Stmt<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V) { - v.visit_stmt(self) - } -} -impl<'tcx> Visitable<'tcx> for &'tcx Body<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V) { - v.visit_body(self) - } -} -impl<'tcx> Visitable<'tcx> for &'tcx Arm<'tcx> { - fn visit<V: Visitor<'tcx>>(self, v: &mut V) { - v.visit_arm(self) - } +macro_rules! visitable_ref { + ($t:ident, $f:ident) => { + impl Visitable<'tcx> for &'tcx $t<'tcx> { + fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) { + visitor.$f(self); + } + } + }; } +visitable_ref!(Block, visit_block); /// Calls the given function for each break expression. pub fn visit_break_exprs<'tcx>( @@ -232,7 +219,7 @@ pub fn visit_break_exprs<'tcx>( fn visit_expr(&mut self, e: &'tcx Expr<'_>) { if let ExprKind::Break(dest, sub_expr) = e.kind { - self.0(e, dest, sub_expr) + self.0(e, dest, sub_expr); } walk_expr(self, e); } @@ -264,7 +251,7 @@ pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool { self.found = true; } } else { - walk_expr(self, e) + walk_expr(self, e); } } } diff --git a/src/tools/clippy/doc/release.md b/src/tools/clippy/doc/release.md index eaa6a9af277..e0af9bf0625 100644 --- a/src/tools/clippy/doc/release.md +++ b/src/tools/clippy/doc/release.md @@ -94,7 +94,7 @@ After finding the Clippy commit, it can be tagged with the release number. # Assuming the current directory corresponds to the Clippy repository $ git checkout $SHA $ git tag rust-1.XX.0 # XX should be exchanged with the corresponding version -$ git push upstream master --tags # `upstream` is the `rust-lang/rust-clippy` remote +$ git push upstream rust-1.XX.0 # `upstream` is the `rust-lang/rust-clippy` remote ``` After this, the release should be available on the Clippy [release page]. diff --git a/src/tools/clippy/mini-macro/Cargo.toml b/src/tools/clippy/mini-macro/Cargo.toml deleted file mode 100644 index 0d95c86aef0..00000000000 --- a/src/tools/clippy/mini-macro/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "clippy-mini-macro-test" -version = "0.2.0" -authors = ["The Rust Clippy Developers"] -license = "MIT OR Apache-2.0" -description = "A macro to test clippy's procedural macro checks" -repository = "https://github.com/rust-lang/rust-clippy" -edition = "2018" - -[lib] -name = "clippy_mini_macro_test" -proc-macro = true - -[dependencies] diff --git a/src/tools/clippy/mini-macro/src/lib.rs b/src/tools/clippy/mini-macro/src/lib.rs deleted file mode 100644 index 2b793589049..00000000000 --- a/src/tools/clippy/mini-macro/src/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![feature(proc_macro_quote)] -#![deny(rust_2018_idioms)] -// FIXME: Remove this attribute once the weird failure is gone. -#![allow(unused_extern_crates)] -extern crate proc_macro; - -use proc_macro::{quote, TokenStream}; - -#[proc_macro_derive(ClippyMiniMacroTest)] -/// # Panics -/// -/// Panics if the macro derivation fails -pub fn mini_macro(_: TokenStream) -> TokenStream { - quote!( - #[allow(unused)] - fn needless_take_by_value(s: String) { - println!("{}", s.len()); - } - #[allow(unused)] - fn needless_loop(items: &[u8]) { - for i in 0..items.len() { - println!("{}", items[i]); - } - } - fn line_wrapper() { - println!("{}", line!()); - } - ) -} diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index cb8cb0978f6..e3863c46288 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-05-20" +channel = "nightly-2021-06-03" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs index ff2a7de5725..5f289918a7c 100644 --- a/src/tools/clippy/rustc_tools_util/src/lib.rs +++ b/src/tools/clippy/rustc_tools_util/src/lib.rs @@ -100,9 +100,9 @@ pub fn get_commit_date() -> Option<String> { } #[must_use] -pub fn get_channel() -> Option<String> { +pub fn get_channel() -> String { match env::var("CFG_RELEASE_CHANNEL") { - Ok(channel) => Some(channel), + Ok(channel) => channel, Err(_) => { // if that failed, try to ask rustc -V, do some parsing and find out match std::process::Command::new("rustc") @@ -113,16 +113,16 @@ pub fn get_channel() -> Option<String> { { Some(rustc_output) => { if rustc_output.contains("beta") { - Some(String::from("beta")) + String::from("beta") } else if rustc_output.contains("stable") { - Some(String::from("stable")) + String::from("stable") } else { // default to nightly if we fail to parse - Some(String::from("nightly")) + String::from("nightly") } }, // default to nightly - None => Some(String::from("nightly")), + None => String::from("nightly"), } }, } diff --git a/src/tools/clippy/tests/clippy.toml b/src/tools/clippy/tests/clippy.toml new file mode 100644 index 00000000000..5eb7ac03541 --- /dev/null +++ b/src/tools/clippy/tests/clippy.toml @@ -0,0 +1 @@ +# default config for tests, overrides clippy.toml at the project root diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index e1110721f6e..7d266a36bb6 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -4,8 +4,8 @@ use compiletest_rs as compiletest; use compiletest_rs::common::Mode as TestMode; -use std::env::{self, set_var, var}; -use std::ffi::OsStr; +use std::env::{self, remove_var, set_var, var_os}; +use std::ffi::{OsStr, OsString}; use std::fs; use std::io; use std::path::{Path, PathBuf}; @@ -88,9 +88,11 @@ fn default_config() -> compiletest::Config { config } -fn run_mode(cfg: &mut compiletest::Config) { +fn run_ui(cfg: &mut compiletest::Config) { cfg.mode = TestMode::Ui; cfg.src_base = Path::new("tests").join("ui"); + // use tests/clippy.toml + let _g = VarGuard::set("CARGO_MANIFEST_DIR", std::fs::canonicalize("tests").unwrap()); compiletest::run_tests(cfg); } @@ -114,7 +116,7 @@ fn run_ui_toml(config: &mut compiletest::Config) { continue; } let dir_path = dir.path(); - set_var("CARGO_MANIFEST_DIR", &dir_path); + let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path); for file in fs::read_dir(&dir_path)? { let file = file?; let file_path = file.path(); @@ -145,9 +147,7 @@ fn run_ui_toml(config: &mut compiletest::Config) { let tests = compiletest::make_tests(config); - let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default(); let res = run_tests(config, tests); - set_var("CARGO_MANIFEST_DIR", &manifest_dir); match res { Ok(true) => {}, Ok(false) => panic!("Some tests failed"), @@ -208,7 +208,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) { Some("main.rs") => {}, _ => continue, } - set_var("CLIPPY_CONF_DIR", case.path()); + let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path()); let paths = compiletest::common::TestPaths { file: file_path, base: config.src_base.clone(), @@ -236,10 +236,8 @@ fn run_ui_cargo(config: &mut compiletest::Config) { let tests = compiletest::make_tests(config); let current_dir = env::current_dir().unwrap(); - let conf_dir = var("CLIPPY_CONF_DIR").unwrap_or_default(); let res = run_tests(config, &config.filters, tests); env::set_current_dir(current_dir).unwrap(); - set_var("CLIPPY_CONF_DIR", conf_dir); match res { Ok(true) => {}, @@ -260,8 +258,32 @@ fn prepare_env() { fn compile_test() { prepare_env(); let mut config = default_config(); - run_mode(&mut config); + run_ui(&mut config); run_ui_toml(&mut config); run_ui_cargo(&mut config); run_internal_tests(&mut config); } + +/// Restores an env var on drop +#[must_use] +struct VarGuard { + key: &'static str, + value: Option<OsString>, +} + +impl VarGuard { + fn set(key: &'static str, val: impl AsRef<OsStr>) -> Self { + let value = var_os(key); + set_var(key, val); + Self { key, value } + } +} + +impl Drop for VarGuard { + fn drop(&mut self) { + match self.value.as_deref() { + None => remove_var(self.key), + Some(value) => set_var(self.key, value), + } + } +} diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs index 5d9f128753f..7de130c7dbe 100644 --- a/src/tools/clippy/tests/dogfood.rs +++ b/src/tools/clippy/tests/dogfood.rs @@ -179,8 +179,39 @@ fn dogfood_subprojects() { #[ignore] #[cfg(feature = "metadata-collector-lint")] fn run_metadata_collection_lint() { + use std::fs::File; + use std::time::SystemTime; + + // Setup for validation + let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/metadata_collection.json"); + let start_time = SystemTime::now(); + + // Run collection as is std::env::set_var("ENABLE_METADATA_COLLECTION", "1"); run_clippy_for_project("clippy_lints"); + + // Check if cargo caching got in the way + if let Ok(file) = File::open(metadata_output_path) { + if let Ok(metadata) = file.metadata() { + if let Ok(last_modification) = metadata.modified() { + if last_modification > start_time { + // The output file has been modified. Most likely by a hungry + // metadata collection monster. So We'll return. + return; + } + } + } + } + + // Force cargo to invalidate the caches + filetime::set_file_mtime( + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"), + filetime::FileTime::now(), + ) + .unwrap(); + + // Running the collection again + run_clippy_for_project("clippy_lints"); } fn run_clippy_for_project(project: &str) { diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index d83080b69f5..a7be00426c4 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1 +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs index aebeaf34679..4b7b7fec78f 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs @@ -53,3 +53,22 @@ pub fn derive_use_self(_input: TokenStream) -> proc_macro::TokenStream { } } } + +#[proc_macro_derive(ClippyMiniMacroTest)] +pub fn mini_macro(_: TokenStream) -> TokenStream { + quote!( + #[allow(unused)] + fn needless_take_by_value(s: String) { + println!("{}", s.len()); + } + #[allow(unused)] + fn needless_loop(items: &[u8]) { + for i in 0..items.len() { + println!("{}", items[i]); + } + } + fn line_wrapper() { + println!("{}", line!()); + } + ) +} diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs new file mode 100644 index 00000000000..780797e3c6a --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs @@ -0,0 +1,14 @@ +pub fn warn<T>(_: T) {} + +macro_rules! define_macro { + ($d:tt $lower:ident $upper:ident) => { + #[macro_export] + macro_rules! $upper { + ($arg:tt) => { + $crate::$lower($arg) + }; + } + }; +} + +define_macro! {$ warn WARNING} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7272.rs b/src/tools/clippy/tests/ui/crashes/ice-7272.rs new file mode 100644 index 00000000000..57ab6ca14f8 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-7272.rs @@ -0,0 +1,12 @@ +// aux-build:ice-7272-aux.rs + +#![allow(clippy::no_effect)] + +extern crate ice_7272_aux; + +use ice_7272_aux::*; + +pub fn main() { + || WARNING!("Style changed!"); + || "}{"; +} diff --git a/src/tools/clippy/tests/ui/crashes/procedural_macro.rs b/src/tools/clippy/tests/ui/crashes/procedural_macro.rs deleted file mode 100644 index c7468493380..00000000000 --- a/src/tools/clippy/tests/ui/crashes/procedural_macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[macro_use] -extern crate clippy_mini_macro_test; - -#[deny(warnings)] -fn main() { - let x = Foo; - println!("{:?}", x); -} - -#[derive(ClippyMiniMacroTest, Debug)] -struct Foo; diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs index 2a948d60b10..cba7666c2d8 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.rs +++ b/src/tools/clippy/tests/ui/def_id_nocore.rs @@ -20,7 +20,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } -pub struct A; +struct A; impl A { pub fn as_ref(self) -> &'static str { diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index dbf0b03af76..4ba9f0c1fcf 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -12,5 +12,7 @@ #[warn(clippy::unknown_clippy_lints)] #[warn(clippy::find_map)] #[warn(clippy::filter_map)] +#[warn(clippy::pub_enum_variant_names)] +#[warn(clippy::wrong_pub_self_convention)] fn main() {} diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index e5de839dbc5..03c9f438891 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -84,5 +84,17 @@ error: lint `clippy::filter_map` has been removed: this lint has been replaced b LL | #[warn(clippy::filter_map)] | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items + --> $DIR/deprecated.rs:15:8 + | +LL | #[warn(clippy::pub_enum_variant_names)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items + --> $DIR/deprecated.rs:16:8 + | +LL | #[warn(clippy::wrong_pub_self_convention)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/enum_variants.rs b/src/tools/clippy/tests/ui/enum_variants.rs index 4fefc0b43f1..083f5143e6e 100644 --- a/src/tools/clippy/tests/ui/enum_variants.rs +++ b/src/tools/clippy/tests/ui/enum_variants.rs @@ -1,5 +1,4 @@ -#![feature(non_ascii_idents)] -#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)] +#![warn(clippy::enum_variant_names)] #![allow(non_camel_case_types, clippy::upper_case_acronyms)] enum FakeCallType { @@ -97,8 +96,8 @@ pub enum PubSeall { WithOut, } -#[allow(clippy::pub_enum_variant_names)] -mod allowed { +#[allow(clippy::enum_variant_names)] +pub mod allowed { pub enum PubAllowed { SomeThis, SomeThat, diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr index ab7fff4507a..447fbb9e1bf 100644 --- a/src/tools/clippy/tests/ui/enum_variants.stderr +++ b/src/tools/clippy/tests/ui/enum_variants.stderr @@ -1,5 +1,5 @@ error: variant name ends with the enum's name - --> $DIR/enum_variants.rs:16:5 + --> $DIR/enum_variants.rs:15:5 | LL | cFoo, | ^^^^ @@ -7,25 +7,25 @@ LL | cFoo, = note: `-D clippy::enum-variant-names` implied by `-D warnings` error: variant name starts with the enum's name - --> $DIR/enum_variants.rs:27:5 + --> $DIR/enum_variants.rs:26:5 | LL | FoodGood, | ^^^^^^^^ error: variant name starts with the enum's name - --> $DIR/enum_variants.rs:28:5 + --> $DIR/enum_variants.rs:27:5 | LL | FoodMiddle, | ^^^^^^^^^^ error: variant name starts with the enum's name - --> $DIR/enum_variants.rs:29:5 + --> $DIR/enum_variants.rs:28:5 | LL | FoodBad, | ^^^^^^^ error: all variants have the same prefix: `Food` - --> $DIR/enum_variants.rs:26:1 + --> $DIR/enum_variants.rs:25:1 | LL | / enum Food { LL | | FoodGood, @@ -37,7 +37,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `CallType` - --> $DIR/enum_variants.rs:36:1 + --> $DIR/enum_variants.rs:35:1 | LL | / enum BadCallType { LL | | CallTypeCall, @@ -49,7 +49,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `Constant` - --> $DIR/enum_variants.rs:48:1 + --> $DIR/enum_variants.rs:47:1 | LL | / enum Consts { LL | | ConstantInt, @@ -61,7 +61,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `With` - --> $DIR/enum_variants.rs:82:1 + --> $DIR/enum_variants.rs:81:1 | LL | / enum Seallll { LL | | WithOutCake, @@ -73,7 +73,7 @@ LL | | } = help: remove the prefixes and use full paths to the variants instead of glob imports error: all variants have the same prefix: `Prefix` - --> $DIR/enum_variants.rs:88:1 + --> $DIR/enum_variants.rs:87:1 | LL | / enum NonCaps { LL | | Prefix的, @@ -84,21 +84,8 @@ LL | | } | = help: remove the prefixes and use full paths to the variants instead of glob imports -error: all variants have the same prefix: `With` - --> $DIR/enum_variants.rs:94:1 - | -LL | / pub enum PubSeall { -LL | | WithOutCake, -LL | | WithOutTea, -LL | | WithOut, -LL | | } - | |_^ - | - = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings` - = help: remove the prefixes and use full paths to the variants instead of glob imports - error: all variants have the same postfix: `IData` - --> $DIR/enum_variants.rs:137:1 + --> $DIR/enum_variants.rs:136:1 | LL | / enum IDataRequest { LL | | PutIData(String), @@ -110,7 +97,7 @@ LL | | } = help: remove the postfixes and use full paths to the variants instead of glob imports error: all variants have the same postfix: `HIData` - --> $DIR/enum_variants.rs:143:1 + --> $DIR/enum_variants.rs:142:1 | LL | / enum HIDataRequest { LL | | PutHIData(String), @@ -121,5 +108,5 @@ LL | | } | = help: remove the postfixes and use full paths to the variants instead of glob imports -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed index 2be2283e3fd..9e752311c67 100644 --- a/src/tools/clippy/tests/ui/eta.fixed +++ b/src/tools/clippy/tests/ui/eta.fixed @@ -48,6 +48,9 @@ fn main() { // See #515 let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> = Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) }); + + // issue #7224 + let _: Option<Vec<u32>> = Some(0).map(|_| vec![]); } trait TestTrait { diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs index f0373f9ccf6..44be4628cbd 100644 --- a/src/tools/clippy/tests/ui/eta.rs +++ b/src/tools/clippy/tests/ui/eta.rs @@ -48,6 +48,9 @@ fn main() { // See #515 let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> = Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) }); + + // issue #7224 + let _: Option<Vec<u32>> = Some(0).map(|_| vec![]); } trait TestTrait { diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr index 57ed6527966..8795d3b42c6 100644 --- a/src/tools/clippy/tests/ui/eta.stderr +++ b/src/tools/clippy/tests/ui/eta.stderr @@ -33,7 +33,7 @@ LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:89:51 + --> $DIR/eta.rs:92:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -41,43 +41,43 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:91:51 + --> $DIR/eta.rs:94:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:94:42 + --> $DIR/eta.rs:97:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:99:29 + --> $DIR/eta.rs:102:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:101:27 + --> $DIR/eta.rs:104:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:104:65 + --> $DIR/eta.rs:107:65 | LL | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:187:27 + --> $DIR/eta.rs:190:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:192:27 + --> $DIR/eta.rs:195:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed index b5f548810e6..12db43b5343 100644 --- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed +++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed @@ -6,6 +6,20 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; use std::iter::FromIterator; +struct Foo(Vec<bool>); + +impl FromIterator<bool> for Foo { + fn from_iter<T: IntoIterator<Item = bool>>(_: T) -> Self { + todo!() + } +} + +impl<'a> FromIterator<&'a bool> for Foo { + fn from_iter<T: IntoIterator<Item = &'a bool>>(iter: T) -> Self { + iter.into_iter().copied().collect::<Self>() + } +} + fn main() { let iter_expr = std::iter::repeat(5).take(5); let _ = iter_expr.collect::<Vec<_>>(); diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs index b842b5451d1..f5ec190e0cd 100644 --- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs @@ -6,6 +6,20 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; use std::iter::FromIterator; +struct Foo(Vec<bool>); + +impl FromIterator<bool> for Foo { + fn from_iter<T: IntoIterator<Item = bool>>(_: T) -> Self { + todo!() + } +} + +impl<'a> FromIterator<&'a bool> for Foo { + fn from_iter<T: IntoIterator<Item = &'a bool>>(iter: T) -> Self { + <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied()) + } +} + fn main() { let iter_expr = std::iter::repeat(5).take(5); let _ = Vec::from_iter(iter_expr); diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr index 434734c9a21..8f08ac8c3ff 100644 --- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr +++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr @@ -1,88 +1,94 @@ error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:11:13 + --> $DIR/from_iter_instead_of_collect.rs:19:9 | -LL | let _ = Vec::from_iter(iter_expr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()` +LL | <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::<Self>()` | = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:13:13 + --> $DIR/from_iter_instead_of_collect.rs:25:13 + | +LL | let _ = Vec::from_iter(iter_expr); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()` + +error: usage of `FromIterator::from_iter` + --> $DIR/from_iter_instead_of_collect.rs:27:13 | LL | let _ = HashMap::<usize, &i8>::from_iter(vec![5, 5, 5, 5].iter().enumerate()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::<HashMap<usize, &i8>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:18:19 + --> $DIR/from_iter_instead_of_collect.rs:32:19 | LL | assert_eq!(a, Vec::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<_>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:19:19 + --> $DIR/from_iter_instead_of_collect.rs:33:19 | LL | assert_eq!(a, Vec::<i32>::from_iter(0..3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<i32>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:21:17 + --> $DIR/from_iter_instead_of_collect.rs:35:17 | LL | let mut b = VecDeque::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<_>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:24:17 + --> $DIR/from_iter_instead_of_collect.rs:38:17 | LL | let mut b = VecDeque::<i32>::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<i32>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:29:21 + --> $DIR/from_iter_instead_of_collect.rs:43:21 | LL | let mut b = collections::VecDeque::<i32>::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::VecDeque<i32>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:34:14 + --> $DIR/from_iter_instead_of_collect.rs:48:14 | LL | let bm = BTreeMap::from_iter(values.iter().cloned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::<BTreeMap<_, _>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:35:19 + --> $DIR/from_iter_instead_of_collect.rs:49:19 | LL | let mut bar = BTreeMap::from_iter(bm.range(0..2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::<BTreeMap<_, _>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:38:19 + --> $DIR/from_iter_instead_of_collect.rs:52:19 | LL | let mut bts = BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<BTreeSet<_>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:42:17 + --> $DIR/from_iter_instead_of_collect.rs:56:17 | LL | let _ = collections::BTreeSet::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<_>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:43:17 + --> $DIR/from_iter_instead_of_collect.rs:57:17 | LL | let _ = collections::BTreeSet::<u32>::from_iter(0..3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<u32>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:46:15 + --> $DIR/from_iter_instead_of_collect.rs:60:15 | LL | for _i in Vec::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<_>>()` error: usage of `FromIterator::from_iter` - --> $DIR/from_iter_instead_of_collect.rs:47:15 + --> $DIR/from_iter_instead_of_collect.rs:61:15 | LL | for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<&i32>>()` -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr index 0a86568b18d..a2b8c2a384b 100644 --- a/src/tools/clippy/tests/ui/functions.stderr +++ b/src/tools/clippy/tests/ui/functions.stderr @@ -30,7 +30,7 @@ error: this function has too many arguments (8/7) LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:63:34 | LL | println!("{}", unsafe { *p }); @@ -38,49 +38,49 @@ LL | println!("{}", unsafe { *p }); | = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings` -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:64:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:65:33 | LL | unsafe { std::ptr::read(p) }; | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:76:30 | LL | println!("{}", unsafe { *p }); | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:77:31 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:78:29 | LL | unsafe { std::ptr::read(p) }; | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:87:34 | LL | println!("{}", unsafe { *p }); | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:88:35 | LL | println!("{:?}", unsafe { p.as_ref() }); | ^ -error: this public function dereferences a raw pointer but is not marked `unsafe` +error: this public function might dereference a raw pointer but is not marked `unsafe` --> $DIR/functions.rs:89:33 | LL | unsafe { std::ptr::read(p) }; diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed index 51c66a46368..70d49d9f2c4 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.fixed +++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed @@ -1,6 +1,7 @@ // compile-flags: --edition 2018 // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs +// aux-build:proc_macro_derive.rs // run-rustfix // ignore-32bit @@ -12,7 +13,7 @@ extern crate macro_use_helper as mac; #[macro_use] -extern crate clippy_mini_macro_test as mini_mac; +extern crate proc_macro_derive as mini_mac; mod a { use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}; diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs index 2011129bc94..68370023861 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports.rs @@ -1,6 +1,7 @@ // compile-flags: --edition 2018 // aux-build:macro_rules.rs // aux-build:macro_use_helper.rs +// aux-build:proc_macro_derive.rs // run-rustfix // ignore-32bit @@ -12,7 +13,7 @@ extern crate macro_use_helper as mac; #[macro_use] -extern crate clippy_mini_macro_test as mini_mac; +extern crate proc_macro_derive as mini_mac; mod a { #[macro_use] diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index f8c86c8d917..49314b7506d 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,5 +1,5 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:18:5 + --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` @@ -7,22 +7,22 @@ LL | #[macro_use] = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:20:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:22:5 + --> $DIR/macro_use_imports.rs:21:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:24:5 + --> $DIR/macro_use_imports.rs:23:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.fixed b/src/tools/clippy/tests/ui/manual_str_repeat.fixed new file mode 100644 index 00000000000..dc140257f32 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_str_repeat.fixed @@ -0,0 +1,66 @@ +// run-rustfix + +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_str_repeat)] + +use std::borrow::Cow; +use std::iter::{repeat, FromIterator}; + +fn main() { + let _: String = "test".repeat(10); + let _: String = "x".repeat(10); + let _: String = "'".repeat(10); + let _: String = "\"".repeat(10); + + let x = "test"; + let count = 10; + let _ = x.repeat(count + 2); + + macro_rules! m { + ($e:expr) => {{ $e }}; + } + // FIXME: macro args are fine + let _: String = repeat(m!("test")).take(m!(count)).collect(); + + let x = &x; + let _: String = (*x).repeat(count); + + macro_rules! repeat_m { + ($e:expr) => {{ repeat($e) }}; + } + // Don't lint, repeat is from a macro. + let _: String = repeat_m!("test").take(count).collect(); + + let x: Box<str> = Box::from("test"); + let _: String = x.repeat(count); + + #[derive(Clone)] + struct S; + impl FromIterator<Box<S>> for String { + fn from_iter<T: IntoIterator<Item = Box<S>>>(_: T) -> Self { + Self::new() + } + } + // Don't lint, wrong box type + let _: String = repeat(Box::new(S)).take(count).collect(); + + let _: String = Cow::Borrowed("test").repeat(count); + + let x = "x".to_owned(); + let _: String = x.repeat(count); + + let x = 'x'; + // Don't lint, not char literal + let _: String = repeat(x).take(count).collect(); +} + +fn _msrv_1_15() { + #![clippy::msrv = "1.15"] + // `str::repeat` was stabilized in 1.16. Do not lint this + let _: String = std::iter::repeat("test").take(10).collect(); +} + +fn _msrv_1_16() { + #![clippy::msrv = "1.16"] + let _: String = "test".repeat(10); +} diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.rs b/src/tools/clippy/tests/ui/manual_str_repeat.rs new file mode 100644 index 00000000000..0d69c989b2e --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_str_repeat.rs @@ -0,0 +1,66 @@ +// run-rustfix + +#![feature(custom_inner_attributes)] +#![warn(clippy::manual_str_repeat)] + +use std::borrow::Cow; +use std::iter::{repeat, FromIterator}; + +fn main() { + let _: String = std::iter::repeat("test").take(10).collect(); + let _: String = std::iter::repeat('x').take(10).collect(); + let _: String = std::iter::repeat('\'').take(10).collect(); + let _: String = std::iter::repeat('"').take(10).collect(); + + let x = "test"; + let count = 10; + let _ = repeat(x).take(count + 2).collect::<String>(); + + macro_rules! m { + ($e:expr) => {{ $e }}; + } + // FIXME: macro args are fine + let _: String = repeat(m!("test")).take(m!(count)).collect(); + + let x = &x; + let _: String = repeat(*x).take(count).collect(); + + macro_rules! repeat_m { + ($e:expr) => {{ repeat($e) }}; + } + // Don't lint, repeat is from a macro. + let _: String = repeat_m!("test").take(count).collect(); + + let x: Box<str> = Box::from("test"); + let _: String = repeat(x).take(count).collect(); + + #[derive(Clone)] + struct S; + impl FromIterator<Box<S>> for String { + fn from_iter<T: IntoIterator<Item = Box<S>>>(_: T) -> Self { + Self::new() + } + } + // Don't lint, wrong box type + let _: String = repeat(Box::new(S)).take(count).collect(); + + let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); + + let x = "x".to_owned(); + let _: String = repeat(x).take(count).collect(); + + let x = 'x'; + // Don't lint, not char literal + let _: String = repeat(x).take(count).collect(); +} + +fn _msrv_1_15() { + #![clippy::msrv = "1.15"] + // `str::repeat` was stabilized in 1.16. Do not lint this + let _: String = std::iter::repeat("test").take(10).collect(); +} + +fn _msrv_1_16() { + #![clippy::msrv = "1.16"] + let _: String = std::iter::repeat("test").take(10).collect(); +} diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.stderr b/src/tools/clippy/tests/ui/manual_str_repeat.stderr new file mode 100644 index 00000000000..c6511689716 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_str_repeat.stderr @@ -0,0 +1,64 @@ +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:10:21 + | +LL | let _: String = std::iter::repeat("test").take(10).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` + | + = note: `-D clippy::manual-str-repeat` implied by `-D warnings` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:11:21 + | +LL | let _: String = std::iter::repeat('x').take(10).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"x".repeat(10)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:12:21 + | +LL | let _: String = std::iter::repeat('/'').take(10).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"'".repeat(10)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:13:21 + | +LL | let _: String = std::iter::repeat('"').take(10).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"/"".repeat(10)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:17:13 + | +LL | let _ = repeat(x).take(count + 2).collect::<String>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count + 2)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:26:21 + | +LL | let _: String = repeat(*x).take(count).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(*x).repeat(count)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:35:21 + | +LL | let _: String = repeat(x).take(count).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:47:21 + | +LL | let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Cow::Borrowed("test").repeat(count)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:50:21 + | +LL | let _: String = repeat(x).take(count).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)` + +error: manual implementation of `str::repeat` using iterators + --> $DIR/manual_str_repeat.rs:65:21 + | +LL | let _: String = std::iter::repeat("test").take(10).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)` + +error: aborting due to 10 previous errors + diff --git a/src/tools/clippy/tests/ui/missing-doc-impl.rs b/src/tools/clippy/tests/ui/missing-doc-impl.rs index 57af84dcdf4..bfa9ef01b0e 100644 --- a/src/tools/clippy/tests/ui/missing-doc-impl.rs +++ b/src/tools/clippy/tests/ui/missing-doc-impl.rs @@ -67,7 +67,10 @@ impl PubFoo { pub fn foo() {} /// dox pub fn foo1() {} - fn foo2() {} + #[must_use = "yep"] + fn foo2() -> u32 { + 1 + } #[allow(clippy::missing_docs_in_private_items)] pub fn foo3() {} } diff --git a/src/tools/clippy/tests/ui/missing-doc-impl.stderr b/src/tools/clippy/tests/ui/missing-doc-impl.stderr index 7e10404ca00..d33d512475b 100644 --- a/src/tools/clippy/tests/ui/missing-doc-impl.stderr +++ b/src/tools/clippy/tests/ui/missing-doc-impl.stderr @@ -94,10 +94,12 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:70:5 + --> $DIR/missing-doc-impl.rs:71:5 | -LL | fn foo2() {} - | ^^^^^^^^^^^^ +LL | / fn foo2() -> u32 { +LL | | 1 +LL | | } + | |_____^ error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.rs b/src/tools/clippy/tests/ui/module_name_repetitions.rs index 669bf01a84c..f5908cb5701 100644 --- a/src/tools/clippy/tests/ui/module_name_repetitions.rs +++ b/src/tools/clippy/tests/ui/module_name_repetitions.rs @@ -15,12 +15,4 @@ mod foo { pub struct Foobar; } -#[cfg(test)] -mod test { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} - fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index 5ae4a0e79b9..a87171dc3f2 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -18,7 +18,6 @@ fn main() { let vec = Vec::new(); let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]` h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait` - if let Some(cake) = Some(&5) {} let garbl = match 42 { 44 => &a, 45 => { @@ -43,19 +42,3 @@ trait Trait {} impl<'a> Trait for &'a str {} fn h(_: &dyn Trait) {} -#[warn(clippy::needless_borrow)] -#[allow(dead_code)] -fn issue_1432() { - let mut v = Vec::<String>::new(); - let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - let _ = v.iter().filter(|&a| a.is_empty()); - - let _ = v.iter().filter(|&a| a.is_empty()); -} - -#[allow(dead_code)] -#[warn(clippy::needless_borrow)] -#[derive(Debug)] -enum Foo<'a> { - Str(&'a str), -} diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 1e281316c8a..059dc8ceac3 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -18,7 +18,6 @@ fn main() { let vec = Vec::new(); let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]` h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait` - if let Some(ref cake) = Some(&5) {} let garbl = match 42 { 44 => &a, 45 => { @@ -43,19 +42,3 @@ trait Trait {} impl<'a> Trait for &'a str {} fn h(_: &dyn Trait) {} -#[warn(clippy::needless_borrow)] -#[allow(dead_code)] -fn issue_1432() { - let mut v = Vec::<String>::new(); - let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - let _ = v.iter().filter(|&ref a| a.is_empty()); - - let _ = v.iter().filter(|&a| a.is_empty()); -} - -#[allow(dead_code)] -#[warn(clippy::needless_borrow)] -#[derive(Debug)] -enum Foo<'a> { - Str(&'a str), -} diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index bea4b41b803..6eddf26db06 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -6,23 +6,11 @@ LL | let c = x(&&a); | = note: `-D clippy::needless-borrow` implied by `-D warnings` -error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:21:17 - | -LL | if let Some(ref cake) = Some(&5) {} - | ^^^^^^^^ help: change this to: `cake` - error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:28:15 + --> $DIR/needless_borrow.rs:27:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` -error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:51:31 - | -LL | let _ = v.iter().filter(|&ref a| a.is_empty()); - | ^^^^^ help: change this to: `a` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.rs b/src/tools/clippy/tests/ui/needless_borrow_pat.rs new file mode 100644 index 00000000000..f0926220755 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_borrow_pat.rs @@ -0,0 +1,151 @@ +// edition:2018 +// FIXME: run-rustfix waiting on multi-span suggestions + +#![warn(clippy::needless_borrow)] +#![allow(clippy::needless_borrowed_reference)] + +fn f1(_: &str) {} +macro_rules! m1 { + ($e:expr) => { + f1($e); + }; +} +macro_rules! m3 { + ($i:ident) => { + Some(ref $i) + }; +} +macro_rules! if_chain { + (if $e:expr; $($rest:tt)*) => { + if $e { + if_chain!($($rest)*) + } + }; + + (if let $p:pat = $e:expr; $($rest:tt)*) => { + if let $p = $e { + if_chain!($($rest)*) + } + }; + + (then $b:block) => { + $b + }; +} + +#[allow(dead_code)] +fn main() { + let x = String::new(); + + // Ok, reference to a String. + let _: &String = match Some(x.clone()) { + Some(ref x) => x, + None => return, + }; + + // Ok, reference to a &mut String + let _: &&mut String = match Some(&mut x.clone()) { + Some(ref x) => x, + None => return, + }; + + // Ok, the pattern is from a macro + let _: &String = match Some(&x) { + m3!(x) => x, + None => return, + }; + + // Err, reference to a &String + let _: &String = match Some(&x) { + Some(ref x) => x, + None => return, + }; + + // Err, reference to a &String. + let _: &String = match Some(&x) { + Some(ref x) => *x, + None => return, + }; + + // Err, reference to a &String + let _: &String = match Some(&x) { + Some(ref x) => { + f1(x); + f1(*x); + x + }, + None => return, + }; + + // Err, reference to a &String + match Some(&x) { + Some(ref x) => m1!(x), + None => return, + }; + + // Err, reference to a &String + let _ = |&ref x: &&String| { + let _: &String = x; + }; + + // Err, reference to a &String + let (ref y,) = (&x,); + let _: &String = *y; + + let y = &&x; + // Ok, different y + let _: &String = *y; + + let x = (0, 0); + // Err, reference to a &u32. Don't suggest adding a reference to the field access. + let _: u32 = match Some(&x) { + Some(ref x) => x.0, + None => return, + }; + + enum E { + A(&'static u32), + B(&'static u32), + } + // Err, reference to &u32. + let _: &u32 = match E::A(&0) { + E::A(ref x) | E::B(ref x) => *x, + }; + + // Err, reference to &String. + if_chain! { + if true; + if let Some(ref x) = Some(&String::new()); + then { + f1(x); + } + } +} + +// Err, reference to a &String +fn f2<'a>(&ref x: &&'a String) -> &'a String { + let _: &String = x; + *x +} + +trait T1 { + // Err, reference to a &String + fn f(&ref x: &&String) { + let _: &String = x; + } +} + +struct S; +impl T1 for S { + // Err, reference to a &String + fn f(&ref x: &&String) { + let _: &String = *x; + } +} + +// Ok - used to error due to rustc bug +#[allow(dead_code)] +#[derive(Debug)] +enum Foo<'a> { + Str(&'a str), +} diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr new file mode 100644 index 00000000000..32913d59f7a --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr @@ -0,0 +1,112 @@ +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:60:14 + | +LL | Some(ref x) => x, + | ^^^^^ help: try this: `x` + | + = note: `-D clippy::needless-borrow` implied by `-D warnings` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:66:14 + | +LL | Some(ref x) => *x, + | ^^^^^ + | +help: try this + | +LL | Some(x) => x, + | ^ ^ + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:72:14 + | +LL | Some(ref x) => { + | ^^^^^ + | +help: try this + | +LL | Some(x) => { +LL | f1(x); +LL | f1(x); + | + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:82:14 + | +LL | Some(ref x) => m1!(x), + | ^^^^^ help: try this: `x` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:87:15 + | +LL | let _ = |&ref x: &&String| { + | ^^^^^ help: try this: `x` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:92:10 + | +LL | let (ref y,) = (&x,); + | ^^^^^ + | +help: try this + | +LL | let (y,) = (&x,); +LL | let _: &String = y; + | + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:102:14 + | +LL | Some(ref x) => x.0, + | ^^^^^ help: try this: `x` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:112:14 + | +LL | E::A(ref x) | E::B(ref x) => *x, + | ^^^^^ ^^^^^ + | +help: try this + | +LL | E::A(x) | E::B(x) => x, + | ^ ^ ^ + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:118:21 + | +LL | if let Some(ref x) = Some(&String::new()); + | ^^^^^ help: try this: `x` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:126:12 + | +LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { + | ^^^^^ + | +help: try this + | +LL | fn f2<'a>(&x: &&'a String) -> &'a String { +LL | let _: &String = x; +LL | x + | + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:133:11 + | +LL | fn f(&ref x: &&String) { + | ^^^^^ help: try this: `x` + +error: this pattern creates a reference to a reference + --> $DIR/needless_borrow_pat.rs:141:11 + | +LL | fn f(&ref x: &&String) { + | ^^^^^ + | +help: try this + | +LL | fn f(&x: &&String) { +LL | let _: &String = x; + | + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs index 2458bf1e490..2c94235b8f5 100644 --- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs +++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs @@ -1,4 +1,4 @@ -use std::collections::{BinaryHeap, HashMap, LinkedList, VecDeque}; +use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; fn main() { let sample = [1; 5]; @@ -75,3 +75,9 @@ mod issue7110 { buffer.len() } } + +fn allow_test() { + #[allow(clippy::needless_collect)] + let v = [1].iter().collect::<Vec<_>>(); + v.into_iter().collect::<HashSet<_>>(); +} diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs index 8fbfcb79860..7ec845adfaa 100644 --- a/src/tools/clippy/tests/ui/no_effect.rs +++ b/src/tools/clippy/tests/ui/no_effect.rs @@ -91,6 +91,9 @@ fn main() { let s: String = "foo".into(); FooString { s: s }; + #[allow(clippy::no_effect)] + 0; + // Do not warn get_number(); unsafe { unsafe_fn() }; diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs new file mode 100644 index 00000000000..c7235e1c221 --- /dev/null +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs @@ -0,0 +1,76 @@ +// edition:2018 +// FIXME: run-rustfix waiting on multi-span suggestions + +#![warn(clippy::ref_binding_to_reference)] +#![allow(clippy::needless_borrowed_reference)] + +fn f1(_: &str) {} +macro_rules! m2 { + ($e:expr) => { + f1(*$e); + }; +} +macro_rules! m3 { + ($i:ident) => { + Some(ref $i) + }; +} + +#[allow(dead_code)] +fn main() { + let x = String::new(); + + // Ok, the pattern is from a macro + let _: &&String = match Some(&x) { + m3!(x) => x, + None => return, + }; + + // Err, reference to a &String + let _: &&String = match Some(&x) { + Some(ref x) => x, + None => return, + }; + + // Err, reference to a &String + let _: &&String = match Some(&x) { + Some(ref x) => { + f1(x); + f1(*x); + x + }, + None => return, + }; + + // Err, reference to a &String + match Some(&x) { + Some(ref x) => m2!(x), + None => return, + } + + // Err, reference to a &String + let _ = |&ref x: &&String| { + let _: &&String = x; + }; +} + +// Err, reference to a &String +fn f2<'a>(&ref x: &&'a String) -> &'a String { + let _: &&String = x; + *x +} + +trait T1 { + // Err, reference to a &String + fn f(&ref x: &&String) { + let _: &&String = x; + } +} + +struct S; +impl T1 for S { + // Err, reference to a &String + fn f(&ref x: &&String) { + let _: &&String = x; + } +} diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr new file mode 100644 index 00000000000..00aeff4fefa --- /dev/null +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr @@ -0,0 +1,88 @@ +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:31:14 + | +LL | Some(ref x) => x, + | ^^^^^ + | + = note: `-D clippy::ref-binding-to-reference` implied by `-D warnings` +help: try this + | +LL | Some(x) => &x, + | ^ ^^ + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:37:14 + | +LL | Some(ref x) => { + | ^^^^^ + | +help: try this + | +LL | Some(x) => { +LL | f1(x); +LL | f1(x); +LL | &x + | + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:47:14 + | +LL | Some(ref x) => m2!(x), + | ^^^^^ + | +help: try this + | +LL | Some(x) => m2!(&x), + | ^ ^^ + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:52:15 + | +LL | let _ = |&ref x: &&String| { + | ^^^^^ + | +help: try this + | +LL | let _ = |&x: &&String| { +LL | let _: &&String = &x; + | + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:58:12 + | +LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { + | ^^^^^ + | +help: try this + | +LL | fn f2<'a>(&x: &&'a String) -> &'a String { +LL | let _: &&String = &x; +LL | x + | + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:65:11 + | +LL | fn f(&ref x: &&String) { + | ^^^^^ + | +help: try this + | +LL | fn f(&x: &&String) { +LL | let _: &&String = &x; + | + +error: this pattern creates a reference to a reference + --> $DIR/ref_binding_to_reference.rs:73:11 + | +LL | fn f(&ref x: &&String) { + | ^^^^^ + | +help: try this + | +LL | fn f(&x: &&String) { +LL | let _: &&String = &x; + | + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui/similar_names.rs b/src/tools/clippy/tests/ui/similar_names.rs index 5981980988b..2b1bc1f4859 100644 --- a/src/tools/clippy/tests/ui/similar_names.rs +++ b/src/tools/clippy/tests/ui/similar_names.rs @@ -72,6 +72,10 @@ fn main() { let rx1: i32; let tx_cake: i32; let rx_cake: i32; + + // names often used in win32 code (for example WindowProc) + let wparam: i32; + let lparam: i32; } fn foo() { diff --git a/src/tools/clippy/tests/ui/similar_names.stderr b/src/tools/clippy/tests/ui/similar_names.stderr index 0256f126a94..a7eb2be0778 100644 --- a/src/tools/clippy/tests/ui/similar_names.stderr +++ b/src/tools/clippy/tests/ui/similar_names.stderr @@ -92,13 +92,13 @@ LL | let parsee: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> $DIR/similar_names.rs:81:16 + --> $DIR/similar_names.rs:85:16 | LL | bpple: sprang, | ^^^^^^ | note: existing binding defined here - --> $DIR/similar_names.rs:80:16 + --> $DIR/similar_names.rs:84:16 | LL | apple: spring, | ^^^^^^ diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed index fcbe9af9f56..1abd2b7883d 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.fixed +++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed @@ -25,8 +25,8 @@ fn main() { x.rsplit('x'); x.split_terminator('x'); x.rsplit_terminator('x'); - x.splitn(0, 'x'); - x.rsplitn(0, 'x'); + x.splitn(2, 'x'); + x.rsplitn(2, 'x'); x.matches('x'); x.rmatches('x'); x.match_indices('x'); diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs index b8bc20f4070..e662bf34be2 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.rs +++ b/src/tools/clippy/tests/ui/single_char_pattern.rs @@ -25,8 +25,8 @@ fn main() { x.rsplit("x"); x.split_terminator("x"); x.rsplit_terminator("x"); - x.splitn(0, "x"); - x.rsplitn(0, "x"); + x.splitn(2, "x"); + x.rsplitn(2, "x"); x.matches("x"); x.rmatches("x"); x.match_indices("x"); diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr index 6d94d8a34e3..22d4b2d460f 100644 --- a/src/tools/clippy/tests/ui/single_char_pattern.stderr +++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr @@ -75,13 +75,13 @@ LL | x.rsplit_terminator("x"); error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:28:17 | -LL | x.splitn(0, "x"); +LL | x.splitn(2, "x"); | ^^^ help: try using a `char` instead: `'x'` error: single-character string constant used as pattern --> $DIR/single_char_pattern.rs:29:18 | -LL | x.rsplitn(0, "x"); +LL | x.rsplitn(2, "x"); | ^^^ help: try using a `char` instead: `'x'` error: single-character string constant used as pattern diff --git a/src/tools/clippy/tests/ui/suspicious_splitn.rs b/src/tools/clippy/tests/ui/suspicious_splitn.rs new file mode 100644 index 00000000000..a21d94cf20b --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_splitn.rs @@ -0,0 +1,20 @@ +#![warn(clippy::suspicious_splitn)] + +fn main() { + let _ = "a,b,c".splitn(3, ','); + let _ = [0, 1, 2, 1, 3].splitn(3, |&x| x == 1); + let _ = "".splitn(0, ','); + let _ = [].splitn(0, |&x: &u32| x == 1); + + let _ = "a,b".splitn(0, ','); + let _ = "a,b".rsplitn(0, ','); + let _ = "a,b".splitn(1, ','); + let _ = [0, 1, 2].splitn(0, |&x| x == 1); + let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1); + let _ = [0, 1, 2].splitn(1, |&x| x == 1); + let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); + + const X: usize = 0; + let _ = "a,b".splitn(X + 1, ','); + let _ = "a,b".splitn(X, ','); +} diff --git a/src/tools/clippy/tests/ui/suspicious_splitn.stderr b/src/tools/clippy/tests/ui/suspicious_splitn.stderr new file mode 100644 index 00000000000..b6220ae2393 --- /dev/null +++ b/src/tools/clippy/tests/ui/suspicious_splitn.stderr @@ -0,0 +1,75 @@ +error: `splitn` called with `0` splits + --> $DIR/suspicious_splitn.rs:9:13 + | +LL | let _ = "a,b".splitn(0, ','); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::suspicious-splitn` implied by `-D warnings` + = note: the resulting iterator will always return `None` + +error: `rsplitn` called with `0` splits + --> $DIR/suspicious_splitn.rs:10:13 + | +LL | let _ = "a,b".rsplitn(0, ','); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return `None` + +error: `splitn` called with `1` split + --> $DIR/suspicious_splitn.rs:11:13 + | +LL | let _ = "a,b".splitn(1, ','); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return the entire string followed by `None` + +error: `splitn` called with `0` splits + --> $DIR/suspicious_splitn.rs:12:13 + | +LL | let _ = [0, 1, 2].splitn(0, |&x| x == 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return `None` + +error: `splitn_mut` called with `0` splits + --> $DIR/suspicious_splitn.rs:13:13 + | +LL | let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return `None` + +error: `splitn` called with `1` split + --> $DIR/suspicious_splitn.rs:14:13 + | +LL | let _ = [0, 1, 2].splitn(1, |&x| x == 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return the entire slice followed by `None` + +error: `rsplitn_mut` called with `1` split + --> $DIR/suspicious_splitn.rs:15:13 + | +LL | let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return the entire slice followed by `None` + +error: `splitn` called with `1` split + --> $DIR/suspicious_splitn.rs:18:13 + | +LL | let _ = "a,b".splitn(X + 1, ','); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return the entire string followed by `None` + +error: `splitn` called with `0` splits + --> $DIR/suspicious_splitn.rs:19:13 + | +LL | let _ = "a,b".splitn(X, ','); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the resulting iterator will always return `None` + +error: aborting due to 9 previous errors + diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr index ccc3cdb2b74..2b0005bbff1 100644 --- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr @@ -89,12 +89,6 @@ LL | fn trait_method(&self, _foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:80:37 - | -LL | fn trait_method2(&self, _color: &Color); - | ^^^^^^ help: consider passing by value instead: `Color` - -error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) --> $DIR/trivially_copy_pass_by_ref.rs:108:21 | LL | fn foo_never(x: &i32) { @@ -106,5 +100,5 @@ error: this argument (N byte) is passed by reference, but would be more efficien LL | fn foo(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.rs b/src/tools/clippy/tests/ui/unnecessary_wraps.rs index 54f22e3ee6a..63648ef5826 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.rs +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.rs @@ -65,7 +65,7 @@ fn func10() -> Option<()> { unimplemented!() } -struct A; +pub struct A; impl A { // should not be linted diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed index 3c422cc4fee..f0c2ba7ccdf 100644 --- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed +++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed @@ -1,10 +1,11 @@ // run-rustfix +// aux-build:proc_macro_derive.rs #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] #[macro_use] -extern crate clippy_mini_macro_test; +extern crate proc_macro_derive; // Test for proc-macro attribute #[derive(ClippyMiniMacroTest)] diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs index 09608661e0e..f44880b4147 100644 --- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs +++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs @@ -1,10 +1,11 @@ // run-rustfix +// aux-build:proc_macro_derive.rs #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] #[macro_use] -extern crate clippy_mini_macro_test; +extern crate proc_macro_derive; // Test for proc-macro attribute #[derive(ClippyMiniMacroTest)] diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr index a0c0be7a9d1..ab2f75e0c56 100644 --- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr +++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr @@ -1,5 +1,5 @@ error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:23:18 + --> $DIR/unseparated_prefix_literals.rs:24:18 | LL | let _fail1 = 1234i32; | ^^^^^^^ help: add an underscore: `1234_i32` @@ -7,43 +7,43 @@ LL | let _fail1 = 1234i32; = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings` error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:24:18 + --> $DIR/unseparated_prefix_literals.rs:25:18 | LL | let _fail2 = 1234u32; | ^^^^^^^ help: add an underscore: `1234_u32` error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:25:18 + --> $DIR/unseparated_prefix_literals.rs:26:18 | LL | let _fail3 = 1234isize; | ^^^^^^^^^ help: add an underscore: `1234_isize` error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:26:18 + --> $DIR/unseparated_prefix_literals.rs:27:18 | LL | let _fail4 = 1234usize; | ^^^^^^^^^ help: add an underscore: `1234_usize` error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:27:18 + --> $DIR/unseparated_prefix_literals.rs:28:18 | LL | let _fail5 = 0x123isize; | ^^^^^^^^^^ help: add an underscore: `0x123_isize` error: float type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:31:19 + --> $DIR/unseparated_prefix_literals.rs:32:19 | LL | let _failf1 = 1.5f32; | ^^^^^^ help: add an underscore: `1.5_f32` error: float type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:32:19 + --> $DIR/unseparated_prefix_literals.rs:33:19 | LL | let _failf2 = 1f32; | ^^^^ help: add an underscore: `1_f32` error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:15:9 + --> $DIR/unseparated_prefix_literals.rs:16:9 | LL | 42usize | ^^^^^^^ help: add an underscore: `42_usize` @@ -54,7 +54,7 @@ LL | let _ = lit_from_macro!(); = note: this error originates in the macro `lit_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: integer type suffix should be separated by an underscore - --> $DIR/unseparated_prefix_literals.rs:40:16 + --> $DIR/unseparated_prefix_literals.rs:41:16 | LL | assert_eq!(4897u32, 32223); | ^^^^^^^ help: add an underscore: `4897_u32` diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.rs b/src/tools/clippy/tests/ui/wrong_self_convention.rs index cdfbdb8b0db..151dd0c27d5 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.rs +++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs @@ -1,6 +1,5 @@ // edition:2018 #![warn(clippy::wrong_self_convention)] -#![warn(clippy::wrong_pub_self_convention)] #![allow(dead_code)] fn main() {} diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr index 29f5ba82695..ce23317abf6 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:18:17 + --> $DIR/wrong_self_convention.rs:17:17 | LL | fn from_i32(self) {} | ^^^^ @@ -8,7 +8,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:24:21 + --> $DIR/wrong_self_convention.rs:23:21 | LL | pub fn from_i64(self) {} | ^^^^ @@ -16,7 +16,7 @@ LL | pub fn from_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/wrong_self_convention.rs:36:15 + --> $DIR/wrong_self_convention.rs:35:15 | LL | fn as_i32(self) {} | ^^^^ @@ -24,7 +24,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:38:17 + --> $DIR/wrong_self_convention.rs:37:17 | LL | fn into_i32(&self) {} | ^^^^^ @@ -32,7 +32,7 @@ LL | fn into_i32(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by reference or no `self` - --> $DIR/wrong_self_convention.rs:40:15 + --> $DIR/wrong_self_convention.rs:39:15 | LL | fn is_i32(self) {} | ^^^^ @@ -40,7 +40,7 @@ LL | fn is_i32(self) {} = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> $DIR/wrong_self_convention.rs:42:15 + --> $DIR/wrong_self_convention.rs:41:15 | LL | fn to_i32(self) {} | ^^^^ @@ -48,7 +48,7 @@ LL | fn to_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:44:17 + --> $DIR/wrong_self_convention.rs:43:17 | LL | fn from_i32(self) {} | ^^^^ @@ -56,7 +56,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/wrong_self_convention.rs:46:19 + --> $DIR/wrong_self_convention.rs:45:19 | LL | pub fn as_i64(self) {} | ^^^^ @@ -64,7 +64,7 @@ LL | pub fn as_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:47:21 + --> $DIR/wrong_self_convention.rs:46:21 | LL | pub fn into_i64(&self) {} | ^^^^^ @@ -72,7 +72,7 @@ LL | pub fn into_i64(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by reference or no `self` - --> $DIR/wrong_self_convention.rs:48:19 + --> $DIR/wrong_self_convention.rs:47:19 | LL | pub fn is_i64(self) {} | ^^^^ @@ -80,7 +80,7 @@ LL | pub fn is_i64(self) {} = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> $DIR/wrong_self_convention.rs:49:19 + --> $DIR/wrong_self_convention.rs:48:19 | LL | pub fn to_i64(self) {} | ^^^^ @@ -88,7 +88,7 @@ LL | pub fn to_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:50:21 + --> $DIR/wrong_self_convention.rs:49:21 | LL | pub fn from_i64(self) {} | ^^^^ @@ -96,7 +96,7 @@ LL | pub fn from_i64(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/wrong_self_convention.rs:95:19 + --> $DIR/wrong_self_convention.rs:94:19 | LL | fn as_i32(self) {} | ^^^^ @@ -104,7 +104,7 @@ LL | fn as_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:98:25 + --> $DIR/wrong_self_convention.rs:97:25 | LL | fn into_i32_ref(&self) {} | ^^^^^ @@ -112,7 +112,7 @@ LL | fn into_i32_ref(&self) {} = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by reference or no `self` - --> $DIR/wrong_self_convention.rs:100:19 + --> $DIR/wrong_self_convention.rs:99:19 | LL | fn is_i32(self) {} | ^^^^ @@ -120,7 +120,7 @@ LL | fn is_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:104:21 + --> $DIR/wrong_self_convention.rs:103:21 | LL | fn from_i32(self) {} | ^^^^ @@ -128,7 +128,7 @@ LL | fn from_i32(self) {} = help: consider choosing a less ambiguous name error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/wrong_self_convention.rs:119:19 + --> $DIR/wrong_self_convention.rs:118:19 | LL | fn as_i32(self); | ^^^^ @@ -136,7 +136,7 @@ LL | fn as_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:122:25 + --> $DIR/wrong_self_convention.rs:121:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -144,7 +144,7 @@ LL | fn into_i32_ref(&self); = help: consider choosing a less ambiguous name error: methods called `is_*` usually take `self` by reference or no `self` - --> $DIR/wrong_self_convention.rs:124:19 + --> $DIR/wrong_self_convention.rs:123:19 | LL | fn is_i32(self); | ^^^^ @@ -152,7 +152,7 @@ LL | fn is_i32(self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:128:21 + --> $DIR/wrong_self_convention.rs:127:21 | LL | fn from_i32(self); | ^^^^ @@ -160,7 +160,7 @@ LL | fn from_i32(self); = help: consider choosing a less ambiguous name error: methods called `into_*` usually take `self` by value - --> $DIR/wrong_self_convention.rs:146:25 + --> $DIR/wrong_self_convention.rs:145:25 | LL | fn into_i32_ref(&self); | ^^^^^ @@ -168,7 +168,7 @@ LL | fn into_i32_ref(&self); = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention.rs:152:21 + --> $DIR/wrong_self_convention.rs:151:21 | LL | fn from_i32(self); | ^^^^ @@ -176,7 +176,7 @@ LL | fn from_i32(self); = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value - --> $DIR/wrong_self_convention.rs:176:22 + --> $DIR/wrong_self_convention.rs:175:22 | LL | fn to_u64_v2(&self) -> u64 { | ^^^^^ @@ -184,7 +184,7 @@ LL | fn to_u64_v2(&self) -> u64 { = help: consider choosing a less ambiguous name error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference - --> $DIR/wrong_self_convention.rs:185:19 + --> $DIR/wrong_self_convention.rs:184:19 | LL | fn to_u64(self) -> u64 { | ^^^^ diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.rs b/src/tools/clippy/tests/ui/wrong_self_convention2.rs index 3a72174d03d..501bc1e6a85 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention2.rs +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.rs @@ -1,6 +1,5 @@ // edition:2018 #![warn(clippy::wrong_self_convention)] -#![warn(clippy::wrong_pub_self_convention)] #![allow(dead_code)] fn main() {} diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr index d2d74ce099e..0e0d066d656 100644 --- a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr +++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr @@ -1,5 +1,5 @@ error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention2.rs:56:29 + --> $DIR/wrong_self_convention2.rs:55:29 | LL | pub fn from_be_self(self) -> Self { | ^^^^ @@ -8,7 +8,7 @@ LL | pub fn from_be_self(self) -> Self { = help: consider choosing a less ambiguous name error: methods called `from_*` usually take no `self` - --> $DIR/wrong_self_convention2.rs:65:25 + --> $DIR/wrong_self_convention2.rs:64:25 | LL | fn from_be_self(self) -> Self; | ^^^^ diff --git a/src/tools/clippy/util/cov.sh b/src/tools/clippy/util/cov.sh deleted file mode 100755 index 3f9a6b06f72..00000000000 --- a/src/tools/clippy/util/cov.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/bash - -# This run `kcov` on Clippy. The coverage report will be at -# `./target/cov/index.html`. -# `compile-test` is special. `kcov` does not work directly on it so these files -# are compiled manually. - -tests=$(find tests/ -maxdepth 1 -name '*.rs' ! -name compile-test.rs -exec basename {} .rs \;) -tmpdir=$(mktemp -d) - -cargo test --no-run --verbose - -for t in $tests; do - kcov \ - --verify \ - --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \ - "$tmpdir/$t" \ - cargo test --test "$t" -done - -for t in ./tests/compile-fail/*.rs; do - kcov \ - --verify \ - --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \ - "$tmpdir/compile-fail-$(basename "$t")" \ - cargo run -- -L target/debug -L target/debug/deps -Z no-trans "$t" -done - -for t in ./tests/run-pass/*.rs; do - kcov \ - --verify \ - --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \ - "$tmpdir/run-pass-$(basename "$t")" \ - cargo run -- -L target/debug -L target/debug/deps -Z no-trans "$t" -done - -kcov --verify --merge target/cov "$tmpdir"/* diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index a6efc4c9a6b..b5f1554dbe4 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -8,8 +8,7 @@ edition = "2018" jsonpath_lib = "0.2" getopts = "0.2" regex = "1.4" -lazy_static = "1.4" -shlex = "0.1" -serde = "1.0" +shlex = "1.0" serde_json = "1.0" fs-err = "2.5.0" +once_cell = "1.0" diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index 216890d59ad..b8ea10f3d22 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -1,5 +1,5 @@ use jsonpath_lib::select; -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use regex::{Regex, RegexBuilder}; use serde_json::Value; use std::borrow::Cow; @@ -94,19 +94,19 @@ impl fmt::Display for CommandKind { } } -lazy_static! { - static ref LINE_PATTERN: Regex = RegexBuilder::new( +static LINE_PATTERN: Lazy<Regex> = Lazy::new(|| { + RegexBuilder::new( r#" \s(?P<invalid>!?)@(?P<negated>!?) (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*) (?P<args>.*)$ - "# + "#, ) .ignore_whitespace(true) .unicode(true) .build() - .unwrap(); -} + .unwrap() +}); fn print_err(msg: &str, lineno: usize) { eprintln!("Invalid command: {} on line {}", msg, lineno) diff --git a/src/tools/linkchecker/linkcheck.sh b/src/tools/linkchecker/linkcheck.sh index b68053c76be..9eeebf444a4 100755 --- a/src/tools/linkchecker/linkcheck.sh +++ b/src/tools/linkchecker/linkcheck.sh @@ -85,11 +85,11 @@ fi if [ ! -e "linkchecker/main.rs" ] || [ "$iterative" = "0" ] then echo "Downloading linkchecker source..." + nightly_hash=$(rustc +nightly -Vv | grep commit-hash | cut -f2 -d" ") + url="https://raw.githubusercontent.com/rust-lang/rust" mkdir linkchecker - curl -o linkchecker/Cargo.toml \ - https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/Cargo.toml - curl -o linkchecker/main.rs \ - https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/main.rs + curl -o linkchecker/Cargo.toml ${url}/${nightly_hash}/src/tools/linkchecker/Cargo.toml + curl -o linkchecker/main.rs ${url}/${nightly_hash}/src/tools/linkchecker/main.rs fi echo "Building book \"$book_name\"..." @@ -106,7 +106,7 @@ else check_path="linkcheck/$book_name" fi echo "Running linkchecker on \"$check_path\"..." -cargo run --manifest-path=linkchecker/Cargo.toml -- "$check_path" +cargo run --release --manifest-path=linkchecker/Cargo.toml -- "$check_path" if [ "$iterative" = "0" ] then diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 076b3653583..47960c3f6cc 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -463,7 +463,7 @@ fn maybe_redirect(source: &str) -> Option<String> { const REDIRECT: &str = "<p>Redirecting to <a href="; let mut lines = source.lines(); - let redirect_line = lines.nth(6)?; + let redirect_line = lines.nth(7)?; redirect_line.find(REDIRECT).map(|i| { let rest = &redirect_line[(i + REDIRECT.len() + 1)..]; diff --git a/src/tools/miri b/src/tools/miri -Subproject 453affaaa1762a065d2857970b8333017211208 +Subproject 5dde0fe6de2941c9ef16bc1e9d91ecf20ac5ee8 diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index 298fc7519fa..c55e014e834 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -63,6 +63,13 @@ async function main(argv) { // This is more convenient that setting fields one by one. options.parseArguments([ "--no-screenshot", + // This option shows what puppeteer "code" is run + // "--debug", + // This option disable the headless mode, allowing you to see what's going on. + // "--no-headless", + // The text isn't rendered by default because of a lot of small differences + // between hosts. + // "--show-text", "--variable", "DOC_PATH", opts["doc_folder"], ]); } catch (error) { diff --git a/triagebot.toml b/triagebot.toml index 8b6157cd4aa..c97f63f1cfd 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -79,7 +79,7 @@ trigger_labels = [ "regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly", - "I-unsound 💥", + "I-unsound", ] exclude_labels = [ "P-*", |
