diff options
763 files changed, 11183 insertions, 5169 deletions
diff --git a/.mailmap b/.mailmap index 8cb74824d93..5d9bc173364 100644 --- a/.mailmap +++ b/.mailmap @@ -72,6 +72,7 @@ Daniel Ramos <dan@daramos.com> David Klein <david.klein@baesystemsdetica.com> David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au> David Ross <daboross@daboross.net> +Deadbeef <ent3rm4n@gmail.com> <fee1-dead-beef@protonmail.com> Derek Chiang <derekchiang93@gmail.com> Derek Chiang (Enchi Jiang) <derekchiang93@gmail.com> Diggory Hardy <diggory.hardy@gmail.com> Diggory Hardy <github@dhardy.name> Donough Liu <ldm2993593805@163.com> <donoughliu@gmail.com> @@ -290,6 +291,7 @@ Xuefeng Wu <benewu@gmail.com> XuefengWu <benewu@gmail.com> York Xiang <bombless@126.com> Youngsoo Son <ysson83@gmail.com> <ysoo.son@samsung.com> Yuki Okushi <jtitor@2k36.org> <huyuumi.dev@gmail.com> +Yuki Okushi <jtitor@2k36.org> <yuki.okushi@huawei.com> Zach Pomerantz <zmp@umich.edu> Zack Corr <zack@z0w0.me> <zackcorr95@gmail.com> Zack Slayton <zack.slayton@gmail.com> diff --git a/Cargo.lock b/Cargo.lock index 65ad130d559..f8f13315794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,7 +180,7 @@ dependencies = [ "merge", "num_cpus", "once_cell", - "opener 0.5.0", + "opener", "pretty_assertions", "serde", "serde_json", @@ -290,7 +290,7 @@ dependencies = [ "log", "memchr", "num_cpus", - "opener 0.5.0", + "opener", "openssl", "percent-encoding 2.1.0", "pretty_env_logger", @@ -398,7 +398,7 @@ dependencies = [ "jobserver", "libc", "log", - "miow 0.3.6", + "miow 0.3.7", "same-file", "shell-escape", "tempfile", @@ -420,17 +420,6 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35" -dependencies = [ - "semver 0.10.0", - "serde", - "serde_json", -] - -[[package]] -name = "cargo_metadata" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" @@ -553,7 +542,7 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.54" +version = "0.1.55" dependencies = [ "cargo_metadata 0.12.0", "clippy_lints", @@ -578,7 +567,7 @@ dependencies = [ "bytecount", "clap", "itertools 0.9.0", - "opener 0.4.1", + "opener", "regex", "shell-escape", "walkdir", @@ -586,7 +575,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.54" +version = "0.1.55" dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", @@ -601,12 +590,13 @@ dependencies = [ "serde_json", "toml", "unicode-normalization", + "unicode-script", "url 2.2.2", ] [[package]] name = "clippy_utils" -version = "0.1.54" +version = "0.1.55" dependencies = [ "if_chain", "itertools 0.9.0", @@ -674,7 +664,7 @@ dependencies = [ "glob", "lazy_static", "libc", - "miow 0.3.6", + "miow 0.3.7", "regex", "rustfix 0.6.0", "serde", @@ -698,7 +688,7 @@ dependencies = [ "lazy_static", "libc", "log", - "miow 0.3.6", + "miow 0.3.7", "regex", "rustfix 0.5.1", "serde", @@ -866,24 +856,24 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.36" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bac9f84ca0977c4d9b8db998689de55b9e976656a6bc87fada2ca710d504c7" +checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", - "socket2 0.4.0", + "socket2", "winapi 0.3.9", ] [[package]] name = "curl-sys" -version = "0.4.42+curl-7.76.0" +version = "0.4.44+curl-7.77.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4636d8d6109c842707018a104051436bffb8991ea20b2d1293db70b6e0ee4c7c" +checksum = "4b6d85e9322b193f117c966e79c2d6929ec08c02f339f950044aba12e20bbaf1" dependencies = [ "cc", "libc", @@ -1522,12 +1512,6 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" - -[[package]] -name = "hashbrown" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "362385356d610bd1e5a408ddf8d022041774b683f345a1d2cfcb4f60f8ae2db5" @@ -1579,6 +1563,13 @@ dependencies = [ ] [[package]] +name = "html-checker" +version = "0.1.0" +dependencies = [ + "walkdir", +] + +[[package]] name = "html5ever" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1669,12 +1660,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown 0.9.1", + "hashbrown", ] [[package]] @@ -2261,7 +2252,7 @@ checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" dependencies = [ "log", "mio", - "miow 0.3.6", + "miow 0.3.7", "winapi 0.3.9", ] @@ -2290,11 +2281,10 @@ dependencies = [ [[package]] name = "miow" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "socket2 0.3.19", "winapi 0.3.9", ] @@ -2414,15 +2404,6 @@ dependencies = [ [[package]] name = "opener" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "opener" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" @@ -2433,9 +2414,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.33" +version = "0.10.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" +checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2462,9 +2443,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.61" +version = "0.9.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" +checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" dependencies = [ "autocfg", "cc", @@ -2532,7 +2513,7 @@ dependencies = [ "libc", "log", "mio-named-pipes", - "miow 0.3.6", + "miow 0.3.7", "rand 0.7.3", "tokio", "winapi 0.3.9", @@ -3713,10 +3694,8 @@ dependencies = [ "rustc_codegen_ssa", "rustc_data_structures", "rustc_errors", - "rustc_feature", "rustc_fs_util", "rustc_hir", - "rustc_incremental", "rustc_index", "rustc_llvm", "rustc_metadata", @@ -3768,7 +3747,6 @@ dependencies = [ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", @@ -3811,7 +3789,6 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_mir", - "rustc_mir_build", "rustc_parse", "rustc_plugin_impl", "rustc_save_analysis", @@ -3819,7 +3796,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_typeck", "tracing", "tracing-subscriber", "tracing-tree", @@ -3945,10 +3921,8 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ - "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_graphviz", "rustc_hir", "rustc_index", "rustc_macros", @@ -3980,7 +3954,6 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_incremental", - "rustc_index", "rustc_lint", "rustc_metadata", "rustc_middle", @@ -4048,7 +4021,6 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "tracing", ] [[package]] @@ -4092,7 +4064,6 @@ dependencies = [ "rustc_target", "smallvec", "snap", - "stable_deref_trait", "tracing", "winapi 0.3.9", ] @@ -4103,7 +4074,6 @@ version = "0.0.0" dependencies = [ "bitflags", "chalk-ir", - "measureme", "polonius-engine", "rustc-rayon-core", "rustc_apfloat", @@ -4193,7 +4163,6 @@ dependencies = [ "rustc_lexer", "rustc_session", "rustc_span", - "smallvec", "tracing", "unicode-normalization", ] @@ -4223,7 +4192,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", "tracing", ] @@ -4263,20 +4231,13 @@ version = "0.0.0" dependencies = [ "measureme", "rustc-rayon-core", - "rustc_ast", - "rustc_attr", "rustc_data_structures", "rustc_errors", - "rustc_feature", "rustc_hir", - "rustc_index", - "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_serialize", - "rustc_session", "rustc_span", - "rustc_target", "tracing", ] @@ -4354,7 +4315,6 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ - "bitflags", "getopts", "num_cpus", "rustc_ast", @@ -4394,7 +4354,6 @@ version = "0.0.0" dependencies = [ "punycode", "rustc-demangle", - "rustc_ast", "rustc_data_structures", "rustc_hir", "rustc_middle", @@ -4712,16 +4671,6 @@ dependencies = [ [[package]] name = "semver" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190" -dependencies = [ - "semver-parser 0.7.0", - "serde", -] - -[[package]] -name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" @@ -4910,17 +4859,6 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "socket2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" @@ -4959,7 +4897,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.11.0", + "hashbrown", "hermit-abi", "libc", "miniz_oxide", @@ -5259,7 +5197,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "cargo_metadata 0.11.1", + "cargo_metadata 0.12.0", "crossbeam-utils 0.8.3", "lazy_static", "regex", @@ -5518,9 +5456,9 @@ dependencies = [ [[package]] name = "unicode-script" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79bf4d5fc96546fdb73f9827097810bbda93b11a6770ff3a54e1f445d4135787" +checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9" [[package]] name = "unicode-security" diff --git a/Cargo.toml b/Cargo.toml index 327afe35c2f..4c00a7dc99e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ members = [ "src/tools/unicode-table-generator", "src/tools/expand-yaml-anchors", "src/tools/jsondocck", + "src/tools/html-checker", ] exclude = [ diff --git a/README.md b/README.md index cf75f4184a1..32fab9fc25d 100644 --- a/README.md +++ b/README.md @@ -272,15 +272,14 @@ See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and ## Trademark -The Rust programming language is an open source, community project governed -by a core team. It is also sponsored by the Mozilla Foundation (“Mozilla”), -which owns and protects the Rust and Cargo trademarks and logos -(the “Rust Trademarks”). +[The Rust Foundation][rust-foundation] owns and protects the Rust and Cargo +trademarks and logos (the “Rust Trademarks”). If you want to use these names or brands, please read the [media guide][media-guide]. Third-party logos may be subject to third-party copyrights and trademarks. See [Licenses][policies-licenses] for details. +[rust-foundation]: https://foundation.rust-lang.org/ [media-guide]: https://www.rust-lang.org/policies/media-guide [policies-licenses]: https://www.rust-lang.org/policies/licenses diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index 290f6006de0..c0a837985fd 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub enum EntryPointType { None, MainNamed, diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 7c79b4aab3c..3207aee6d2a 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -10,7 +10,6 @@ )] #![feature(box_syntax)] #![feature(box_patterns)] -#![cfg_attr(bootstrap, feature(const_fn_unsize))] #![feature(const_fn_transmute)] #![feature(crate_visibility_modifier)] #![feature(iter_zip)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9592c1d2fab..7a4e39376a8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -296,7 +296,7 @@ pub fn lower_crate<'a, 'hir>( resolver: &'a mut dyn ResolverAstLowering, nt_to_tokenstream: NtToTokenstream, arena: &'hir Arena<'hir>, -) -> hir::Crate<'hir> { +) -> &'hir hir::Crate<'hir> { let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); LoweringContext { @@ -403,7 +403,7 @@ enum AnonymousLifetimeMode { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> { + fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { /// Full-crate AST visitor that inserts into a fresh /// `LoweringContext` any information that may be /// needed from arbitrary locations in the crate, @@ -530,7 +530,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - hir::Crate { + let krate = hir::Crate { item: module, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), @@ -545,7 +545,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { proc_macros, trait_map, attrs: self.attrs, - } + }; + self.arena.alloc(krate) } fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 488ff6e1349..a8a0bb52a24 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -233,7 +233,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, pub(crate) pointer_type: Type, // Cached from module - pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>, + pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer>, pub(crate) constants_cx: ConstantCx, pub(crate) instance: Instance<'tcx>, diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 3ba12c4e96d..a87b3703949 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -249,7 +249,7 @@ pub(crate) fn codegen_const_value<'tcx>( } } -fn pointer_for_allocation<'tcx>( +pub(crate) fn pointer_for_allocation<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, alloc: &'tcx Allocation, ) -> crate::pointer::Pointer { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 6aadaf8a7ca..b817bf4aff7 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -98,7 +98,7 @@ mod prelude { pub(crate) use cranelift_codegen::isa::{self, CallConv}; pub(crate) use cranelift_codegen::Context; pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; - pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module}; + pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module}; pub(crate) use crate::abi::*; pub(crate) use crate::base::{codegen_operand, codegen_place}; diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 042583cd572..b9d379c6117 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -31,9 +31,7 @@ pub(crate) fn unsized_info<'tcx>( // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::Dynamic(ref data, ..)) => { - crate::vtable::get_vtable(fx, fx.layout_of(source), data.principal()) - } + (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 4d1ee47b41e..12f7092d935 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -4,7 +4,7 @@ // FIXME dedup this logic between miri, cg_llvm and cg_clif use crate::prelude::*; -use ty::VtblEntry; +use super::constant::pointer_for_allocation; fn vtable_memflags() -> MemFlags { let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. @@ -66,105 +66,19 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( pub(crate) fn get_vtable<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - layout: TyAndLayout<'tcx>, + ty: Ty<'tcx>, trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, ) -> Value { - let data_id = if let Some(data_id) = fx.vtables.get(&(layout.ty, trait_ref)) { - *data_id + let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) { + *vtable_ptr } else { - let data_id = build_vtable(fx, layout, trait_ref); - fx.vtables.insert((layout.ty, trait_ref), data_id); - data_id - }; - - let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) -} - -fn build_vtable<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - layout: TyAndLayout<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, -) -> DataId { - let tcx = fx.tcx; - let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; + let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); + let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory(); + let vtable_ptr = pointer_for_allocation(fx, vtable_allocation); - let drop_in_place_fn = import_function( - tcx, - fx.module, - Instance::resolve_drop_in_place(tcx, layout.ty).polymorphize(fx.tcx), - ); - - let vtable_entries = if let Some(trait_ref) = trait_ref { - tcx.vtable_entries(trait_ref.with_self_ty(tcx, layout.ty)) - } else { - ty::COMMON_VTABLE_ENTRIES + fx.vtables.insert((ty, trait_ref), vtable_ptr); + vtable_ptr }; - let mut data_ctx = DataContext::new(); - let mut data = ::std::iter::repeat(0u8) - .take(vtable_entries.len() * usize_size) - .collect::<Vec<u8>>() - .into_boxed_slice(); - - for (idx, entry) in vtable_entries.iter().enumerate() { - match entry { - VtblEntry::MetadataSize => { - write_usize(fx.tcx, &mut data, idx, layout.size.bytes()); - } - VtblEntry::MetadataAlign => { - write_usize(fx.tcx, &mut data, idx, layout.align.abi.bytes()); - } - VtblEntry::MetadataDropInPlace | VtblEntry::Vacant | VtblEntry::Method(_, _) => {} - } - } - data_ctx.define(data); - - for (idx, entry) in vtable_entries.iter().enumerate() { - match entry { - VtblEntry::MetadataDropInPlace => { - let func_ref = fx.module.declare_func_in_data(drop_in_place_fn, &mut data_ctx); - data_ctx.write_function_addr((idx * usize_size) as u32, func_ref); - } - VtblEntry::Method(def_id, substs) => { - let func_id = import_function( - tcx, - fx.module, - Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), *def_id, substs) - .unwrap() - .polymorphize(fx.tcx), - ); - let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx); - data_ctx.write_function_addr((idx * usize_size) as u32, func_ref); - } - VtblEntry::MetadataSize | VtblEntry::MetadataAlign | VtblEntry::Vacant => {} - } - } - - data_ctx.set_align(fx.tcx.data_layout.pointer_align.pref.bytes()); - - let data_id = fx.module.declare_anonymous_data(false, false).unwrap(); - - fx.module.define_data(data_id, &data_ctx).unwrap(); - - data_id -} - -fn write_usize(tcx: TyCtxt<'_>, buf: &mut [u8], idx: usize, num: u64) { - let pointer_size = - tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.usize)).unwrap().size.bytes() as usize; - let target = &mut buf[idx * pointer_size..(idx + 1) * pointer_size]; - - match tcx.data_layout.endian { - rustc_target::abi::Endian::Little => match pointer_size { - 4 => target.copy_from_slice(&(num as u32).to_le_bytes()), - 8 => target.copy_from_slice(&(num as u64).to_le_bytes()), - _ => todo!("pointer size {} is not yet supported", pointer_size), - }, - rustc_target::abi::Endian::Big => match pointer_size { - 4 => target.copy_from_slice(&(num as u32).to_be_bytes()), - 8 => target.copy_from_slice(&(num as u64).to_be_bytes()), - _ => todo!("pointer size {} is not yet supported", pointer_size), - }, - } + vtable_ptr.get_addr(fx) } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index d0eb6913acc..d78af9d413e 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -21,10 +21,8 @@ rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_feature = { path = "../rustc_feature" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } -rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_llvm = { path = "../rustc_llvm" } rustc_metadata = { path = "../rustc_metadata" } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 6a032b9be72..56b93f83466 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; use rustc_session::Session; use rustc_target::spec::abi::Abi; -use rustc_target::spec::{SanitizerSet, StackProbeType}; +use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -69,15 +69,25 @@ fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { - if cx.sess().must_not_eliminate_frame_pointers() { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("frame-pointer"), - cstr!("all"), - ); +pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let mut fp = cx.sess().target.frame_pointer; + // "mcount" function relies on stack pointer. + // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>. + if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true)) + { + fp = FramePointer::Always; } + let attr_value = match fp { + FramePointer::Always => cstr!("all"), + FramePointer::NonLeaf => cstr!("non-leaf"), + FramePointer::MayOmit => return, + }; + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("frame-pointer"), + attr_value, + ); } /// Tell LLVM what instrument function to insert. @@ -254,7 +264,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: } // FIXME: none of these three functions interact with source level attributes. - set_frame_pointer_elimination(cx, llfn); + set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 58af9d4cd04..df5ad8ecc27 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -282,6 +282,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } + fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value { + const_alloc_to_llvm(self, alloc) + } + fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 7415a570453..f662887abf8 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -410,8 +410,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.used_statics } - fn set_frame_pointer_elimination(&self, llfn: &'ll Value) { - attributes::set_frame_pointer_elimination(self, llfn) + fn set_frame_pointer_type(&self, llfn: &'ll Value) { + attributes::set_frame_pointer_type(self, llfn) } fn apply_target_cpu_attr(&self, llfn: &'ll Value) { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e70664e64d..0e42931b29a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -471,21 +471,28 @@ fn trait_pointer_metadata( // type is assigned the correct name, size, namespace, and source location. // However, it does not describe the trait's methods. - let containing_scope = match trait_type.kind() { - ty::Dynamic(ref data, ..) => { - data.principal_def_id().map(|did| get_namespace_for_item(cx, did)) - } - _ => { - bug!( - "debuginfo: unexpected trait-object type in \ - trait_pointer_metadata(): {:?}", - trait_type - ); - } - }; + let (containing_scope, trait_type_name) = match trait_object_type { + Some(trait_object_type) => match trait_object_type.kind() { + ty::Adt(def, _) => ( + Some(get_namespace_for_item(cx, def.did)), + compute_debuginfo_type_name(cx.tcx, trait_object_type, false), + ), + ty::RawPtr(_) | ty::Ref(..) => { + (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true)) + } + _ => { + bug!( + "debuginfo: unexpected trait-object type in \ + trait_pointer_metadata(): {:?}", + trait_object_type + ); + } + }, - let trait_object_type = trait_object_type.unwrap_or(trait_type); - let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false); + // No object type, use the trait type directly (no scope here since the type + // will be wrapped in the dyn$ synthetic type). + None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)), + }; let file_metadata = unknown_file_metadata(cx); @@ -525,7 +532,7 @@ fn trait_pointer_metadata( composite_type_metadata( cx, - trait_object_type, + trait_object_type.unwrap_or(trait_type), &trait_type_name[..], unique_type_id, member_descriptions, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2b99a2ebad9..8375d4c7ca5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,6 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_metadata, TypeMap}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::type_names::compute_debuginfo_type_name; use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; @@ -311,10 +310,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) }; - // Find the enclosing function, in case this is a closure. - let def_key = self.tcx().def_key(def_id); - let mut name = def_key.disambiguated_data.data.to_string(); + let mut name = String::new(); + type_names::push_item_name(self.tcx(), def_id, false, &mut name); + // Find the enclosing function, in case this is a closure. let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id); // Get_template_parameters() will append a `<...>` clause to the function @@ -428,24 +427,16 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { substs: SubstsRef<'tcx>, name_to_append_suffix_to: &mut String, ) -> &'ll DIArray { + type_names::push_generic_params( + cx.tcx, + cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), + name_to_append_suffix_to, + ); + if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } - name_to_append_suffix_to.push('<'); - for (i, actual_type) in substs.types().enumerate() { - if i != 0 { - name_to_append_suffix_to.push(','); - } - - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type); - // Add actual type name to <...> clause of function name - let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true); - name_to_append_suffix_to.push_str(&actual_type_name[..]); - } - name_to_append_suffix_to.push('>'); - // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 9945d4f4282..1cbf5386996 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -1,13 +1,13 @@ // Namespace Handling. use super::utils::{debug_context, DIB}; +use rustc_codegen_ssa::debuginfo::type_names; use rustc_middle::ty::{self, Instance}; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; use rustc_hir::def_id::DefId; -use rustc_hir::definitions::DefPathData; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { .parent .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent })); - let crate_name_as_str; - let name_to_string; - let namespace_name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => { - crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str(); - &*crate_name_as_str - } - data => { - name_to_string = data.to_string(); - &*name_to_string - } + let namespace_name_string = { + let mut output = String::new(); + type_names::push_item_name(cx.tcx, def_id, false, &mut output); + output }; let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(cx), parent_scope, - namespace_name.as_ptr().cast(), - namespace_name.len(), + namespace_name_string.as_ptr().cast(), + namespace_name_string.len(), false, // ExportSymbols (only relevant for C++ anonymous namespaces) ) }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 22d513d66d1..1fb201eda6b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -674,7 +674,7 @@ fn gen_fn<'ll, 'tcx>( ) -> &'ll Value { let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); - cx.set_frame_pointer_elimination(llfn); + cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 776cb2ee99b..fc890f23853 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,7 +8,6 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6c9ec9e7b0d..d47624da79a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -912,14 +912,23 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.struct_err(&format!( + let escaped_output = escape_stdout_stderr_string(&output); + let mut err = sess.struct_err(&format!( "linking with `{}` failed: {}", linker_path.display(), prog.status - )) - .note(&format!("{:?}", &cmd)) - .note(&escape_stdout_stderr_string(&output)) - .emit(); + )); + err.note(&format!("{:?}", &cmd)).note(&escaped_output); + if escaped_output.contains("undefined reference to") { + err.help( + "some `extern` functions couldn't be found; some native libraries may \ + need to be installed or have their path specified", + ); + err.note("use the `-l` flag to specify native libraries to link"); + err.note("use the `cargo:rustc-link-lib` directive to specify the native \ + libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)"); + } + err.emit(); // If MSVC's `link.exe` was expected but the return code // is not a Microsoft LNK error then suggest a way to fix or diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 8a035e62e2a..4ef21449d21 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -277,7 +277,7 @@ fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), ) -> DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> { - let cnums = tcx.all_crate_nums(()); + let cnums = tcx.crates(()); let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default(); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ff4e6409571..d27eb7da810 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -994,7 +994,7 @@ fn start_executing_work<B: ExtraBackendMethods>( } Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { exported_symbols.insert(cnum, copy_symbols(cnum)); } Some(Arc::new(exported_symbols)) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 31ae84f4ca1..ec1aa4fd58e 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -406,7 +406,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; // `main` should respect same config for frame pointer elimination as rest of code - cx.set_frame_pointer_elimination(llfn); + cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); let llbb = Bx::append_block(&cx, llfn, "top"); @@ -789,7 +789,7 @@ impl CrateInfo { }; let lang_items = tcx.lang_items(); - let crates = tcx.crates(); + let crates = tcx.crates(()); let n_crates = crates.len(); info.native_libraries.reserve(n_crates); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 7b4b0821c4b..a97c6a6b442 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -1,9 +1,22 @@ // Type Names for Debug Info. +// Notes on targetting MSVC: +// In general, MSVC's debugger attempts to parse all arguments as C++ expressions, +// even if the argument is explicitly a symbol name. +// As such, there are many things that cause parsing issues: +// * `#` is treated as a special character for macros. +// * `{` or `<` at the beginning of a name is treated as an operator. +// * `>>` is always treated as a right-shift. +// * `[` in a name is treated like a regex bracket expression (match any char +// within the brackets). +// * `"` is treated as the start of a string. + use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt}; +use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_target::abi::{TagEncoding, Variants}; use std::fmt::Write; @@ -40,7 +53,13 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), - ty::Never => output.push('!'), + ty::Never => { + if cpp_like_names { + output.push_str("never$"); + } else { + output.push('!'); + } + } ty::Int(int_ty) => output.push_str(int_ty.name_str()), ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), ty::Float(float_ty) => output.push_str(float_ty.name_str()), @@ -50,74 +69,109 @@ pub fn push_debuginfo_type_name<'tcx>( 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); + push_generic_params_internal(tcx, substs, output, visited); } } ty::Tuple(component_types) => { if cpp_like_names { - output.push_str("tuple<"); + output.push_str("tuple$<"); } else { output.push('('); } for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); - output.push_str(", "); + output.push(','); + + // Natvis does not always like having spaces between parts of the type name + // and this causes issues when we need to write a typename in natvis, for example + // as part of a cast like the `HashMap` visualizer does. + if !cpp_like_names { + output.push(' '); + } } if !component_types.is_empty() { output.pop(); - output.pop(); + + if !cpp_like_names { + output.pop(); + } } if cpp_like_names { - output.push('>'); + push_close_angle_bracket(tcx, output); } else { output.push(')'); } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { - if !cpp_like_names { + if cpp_like_names { + match mutbl { + hir::Mutability::Not => output.push_str("ptr_const$<"), + hir::Mutability::Mut => output.push_str("ptr_mut$<"), + } + } else { output.push('*'); - } - match mutbl { - hir::Mutability::Not => output.push_str("const "), - hir::Mutability::Mut => output.push_str("mut "), + match mutbl { + hir::Mutability::Not => output.push_str("const "), + hir::Mutability::Mut => output.push_str("mut "), + } } - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); if cpp_like_names { - output.push('*'); + push_close_angle_bracket(tcx, output); } } ty::Ref(_, inner_type, mutbl) => { + // Slices and `&str` are treated like C++ pointers when computing debug + // info for MSVC debugger. However, wrapping these types' names in a synthetic type + // causes the .natvis engine for WinDbg to fail to display their data, so we opt these + // types out to aid debugging in MSVC. + let is_slice_or_str = match *inner_type.kind() { + ty::Slice(_) | ty::Str => true, + _ => false, + }; + if !cpp_like_names { output.push('&'); + output.push_str(mutbl.prefix_str()); + } else if !is_slice_or_str { + match mutbl { + hir::Mutability::Not => output.push_str("ref$<"), + hir::Mutability::Mut => output.push_str("ref_mut$<"), + } } - output.push_str(mutbl.prefix_str()); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names { - // Slices and `&str` are treated like C++ pointers when computing debug - // info for MSVC debugger. However, adding '*' at the end of these types' names - // causes the .natvis engine for WinDbg to fail to display their data, so we opt these - // types out to aid debugging in MSVC. - match *inner_type.kind() { - ty::Slice(_) | ty::Str => {} - _ => output.push('*'), - } + if cpp_like_names && !is_slice_or_str { + push_close_angle_bracket(tcx, output); } } ty::Array(inner_type, len) => { - output.push('['); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); - output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))); - output.push(']'); + if cpp_like_names { + output.push_str("array$<"); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(), + _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } else { + output.push('['); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(), + _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } } ty::Slice(inner_type) => { if cpp_like_names { - output.push_str("slice<"); + output.push_str("slice$<"); } else { output.push('['); } @@ -125,19 +179,69 @@ pub fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, true, output, visited); if cpp_like_names { - output.push('>'); + push_close_angle_bracket(tcx, output); } else { output.push(']'); } } ty::Dynamic(ref trait_data, ..) => { + if cpp_like_names { + output.push_str("dyn$<"); + } else { + output.push_str("dyn "); + } + if let Some(principal) = trait_data.principal() { let principal = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); - push_item_name(tcx, principal.def_id, false, output); - push_type_params(tcx, principal.substs, output, visited); + push_item_name(tcx, principal.def_id, qualified, output); + push_generic_params_internal(tcx, principal.substs, output, visited); } else { - output.push_str("dyn '_"); + // The auto traits come ordered by `DefPathHash`, which guarantees stability if the + // environment is stable (e.g., incremental builds) but not otherwise (e.g., + // updated compiler version, different target). + // + // To avoid that causing instabilities in test output, sort the auto-traits + // alphabetically. + let mut auto_traits: Vec<_> = trait_data + .iter() + .filter_map(|predicate| { + match tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + predicate, + ) { + ty::ExistentialPredicate::AutoTrait(def_id) => { + let mut name = String::new(); + push_item_name(tcx, def_id, true, &mut name); + Some(name) + } + _ => None, + } + }) + .collect(); + auto_traits.sort(); + + for name in auto_traits { + output.push_str(&name); + + if cpp_like_names { + output.push_str(", "); + } else { + output.push_str(" + "); + } + } + + // Remove the trailing joining characters. For cpp_like_names + // this is `, ` otherwise ` + `. + output.pop(); + output.pop(); + if !cpp_like_names { + output.pop(); + } + } + + if cpp_like_names { + push_close_angle_bracket(tcx, output); } } ty::FnDef(..) | ty::FnPtr(_) => { @@ -155,23 +259,37 @@ pub fn push_debuginfo_type_name<'tcx>( // use a dummy string that should make it clear // that something unusual is going on if !visited.insert(t) { - output.push_str("<recursive_type>"); + output.push_str(if cpp_like_names { + "recursive_type$" + } else { + "<recursive_type>" + }); return; } - let sig = t.fn_sig(tcx); - output.push_str(sig.unsafety().prefix_str()); + let sig = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); - let abi = sig.abi(); - if abi != rustc_target::spec::abi::Abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } + if cpp_like_names { + // Format as a C++ function pointer: return_type (*)(params...) + if sig.output().is_unit() { + output.push_str("void"); + } else { + push_debuginfo_type_name(tcx, sig.output(), true, output, visited); + } + output.push_str(" (*)("); + } else { + output.push_str(sig.unsafety.prefix_str()); + + if sig.abi != rustc_target::spec::abi::Abi::Rust { + output.push_str("extern \""); + output.push_str(sig.abi.name()); + output.push_str("\" "); + } - output.push_str("fn("); + output.push_str("fn("); + } - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(tcx, parameter_type, true, output, visited); @@ -191,7 +309,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push(')'); - if !sig.output().is_unit() { + if !cpp_like_names && !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(tcx, sig.output(), true, output, visited); } @@ -207,17 +325,14 @@ pub fn push_debuginfo_type_name<'tcx>( // processing visited.remove(t); } - ty::Closure(def_id, ..) => { - output.push_str(&format!( - "closure-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); - } - ty::Generator(def_id, ..) => { - output.push_str(&format!( - "generator-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); + ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { + let key = tcx.def_key(def_id); + if qualified { + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + push_item_name(tcx, parent_def_id, true, output); + output.push_str("::"); + } + push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output); } // Type parameters from polymorphized functions. ty::Param(_) => { @@ -273,7 +388,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push_str("enum$<"); push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); + push_generic_params_internal(tcx, substs, output, visited); let dataful_variant_name = def.variants[*dataful_variant].ident.as_str(); @@ -281,47 +396,116 @@ pub fn push_debuginfo_type_name<'tcx>( } else { output.push_str("enum$<"); push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); - output.push('>'); + push_generic_params_internal(tcx, substs, output, visited); + push_close_angle_bracket(tcx, output); } } +} + +pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { + let def_key = tcx.def_key(def_id); + if qualified { + if let Some(parent) = def_key.parent { + push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); + output.push_str("::"); + } + } + + push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); +} - fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { - if qualified { +fn push_unqualified_item_name( + tcx: TyCtxt<'tcx>, + def_id: DefId, + disambiguated_data: DisambiguatedDefPathData, + output: &mut String, +) { + let cpp_like_names = tcx.sess.target.is_like_msvc; + + match disambiguated_data.data { + DefPathData::CrateRoot => { output.push_str(&tcx.crate_name(def_id.krate).as_str()); - for path_element in tcx.def_path(def_id).data { - write!(output, "::{}", path_element.data).unwrap(); + } + DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { + // Generators look like closures, but we want to treat them differently + // in the debug info. + if cpp_like_names { + write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); } - } else { - output.push_str(&tcx.item_name(def_id).as_str()); } + _ => match disambiguated_data.data.name() { + DefPathDataName::Named(name) => { + output.push_str(&name.as_str()); + } + DefPathDataName::Anon { namespace } => { + if cpp_like_names { + write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) + .unwrap(); + } + } + }, + }; +} + +// Pushes the generic parameters in the given `InternalSubsts` to the output string. +// This ignores region parameters, since they can't reliably be +// reconstructed for items from non-local crates. For local crates, this +// would be possible but with inlining and LTO we have to use the least +// common denominator - otherwise we would run into conflicts. +fn push_generic_params_internal<'tcx>( + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + output: &mut String, + visited: &mut FxHashSet<Ty<'tcx>>, +) { + if substs.non_erasable_generics().next().is_none() { + return; } - // Pushes the type parameters in the given `InternalSubsts` to the output string. - // This ignores region parameters, since they can't reliably be - // reconstructed for items from non-local crates. For local crates, this - // would be possible but with inlining and LTO we have to use the least - // common denominator - otherwise we would run into conflicts. - fn push_type_params<'tcx>( - tcx: TyCtxt<'tcx>, - substs: SubstsRef<'tcx>, - output: &mut String, - visited: &mut FxHashSet<Ty<'tcx>>, - ) { - if substs.types().next().is_none() { - return; - } + debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs)); - output.push('<'); + output.push('<'); - for type_parameter in substs.types() { - push_debuginfo_type_name(tcx, type_parameter, true, output, visited); - output.push_str(", "); + for type_parameter in substs.non_erasable_generics() { + match type_parameter { + GenericArgKind::Type(type_parameter) => { + push_debuginfo_type_name(tcx, type_parameter, true, output, visited); + output.push_str(", "); + } + GenericArgKind::Const(const_parameter) => match const_parameter.val { + ty::ConstKind::Param(param) => write!(output, "{}, ", param.name).unwrap(), + _ => write!( + output, + "0x{:x}, ", + const_parameter.eval_bits(tcx, ty::ParamEnv::reveal_all(), const_parameter.ty) + ) + .unwrap(), + }, + other => bug!("Unexpected non-erasable generic: {:?}", other), } + } - output.pop(); - output.pop(); + output.pop(); + output.pop(); - output.push('>'); - } + push_close_angle_bracket(tcx, output); +} + +pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) { + let mut visited = FxHashSet::default(); + push_generic_params_internal(tcx, substs, output, &mut visited); +} + +fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) { + // MSVC debugger always treats `>>` as a shift, even when parsing templates, + // so add a space to avoid confusion. + if tcx.sess.target.is_like_msvc && output.ends_with('>') { + output.push(' ') + }; + + output.push('>'); } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 4f0de729704..63245a94c8e 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -1,6 +1,6 @@ use crate::traits::*; -use rustc_middle::ty::{self, Instance, Ty, VtblEntry, COMMON_VTABLE_ENTRIES}; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::call::FnAbi; #[derive(Copy, Clone, Debug)] @@ -70,48 +70,13 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( return val; } - // Not in the cache; build it. - let nullptr = cx.const_null(cx.type_i8p_ext(cx.data_layout().instruction_address_space)); - - let vtable_entries = if let Some(trait_ref) = trait_ref { - tcx.vtable_entries(trait_ref.with_self_ty(tcx, ty)) - } else { - COMMON_VTABLE_ENTRIES - }; - - let layout = cx.layout_of(ty); - // ///////////////////////////////////////////////////////////////////////////////////////////// - // If you touch this code, be sure to also make the corresponding changes to - // `get_vtable` in `rust_mir/interpret/traits.rs`. - // ///////////////////////////////////////////////////////////////////////////////////////////// - let components: Vec<_> = vtable_entries - .iter() - .map(|entry| match entry { - VtblEntry::MetadataDropInPlace => { - cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)) - } - VtblEntry::MetadataSize => cx.const_usize(layout.size.bytes()), - VtblEntry::MetadataAlign => cx.const_usize(layout.align.abi.bytes()), - VtblEntry::Vacant => nullptr, - VtblEntry::Method(def_id, substs) => cx.get_fn_addr( - ty::Instance::resolve_for_vtable( - cx.tcx(), - ty::ParamEnv::reveal_all(), - *def_id, - substs, - ) - .unwrap() - .polymorphize(cx.tcx()), - ), - }) - .collect(); - - let vtable_const = cx.const_struct(&components, false); + let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref); + let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory(); + let vtable_const = cx.const_data_from_alloc(vtable_allocation); let align = cx.data_layout().pointer_align.abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); cx.create_vtable_metadata(ty, vtable); - cx.vtables().borrow_mut().insert((ty, trait_ref), vtable); vtable } diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 6b58dea794b..20f66187123 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -26,6 +26,8 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>; fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>; + fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value; + fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value; fn from_const_alloc( &self, diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 6fff64bfcb6..46f2adbe552 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -16,7 +16,7 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn sess(&self) -> &Session; fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>; fn used_statics(&self) -> &RefCell<Vec<Self::Value>>; - fn set_frame_pointer_elimination(&self, llfn: Self::Function); + fn set_frame_pointer_type(&self, llfn: Self::Function); fn apply_target_cpu_attr(&self, llfn: Self::Function); fn create_used_variable(&self); /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists. diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index c35a164bb33..112b94f6e0e 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -17,7 +17,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } rustc_graphviz = { path = "../rustc_graphviz" } cfg-if = "0.1.2" -crossbeam-utils = { version = "0.8", features = ["nightly"] } stable_deref_trait = "1.0.0" rayon = { version = "0.3.1", package = "rustc-rayon" } rayon-core = { version = "0.3.1", package = "rustc-rayon-core" } diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index c521f2041d8..93c6ec04e4f 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -34,8 +34,6 @@ rustc_interface = { path = "../rustc_interface" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -rustc_mir_build = { path = "../rustc_mir_build" } -rustc_typeck = { path = "../rustc_typeck" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 35a6495946f..326fefa59ab 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -29,7 +29,7 @@ use rustc_middle::middle::cstore::MetadataLoader; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_serialize::json::{self, ToJson}; -use rustc_session::config::nightly_options; +use rustc_session::config::{nightly_options, CG_OPTIONS, DB_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths}; use rustc_session::getopts; use rustc_session::lint::{Lint, LintId}; @@ -46,7 +46,6 @@ use std::ffi::OsString; use std::fs; use std::io::{self, Read, Write}; use std::lazy::SyncLazy; -use std::mem; use std::panic::{self, catch_unwind}; use std::path::PathBuf; use std::process::{self, Command, Stdio}; @@ -316,12 +315,12 @@ fn run_compiler( if let Some(ppm) = &sess.opts.pretty { if ppm.needs_ast_map() { + let expanded_crate = queries.expansion()?.peek().0.clone(); queries.global_ctxt()?.peek_mut().enter(|tcx| { - let expanded_crate = queries.expansion()?.take().0; pretty::print_after_hir_lowering( tcx, compiler.input(), - &expanded_crate, + &*expanded_crate, *ppm, compiler.output_file().as_ref().map(|p| &**p), ); @@ -377,12 +376,6 @@ fn run_compiler( queries.global_ctxt()?; - // Drop AST after creating GlobalCtxt to free memory - { - let _timer = sess.prof.generic_activity("drop_ast"); - mem::drop(queries.expansion()?.take()); - } - if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json { return early_exit(); } @@ -1017,9 +1010,18 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { for option in config::rustc_optgroups() { (option.apply)(&mut options); } - let matches = options - .parse(args) - .unwrap_or_else(|f| early_error(ErrorOutputType::default(), &f.to_string())); + let matches = options.parse(args).unwrap_or_else(|e| { + let msg = match e { + getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS + .iter() + .map(|&(name, ..)| ('C', name)) + .chain(DB_OPTIONS.iter().map(|&(name, ..)| ('Z', name))) + .find(|&(_, name)| *opt == name.replace("_", "-")) + .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)), + _ => None, + }; + early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string())); + }); // For all options we just parsed, we check a few aspects: // @@ -1303,10 +1305,60 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } +#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] +mod signal_handler { + extern "C" { + fn backtrace_symbols_fd( + buffer: *const *mut libc::c_void, + size: libc::c_int, + fd: libc::c_int, + ); + } + + extern "C" fn print_stack_trace(_: libc::c_int) { + const MAX_FRAMES: usize = 256; + static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] = + [std::ptr::null_mut(); MAX_FRAMES]; + unsafe { + let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32); + if depth == 0 { + return; + } + backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2); + } + } + + // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the + // process, print a stack trace and then exit. + pub(super) fn install() { + unsafe { + const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let mut alt_stack: libc::stack_t = std::mem::zeroed(); + alt_stack.ss_sp = + std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) + as *mut libc::c_void; + alt_stack.ss_size = ALT_STACK_SIZE; + libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); + + let mut sa: libc::sigaction = std::mem::zeroed(); + sa.sa_sigaction = print_stack_trace as libc::sighandler_t; + sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; + libc::sigemptyset(&mut sa.sa_mask); + libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); + } + } +} + +#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))] +mod signal_handler { + pub(super) fn install() {} +} + pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); init_rustc_env_logger(); + signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| { diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index ff7a2344e69..df162f8dce0 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -361,6 +361,7 @@ E0626: include_str!("./error_codes/E0626.md"), E0627: include_str!("./error_codes/E0627.md"), E0628: include_str!("./error_codes/E0628.md"), E0631: include_str!("./error_codes/E0631.md"), +E0632: include_str!("./error_codes/E0632.md"), E0633: include_str!("./error_codes/E0633.md"), E0634: include_str!("./error_codes/E0634.md"), E0635: include_str!("./error_codes/E0635.md"), @@ -623,8 +624,6 @@ E0783: include_str!("./error_codes/E0783.md"), // E0629, // missing 'feature' (rustc_const_unstable) // E0630, // rustc_const_unstable attribute must be paired with stable/unstable // attribute - E0632, // cannot provide explicit generic arguments when `impl Trait` is - // used in argument position E0640, // infer outlives requirements // E0645, // trait aliases not finished E0667, // `impl Trait` in projections diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42baa65bf9f..ec86ec44ece 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,4 +1,4 @@ -An invalid number of type parameters was given to an intrinsic function. +An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_error_codes/src/error_codes/E0632.md b/compiler/rustc_error_codes/src/error_codes/E0632.md new file mode 100644 index 00000000000..40840e894d6 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0632.md @@ -0,0 +1,25 @@ +An explicit generic argument was provided when calling a function that +uses `impl Trait` in argument position. + +Erroneous code example: + +```compile_fail,E0632 +fn foo<T: Copy>(a: T, b: impl Clone) {} + +foo::<i32>(0i32, "abc".to_string()); +``` + +Either all generic arguments should be inferred at the call site, or +the function definition should use an explicit generic type parameter +instead of `impl Trait`. Example: + +``` +fn foo<T: Copy>(a: T, b: impl Clone) {} +fn bar<T: Copy, U: Clone>(a: T, b: U) {} + +foo(0i32, "abc".to_string()); + +bar::<i32, String>(0i32, "abc".to_string()); +bar::<_, _>(0i32, "abc".to_string()); +bar(0i32, "abc".to_string()); +``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0716.md b/compiler/rustc_error_codes/src/error_codes/E0716.md index c6d0337ddda..c3546cd744f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0716.md +++ b/compiler/rustc_error_codes/src/error_codes/E0716.md @@ -14,14 +14,16 @@ Here, the expression `&foo()` is borrowing the expression `foo()`. As `foo()` is a call to a function, and not the name of a variable, this creates a **temporary** -- that temporary stores the return value from `foo()` so that it can be borrowed. You could imagine that `let p = bar(&foo());` is equivalent to -this: +the following, which uses an explicit temporary variable. + +Erroneous code example: ```compile_fail,E0597 # fn foo() -> i32 { 22 } # fn bar(x: &i32) -> &i32 { x } let p = { let tmp = foo(); // the temporary - bar(&tmp) + bar(&tmp) // error: `tmp` does not live long enough }; // <-- tmp is freed as we exit this block let q = p; ``` diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 979f2d3b300..ca2386dfae2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(backtrace)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 92315c4d4f6..1d73002710d 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -411,6 +411,10 @@ impl server::FreeFunctions for Rustc<'_> { fn track_env_var(&mut self, var: &str, value: Option<&str>) { self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern))); } + + fn track_path(&mut self, path: &str) { + self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path)); + } } impl server::TokenStream for Rustc<'_> { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 56a320c8d3b..f045a75cdc8 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -16,8 +16,14 @@ macro_rules! set { } macro_rules! declare_features { + (__status_to_bool active) => { + false + }; + (__status_to_bool incomplete) => { + true + }; ($( - $(#[doc = $doc:tt])* (active, $feature:ident, $ver:expr, $issue:expr, $edition:expr), + $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr), )+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. @@ -67,6 +73,21 @@ macro_rules! declare_features { pub fn unordered_const_ty_params(&self) -> bool { self.const_generics || self.const_generics_defaults } + + /// Some features are known to be incomplete and using them is likely to have + /// unanticipated results, such as compiler crashes. We warn the user about these + /// to alert them. + pub fn incomplete(&self, feature: Symbol) -> bool { + match feature { + $( + sym::$feature => declare_features!(__status_to_bool $status), + )* + // accepted and removed features aren't in this file but are never incomplete + _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false, + _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false, + _ => panic!("`{}` was not listed in `declare_features`", feature), + } + } } }; } @@ -305,7 +326,7 @@ declare_features! ( (active, cfg_target_thread_local, "1.7.0", Some(29594), None), /// Allows specialization of implementations (RFC 1210). - (active, specialization, "1.7.0", Some(31844), None), + (incomplete, specialization, "1.7.0", Some(31844), None), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization @@ -342,7 +363,7 @@ declare_features! ( (active, abi_ptx, "1.15.0", Some(38788), None), /// Allows the `#[repr(i128)]` attribute for enums. - (active, repr128, "1.16.0", Some(56071), None), + (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `#[link(kind="static-nobundle"...)]`. (active, static_nobundle, "1.16.0", Some(37403), None), @@ -384,7 +405,7 @@ declare_features! ( (active, in_band_lifetimes, "1.23.0", Some(44524), None), /// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598). - (active, generic_associated_types, "1.23.0", Some(44265), None), + (incomplete, generic_associated_types, "1.23.0", Some(44265), None), /// Allows defining `trait X = A + B;` alias items. (active, trait_alias, "1.24.0", Some(41517), None), @@ -429,7 +450,7 @@ declare_features! ( (active, proc_macro_hygiene, "1.30.0", Some(54727), None), /// Allows unsized rvalues at arguments and parameters. - (active, unsized_locals, "1.30.0", Some(48055), None), + (incomplete, unsized_locals, "1.30.0", Some(48055), None), /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. (active, custom_test_frameworks, "1.30.0", Some(50297), None), @@ -438,7 +459,7 @@ declare_features! ( (active, custom_inner_attributes, "1.30.0", Some(54726), None), /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), + (incomplete, impl_trait_in_bindings, "1.30.0", Some(63065), None), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (active, lint_reasons, "1.31.0", Some(54503), None), @@ -450,7 +471,7 @@ declare_features! ( (active, ffi_returns_twice, "1.34.0", Some(58314), None), /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`). - (active, const_generics, "1.34.0", Some(44580), None), + (incomplete, const_generics, "1.34.0", Some(44580), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), @@ -462,7 +483,7 @@ declare_features! ( (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows `if/while p && let q = r && ...` chains. - (active, let_chains, "1.37.0", Some(53667), None), + (incomplete, let_chains, "1.37.0", Some(53667), None), /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), @@ -474,13 +495,13 @@ declare_features! ( (active, async_closure, "1.37.0", Some(62290), None), /// Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + (incomplete, type_alias_impl_trait, "1.38.0", Some(63063), None), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), /// Allows the use of raw-dylibs (RFC 2627). - (active, raw_dylib, "1.40.0", Some(58713), None), + (incomplete, raw_dylib, "1.40.0", Some(58713), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and @@ -516,10 +537,10 @@ declare_features! ( (active, bindings_after_at, "1.41.0", Some(65490), None), /// Allows `impl const Trait for T` syntax. - (active, const_trait_impl, "1.42.0", Some(67792), None), + (incomplete, const_trait_impl, "1.42.0", Some(67792), None), /// Allows `T: ?const Trait` syntax in bounds. - (active, const_trait_bound_opt_out, "1.42.0", Some(67794), None), + (incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None), /// Allows the use of `no_sanitize` attribute. (active, no_sanitize, "1.42.0", Some(39699), None), @@ -552,16 +573,16 @@ declare_features! ( (active, format_args_capture, "1.46.0", Some(67984), None), /// Lazily evaluate constants. This allows constants to depend on type parameters. - (active, lazy_normalization_consts, "1.46.0", Some(72219), None), + (incomplete, lazy_normalization_consts, "1.46.0", Some(72219), None), /// Allows calling `transmute` in const fn (active, const_fn_transmute, "1.46.0", Some(53605), None), /// Allows `if let` guard in match arms. - (active, if_let_guard, "1.47.0", Some(51114), None), + (incomplete, if_let_guard, "1.47.0", Some(51114), None), /// Allows non-trivial generic constants which have to be manually propagated upwards. - (active, const_evaluatable_checked, "1.48.0", Some(76560), None), + (incomplete, const_evaluatable_checked, "1.48.0", Some(76560), None), /// Allows basic arithmetic on floating point types in a `const fn`. (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), @@ -582,7 +603,7 @@ declare_features! ( (active, isa_attribute, "1.48.0", Some(74727), None), /// Allow anonymous constants from an inline `const` block - (active, inline_const, "1.49.0", Some(76001), None), + (incomplete, inline_const, "1.49.0", Some(76001), None), /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), @@ -594,7 +615,7 @@ declare_features! ( (active, cfg_panic, "1.49.0", Some(77443), None), /// Allows capturing disjoint fields in a closure/generator (RFC 2229). - (active, capture_disjoint_fields, "1.49.0", Some(53488), None), + (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), @@ -618,7 +639,7 @@ declare_features! ( (active, min_type_alias_impl_trait, "1.52.0", Some(63063), None), /// Allows associated types in inherent impls. - (active, inherent_associated_types, "1.52.0", Some(8995), None), + (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), @@ -661,7 +682,7 @@ declare_features! ( (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), /// Allows unnamed fields of struct and union type - (active, unnamed_fields, "1.53.0", Some(49804), None), + (incomplete, unnamed_fields, "1.53.0", Some(49804), None), /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. (active, more_qualified_paths, "1.54.0", Some(80080), None), @@ -671,31 +692,6 @@ declare_features! ( // ------------------------------------------------------------------------- ); -/// Some features are known to be incomplete and using them is likely to have -/// unanticipated results, such as compiler crashes. We warn the user about these -/// to alert them. -pub const INCOMPLETE_FEATURES: &[Symbol] = &[ - sym::if_let_guard, - sym::impl_trait_in_bindings, - sym::generic_associated_types, - sym::const_generics, - sym::let_chains, - sym::raw_dylib, - sym::const_evaluatable_checked, - sym::const_trait_impl, - sym::const_trait_bound_opt_out, - sym::lazy_normalization_consts, - sym::specialization, - sym::inline_const, - sym::repr128, - sym::unsized_locals, - sym::capture_disjoint_fields, - sym::inherent_associated_types, - sym::type_alias_impl_trait, - sym::rustc_insignificant_dtor, - sym::unnamed_fields, -]; - /// Some features are not allowed to be used together at the same time, if /// the two are present, produce an error. /// diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 654d2408580..cf102aa16e0 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -146,7 +146,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU3 } pub use accepted::ACCEPTED_FEATURES; -pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES, INCOMPLETE_FEATURES}; +pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES}; pub use builtin_attrs::{ deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index ad2ecae9233..42575273839 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -3,7 +3,6 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 8539cc69371..ee62089b237 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -21,8 +21,8 @@ pub enum LoadResult<T> { Error { message: String }, } -impl LoadResult<(SerializedDepGraph, WorkProductMap)> { - pub fn open(self, sess: &Session) -> (SerializedDepGraph, WorkProductMap) { +impl<T: Default> LoadResult<T> { + pub fn open(self, sess: &Session) -> T { match self { LoadResult::Error { message } => { sess.warn(&message); @@ -74,11 +74,14 @@ pub enum MaybeAsync<T> { Sync(T), Async(std::thread::JoinHandle<T>), } -impl<T> MaybeAsync<T> { - pub fn open(self) -> std::thread::Result<T> { + +impl<T> MaybeAsync<LoadResult<T>> { + pub fn open(self) -> LoadResult<T> { match self { - MaybeAsync::Sync(result) => Ok(result), - MaybeAsync::Async(handle) => handle.join(), + MaybeAsync::Sync(result) => result, + MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error { + message: format!("could not decode incremental cache: {:?}", e), + }), } } } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index a75ad7b31a6..933373150c1 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" doctest = false [dependencies] -rustc_graphviz = { path = "../rustc_graphviz" } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -21,4 +20,3 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index c68705da413..ac953f4305c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -46,13 +46,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { { self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( - value, - Some(self), - self.tcx, - &CanonicalizeAllFreeRegions, - query_state, - ) + Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state) } /// Canonicalizes a query *response* `V`. When we canonicalize a @@ -87,7 +81,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeQueryResponse, &mut query_state, @@ -101,7 +95,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeUserTypeAnnotation, &mut query_state, @@ -133,7 +127,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeFreeRegionsOtherThanStatic, query_state, @@ -275,7 +269,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic { } struct Canonicalizer<'cx, 'tcx> { - infcx: Option<&'cx InferCtxt<'cx, 'tcx>>, + infcx: &'cx InferCtxt<'cx, 'tcx>, tcx: TyCtxt<'tcx>, variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>, query_state: &'cx mut OriginalQueryValues<'tcx>, @@ -316,7 +310,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { ty::ReVar(vid) => { let resolved_vid = self .infcx - .unwrap() .inner .borrow_mut() .unwrap_region_constraints() @@ -343,7 +336,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { match *t.kind() { ty::Infer(ty::TyVar(vid)) => { debug!("canonical: type var found with vid {:?}", vid); - match self.infcx.unwrap().probe_ty_var(vid) { + match self.infcx.probe_ty_var(vid) { // `t` could be a float / int variable; canonicalize that instead. Ok(t) => { debug!("(resolved to {:?})", t); @@ -429,7 +422,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { match ct.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { debug!("canonical: const var found with vid {:?}", vid); - match self.infcx.unwrap().probe_const_var(vid) { + match self.infcx.probe_const_var(vid) { Ok(c) => { debug!("(resolved to {:?})", c); return self.fold_const(c); @@ -476,7 +469,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// `canonicalize_query` and `canonicalize_response`. fn canonicalize<V>( value: V, - infcx: Option<&InferCtxt<'_, 'tcx>>, + infcx: &InferCtxt<'_, 'tcx>, tcx: TyCtxt<'tcx>, canonicalize_region_mode: &dyn CanonicalizeRegionMode, query_state: &mut OriginalQueryValues<'tcx>, @@ -610,7 +603,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// Returns the universe in which `vid` is defined. fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex { - self.infcx.unwrap().inner.borrow_mut().unwrap_region_constraints().var_universe(vid) + self.infcx.inner.borrow_mut().unwrap_region_constraints().var_universe(vid) } /// Creates a canonical variable (with the given `info`) @@ -631,7 +624,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// *that*. Otherwise, create a new canonical variable for /// `ty_var`. fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> { - let infcx = self.infcx.expect("encountered ty-var without infcx"); + let infcx = self.infcx; let bound_to = infcx.shallow_resolve(ty_var); if bound_to != ty_var { self.fold_ty(bound_to) @@ -650,7 +643,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { info: CanonicalVarInfo<'tcx>, const_var: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> { - let infcx = self.infcx.expect("encountered const-var without infcx"); + let infcx = self.infcx; let bound_to = infcx.shallow_resolve(const_var); if bound_to != const_var { self.fold_const(bound_to) diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 194464dd0bf..85493978d9d 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -31,7 +31,6 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } rustc_mir = { path = "../rustc_mir" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 4abc4b29b50..c0f7ea8df49 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -7,7 +7,6 @@ use rustc_ast::{self as ast, visit}; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; -use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, PResult}; @@ -29,18 +28,18 @@ use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_query_impl::Queries as TcxQueries; use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_serialize::json; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode}; use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::FileName; use rustc_trait_selection::traits; use rustc_typeck as typeck; -use tracing::{info, warn}; - -use rustc_serialize::json; use tempfile::Builder as TempFileBuilder; +use tracing::{info, warn}; use std::any::Any; use std::cell::RefCell; @@ -101,7 +100,7 @@ mod boxed_resolver { } // Note: Drop order is important to prevent dangling references. Resolver must be dropped first, - // then resolver_arenas and finally session. + // then resolver_arenas and session. impl Drop for BoxedResolverInner { fn drop(&mut self) { self.resolver.take(); @@ -110,13 +109,10 @@ mod boxed_resolver { } impl BoxedResolver { - pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)> - where - F: for<'a> FnOnce( - &'a Session, - &'a ResolverArenas<'a>, - ) -> Result<(ast::Crate, Resolver<'a>)>, - { + pub(super) fn new( + session: Lrc<Session>, + make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>, + ) -> BoxedResolver { let mut boxed_resolver = Box::new(BoxedResolverInner { session, resolver_arenas: Some(Resolver::arenas()), @@ -127,14 +123,14 @@ mod boxed_resolver { // returns a resolver with the same lifetime as the arena. We ensure that the arena // outlives the resolver in the drop impl and elsewhere so these transmutes are sound. unsafe { - let (crate_, resolver) = make_resolver( + let resolver = make_resolver( std::mem::transmute::<&Session, &Session>(&boxed_resolver.session), std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>( boxed_resolver.resolver_arenas.as_ref().unwrap(), ), - )?; + ); boxed_resolver.resolver = Some(resolver); - Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver)))) + BoxedResolver(Pin::new_unchecked(boxed_resolver)) } } @@ -165,35 +161,15 @@ mod boxed_resolver { } } -/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, -/// syntax expansion, secondary `cfg` expansion, synthesis of a test -/// harness if one is to be provided, injection of a dependency on the -/// standard library and prelude, and name resolution. -/// -/// Returns [`None`] if we're aborting after handling -W help. -pub fn configure_and_expand( +pub fn create_resolver( sess: Lrc<Session>, - lint_store: Lrc<LintStore>, metadata_loader: Box<MetadataLoaderDyn>, - krate: ast::Crate, + krate: &ast::Crate, crate_name: &str, -) -> Result<(ast::Crate, BoxedResolver)> { - tracing::trace!("configure_and_expand"); - // Currently, we ignore the name resolution data structures for the purposes of dependency - // tracking. Instead we will run name resolution and include its output in the hash of each - // item, much like we do for macro expansion. In other words, the hash reflects not just - // its contents but the results of name resolution on those contents. Hopefully we'll push - // this back at some point. - let crate_name = crate_name.to_string(); +) -> BoxedResolver { + tracing::trace!("create_resolver"); BoxedResolver::new(sess, move |sess, resolver_arenas| { - configure_and_expand_inner( - sess, - &lint_store, - krate, - &crate_name, - &resolver_arenas, - metadata_loader, - ) + Resolver::new(sess, &krate, &crate_name, metadata_loader, &resolver_arenas) }) } @@ -278,28 +254,24 @@ fn pre_expansion_lint( }); } -fn configure_and_expand_inner<'a>( - sess: &'a Session, +/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, +/// syntax expansion, secondary `cfg` expansion, synthesis of a test +/// harness if one is to be provided, injection of a dependency on the +/// standard library and prelude, and name resolution. +pub fn configure_and_expand( + sess: &Session, lint_store: &LintStore, mut krate: ast::Crate, crate_name: &str, - resolver_arenas: &'a ResolverArenas<'a>, - metadata_loader: Box<MetadataLoaderDyn>, -) -> Result<(ast::Crate, Resolver<'a>)> { - tracing::trace!("configure_and_expand_inner"); + resolver: &mut Resolver<'_>, +) -> Result<ast::Crate> { + tracing::trace!("configure_and_expand"); pre_expansion_lint(sess, lint_store, &krate, crate_name); - - let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); - rustc_builtin_macros::register_builtin_macros(&mut resolver); + rustc_builtin_macros::register_builtin_macros(resolver); krate = sess.time("crate_injection", || { let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); - rustc_builtin_macros::standard_library_imports::inject( - krate, - &mut resolver, - &sess, - alt_std_name, - ) + rustc_builtin_macros::standard_library_imports::inject(krate, resolver, &sess, alt_std_name) }); util::check_attr_crate_type(&sess, &krate.attrs, &mut resolver.lint_buffer()); @@ -354,7 +326,7 @@ fn configure_and_expand_inner<'a>( pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str()); (krate.attrs, krate.items) }; - let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded)); + let mut ecx = ExtCtxt::new(&sess, cfg, resolver, Some(&extern_mod_loaded)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -396,16 +368,16 @@ fn configure_and_expand_inner<'a>( })?; sess.time("maybe_building_test_harness", || { - rustc_builtin_macros::test_harness::inject(&sess, &mut resolver, &mut krate) + rustc_builtin_macros::test_harness::inject(&sess, resolver, &mut krate) }); if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty { tracing::debug!("replacing bodies with loop {{}}"); - util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate); + util::ReplaceBodyWithLoop::new(resolver).visit_crate(&mut krate); } let has_proc_macro_decls = sess.time("AST_validation", || { - rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) + rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer()) }); let crate_types = sess.crate_types(); @@ -431,7 +403,7 @@ fn configure_and_expand_inner<'a>( let is_test_crate = sess.opts.test; rustc_builtin_macros::proc_macro_harness::inject( &sess, - &mut resolver, + resolver, krate, is_proc_macro_crate, has_proc_macro_decls, @@ -471,26 +443,20 @@ fn configure_and_expand_inner<'a>( } }); - Ok((krate, resolver)) + Ok(krate) } pub fn lower_to_hir<'res, 'tcx>( sess: &'tcx Session, lint_store: &LintStore, resolver: &'res mut Resolver<'_>, - dep_graph: &'res DepGraph, - krate: &'res ast::Crate, + krate: Rc<ast::Crate>, arena: &'tcx rustc_ast_lowering::Arena<'tcx>, -) -> Crate<'tcx> { - // We're constructing the HIR here; we don't care what we will - // read, since we haven't even constructed the *input* to - // incr. comp. yet. - dep_graph.assert_ignored(); - +) -> &'tcx Crate<'tcx> { // Lower AST to HIR. let hir_crate = rustc_ast_lowering::lower_crate( sess, - &krate, + &*krate, resolver, rustc_parse::nt_to_tokenstream, arena, @@ -511,6 +477,9 @@ pub fn lower_to_hir<'res, 'tcx>( ) }); + // Drop AST to free memory + sess.time("drop_ast", || std::mem::drop(krate)); + // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.debugging_opts.keep_hygiene_data { rustc_span::hygiene::clear_syntax_context_map(); @@ -603,7 +572,7 @@ fn escape_dep_env(symbol: Symbol) -> String { fn write_out_deps( sess: &Session, - boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>, + boxed_resolver: &RefCell<BoxedResolver>, outputs: &OutputFilenames, out_filenames: &[PathBuf], ) { @@ -625,12 +594,22 @@ fn write_out_deps( .map(|fmap| escape_dep_filename(&fmap.name.prefer_local().to_string())) .collect(); + // Account for explicitly marked-to-track files + // (e.g. accessed in proc macros). + let file_depinfo = sess.parse_sess.file_depinfo.borrow(); + let extra_tracked_files = file_depinfo.iter().map(|path_sym| { + let path = PathBuf::from(&*path_sym.as_str()); + let file = FileName::from(path); + escape_dep_filename(&file.prefer_local().to_string()) + }); + files.extend(extra_tracked_files); + if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend { files.push(backend.to_string()); } if sess.binary_dep_depinfo() { - boxed_resolver.borrow().borrow_mut().access(|resolver| { + boxed_resolver.borrow_mut().access(|resolver| { for cnum in resolver.cstore().crates_untracked() { let source = resolver.cstore().crate_source_untracked(cnum); if let Some((path, _)) = source.dylib { @@ -699,7 +678,7 @@ pub fn prepare_outputs( sess: &Session, compiler: &Compiler, krate: &ast::Crate, - boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>, + boxed_resolver: &RefCell<BoxedResolver>, crate_name: &str, ) -> Result<OutputFilenames> { let _timer = sess.timer("prepare_outputs"); @@ -803,16 +782,26 @@ impl<'tcx> QueryContext<'tcx> { pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc<LintStore>, - krate: &'tcx Crate<'tcx>, + krate: Rc<ast::Crate>, dep_graph: DepGraph, - resolver_outputs: ResolverOutputs, + resolver: Rc<RefCell<BoxedResolver>>, outputs: OutputFilenames, crate_name: &str, queries: &'tcx OnceCell<TcxQueries<'tcx>>, global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, + hir_arena: &'tcx WorkerLocal<rustc_ast_lowering::Arena<'tcx>>, ) -> QueryContext<'tcx> { + // We're constructing the HIR here; we don't care what we will + // read, since we haven't even constructed the *input* to + // incr. comp. yet. + dep_graph.assert_ignored(); + let sess = &compiler.session(); + let krate = resolver + .borrow_mut() + .access(|resolver| lower_to_hir(sess, &lint_store, resolver, krate, hir_arena)); + let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -831,7 +820,7 @@ pub fn create_global_ctxt<'tcx>( let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers)); let gcx = sess.time("setup_global_ctxt", || { - global_ctxt.get_or_init(|| { + global_ctxt.get_or_init(move || { TyCtxt::create_global_ctxt( sess, lint_store, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2320f0b47d2..8a0964e6b9f 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -3,17 +3,15 @@ use crate::passes::{self, BoxedResolver, QueryContext}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::ErrorReported; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::Crate; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt}; +use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_query_impl::Queries as TcxQueries; use rustc_serialize::json; use rustc_session::config::{self, OutputFilenames, OutputType}; @@ -81,9 +79,8 @@ pub struct Queries<'tcx> { parse: Query<ast::Crate>, crate_name: Query<String>, register_plugins: Query<(ast::Crate, Lrc<LintStore>)>, - expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>, + expansion: Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>, dep_graph: Query<DepGraph>, - lower_to_hir: Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>, prepare_outputs: Query<OutputFilenames>, global_ctxt: Query<QueryContext<'tcx>>, ongoing_codegen: Query<Box<dyn Any>>, @@ -103,7 +100,6 @@ impl<'tcx> Queries<'tcx> { register_plugins: Default::default(), expansion: Default::default(), dep_graph: Default::default(), - lower_to_hir: Default::default(), prepare_outputs: Default::default(), global_ctxt: Default::default(), ongoing_codegen: Default::default(), @@ -117,13 +113,10 @@ impl<'tcx> Queries<'tcx> { &self.compiler.codegen_backend() } - pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> { + fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> { self.dep_graph_future.compute(|| { - Ok(self - .session() - .opts - .build_dep_graph() - .then(|| rustc_incremental::load_dep_graph(self.session()))) + let sess = self.session(); + Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess))) }) } @@ -174,83 +167,51 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> { + ) -> Result<&Query<(Rc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> { tracing::trace!("expansion"); self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.take(); let _timer = self.session().timer("configure_and_expand"); - passes::configure_and_expand( - self.session().clone(), - lint_store.clone(), + let sess = self.session(); + let mut resolver = passes::create_resolver( + sess.clone(), self.codegen_backend().metadata_loader(), - krate, + &krate, &crate_name, - ) - .map(|(krate, resolver)| { - (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) - }) + ); + let krate = resolver.access(|resolver| { + passes::configure_and_expand(&sess, &lint_store, krate, &crate_name, resolver) + })?; + Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) } - pub fn dep_graph(&self) -> Result<&Query<DepGraph>> { + fn dep_graph(&self) -> Result<&Query<DepGraph>> { self.dep_graph.compute(|| { - Ok(match self.dep_graph_future()?.take() { - None => DepGraph::new_disabled(), - Some(future) => { + let sess = self.session(); + let future_opt = self.dep_graph_future()?.take(); + let dep_graph = future_opt + .and_then(|future| { let (prev_graph, prev_work_products) = - self.session().time("blocked_on_dep_graph_loading", || { - future - .open() - .unwrap_or_else(|e| rustc_incremental::LoadResult::Error { - message: format!("could not decode incremental cache: {:?}", e), - }) - .open(self.session()) - }); - - rustc_incremental::build_dep_graph( - self.session(), - prev_graph, - prev_work_products, - ) - .unwrap_or_else(DepGraph::new_disabled) - } - }) - }) - } + sess.time("blocked_on_dep_graph_loading", || future.open().open(sess)); - pub fn lower_to_hir(&'tcx self) -> Result<&Query<(&'tcx Crate<'tcx>, Steal<ResolverOutputs>)>> { - self.lower_to_hir.compute(|| { - let expansion_result = self.expansion()?; - let peeked = expansion_result.peek(); - let krate = &peeked.0; - let resolver = peeked.1.steal(); - let lint_store = &peeked.2; - let hir = resolver.borrow_mut().access(|resolver| { - Ok(passes::lower_to_hir( - self.session(), - lint_store, - resolver, - &*self.dep_graph()?.peek(), - &krate, - &self.hir_arena, - )) - })?; - let hir = self.hir_arena.alloc(hir); - Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) + rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products) + }) + .unwrap_or_else(DepGraph::new_disabled); + Ok(dep_graph) }) } pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> { self.prepare_outputs.compute(|| { - let expansion_result = self.expansion()?; - let (krate, boxed_resolver, _) = &*expansion_result.peek(); + let (krate, boxed_resolver, _) = &*self.expansion()?.peek(); let crate_name = self.crate_name()?.peek(); passes::prepare_outputs( self.session(), self.compiler, - &krate, - &boxed_resolver, + krate, + &*boxed_resolver, &crate_name, ) }) @@ -260,22 +221,20 @@ impl<'tcx> Queries<'tcx> { self.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); - let lint_store = self.expansion()?.peek().2.clone(); - let hir = self.lower_to_hir()?.peek(); let dep_graph = self.dep_graph()?.peek().clone(); - let (ref krate, ref resolver_outputs) = &*hir; - let _timer = self.session().timer("create_global_ctxt"); + let (krate, resolver, lint_store) = self.expansion()?.take(); Ok(passes::create_global_ctxt( self.compiler, lint_store, krate, dep_graph, - resolver_outputs.steal(), + resolver, outputs, &crate_name, &self.queries, &self.gcx, &self.arena, + &self.hir_arena, )) }) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ebd18630e4e..b252409a92a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -654,6 +654,7 @@ fn test_debugging_options_tracking_hash() { untracked!(perf_stats, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); + untracked!(profile_closures, true); untracked!(print_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5479af1dc30..b303f55cf77 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -984,13 +984,16 @@ impl EarlyLintPass for DeprecatedAttr { } fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) { + use rustc_ast::token::CommentKind; + let mut attrs = attrs.iter().peekable(); // Accumulate a single span for sugared doc comments. let mut sugared_span: Option<Span> = None; while let Some(attr) = attrs.next() { - if attr.is_doc_comment() { + let is_doc_comment = attr.is_doc_comment(); + if is_doc_comment { sugared_span = Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi()))); } @@ -1001,13 +1004,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & let span = sugared_span.take().unwrap_or(attr.span); - if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) { + if is_doc_comment || cx.sess().check_name(attr, sym::doc) { cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { let mut err = lint.build("unused doc comment"); err.span_label( node_span, format!("rustdoc does not generate documentation for {}", node_kind), ); + match attr.kind { + AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { + err.help("use `//` for a plain comment"); + } + AttrKind::DocComment(CommentKind::Block, _) => { + err.help("use `/* */` for a plain comment"); + } + } err.emit(); }); } @@ -1084,7 +1095,7 @@ declare_lint! { /// /// ### Explanation /// - /// An function with generics must have its symbol mangled to accommodate + /// A function with generics must have its symbol mangled to accommodate /// the generic parameter. The [`no_mangle` attribute] has no effect in /// this situation, and should be removed. /// @@ -2327,7 +2338,7 @@ impl EarlyLintPass for IncompleteFeatures { .iter() .map(|(name, span, _)| (name, span)) .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) - .filter(|(name, _)| rustc_feature::INCOMPLETE_FEATURES.iter().any(|f| name == &f)) + .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { let mut builder = lint.build(&format!( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 933f7e47c3e..e7322251f5e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -220,17 +220,20 @@ impl LintStore { }) .lint_ids .push(id); + } else { + // Lints belonging to the `future_incompatible` lint group are lints where a + // future version of rustc will cause existing code to stop compiling. + // Lints tied to an edition don't count because they are opt-in. + self.lint_groups + .entry("future_incompatible") + .or_insert(LintGroup { + lint_ids: vec![], + from_plugin: lint.is_plugin, + depr: None, + }) + .lint_ids + .push(id); } - - self.lint_groups - .entry("future_incompatible") - .or_insert(LintGroup { - lint_ids: vec![], - from_plugin: lint.is_plugin, - depr: None, - }) - .lint_ids - .push(id); } } } @@ -273,22 +276,6 @@ impl LintStore { } } - /// This lint should be available with either the old or the new name. - /// - /// Using the old name will not give a warning. - /// You must register a lint with the new name before calling this function. - #[track_caller] - pub fn register_alias(&mut self, old_name: &str, new_name: &str) { - let target = match self.by_name.get(new_name) { - Some(&Id(lint_id)) => lint_id, - _ => bug!("cannot add alias {} for lint {} that does not exist", old_name, new_name), - }; - match self.by_name.insert(old_name.to_string(), Id(target)) { - None | Some(Ignored) => {} - Some(x) => bug!("duplicate specification of lint {} (was {:?})", old_name, x), - } - } - /// This lint should give no warning and have no effect. /// /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints. @@ -334,14 +321,8 @@ impl LintStore { } } - /// Checks the validity of lint names derived from the command line. Returns - /// true if the lint is valid, false otherwise. - pub fn check_lint_name_cmdline( - &self, - sess: &Session, - lint_name: &str, - level: Option<Level>, - ) -> bool { + /// Checks the validity of lint names derived from the command line + pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Level) { let db = match self.check_lint_name(lint_name, None) { CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)), @@ -367,23 +348,19 @@ impl LintStore { }; if let Some(mut db) = db { - if let Some(level) = level { - let msg = format!( - "requested on the command line with `{} {}`", - match level { - Level::Allow => "-A", - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - }, - lint_name - ); - db.note(&msg); - } + let msg = format!( + "requested on the command line with `{} {}`", + match level { + Level::Allow => "-A", + Level::Warn => "-W", + Level::ForceWarn => "--force-warns", + Level::Deny => "-D", + Level::Forbid => "-F", + }, + lint_name + ); + db.note(&msg); db.emit(); - false - } else { - true } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 0ee434f5fb5..c0a059b92aa 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -88,7 +88,7 @@ impl<'s> LintLevelsBuilder<'s> { self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); for &(ref lint_name, level) in &sess.opts.lint_opts { - store.check_lint_name_cmdline(sess, &lint_name, Some(level)); + store.check_lint_name_cmdline(sess, &lint_name, level); let orig_level = level; // If the cap is less than this specified level, e.g., if we've got @@ -110,12 +110,13 @@ impl<'s> LintLevelsBuilder<'s> { } for lint_name in &sess.opts.force_warns { - let valid = store.check_lint_name_cmdline(sess, lint_name, None); - if valid { - let lints = store - .find_lints(lint_name) - .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids")); - self.sets.force_warns.extend(&lints); + store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn); + let lints = store + .find_lints(lint_name) + .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids")); + for id in lints { + let src = LintLevelSource::CommandLine(Symbol::intern(lint_name), Level::ForceWarn); + specs.insert(id, (Level::ForceWarn, src)); } } @@ -131,6 +132,8 @@ impl<'s> LintLevelsBuilder<'s> { id: LintId, (level, src): LevelAndSource, ) { + let (old_level, old_src) = + self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a // `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`. @@ -138,9 +141,7 @@ impl<'s> LintLevelsBuilder<'s> { // This means that this only errors if we're truly lowering the lint // level from forbid. if level != Level::Forbid { - if let (Level::Forbid, old_src) = - self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess) - { + if let Level::Forbid = old_level { // Backwards compatibility check: // // We used to not consider `forbid(lint_group)` @@ -152,9 +153,6 @@ impl<'s> LintLevelsBuilder<'s> { LintLevelSource::Default => false, LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol), LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol), - LintLevelSource::ForceWarn(_symbol) => { - bug!("forced warn lint returned a forbid lint level") - } }; debug!( "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}", @@ -179,7 +177,6 @@ impl<'s> LintLevelsBuilder<'s> { LintLevelSource::CommandLine(_, _) => { diag_builder.note("`forbid` lint level was set on command line"); } - _ => bug!("forced warn lint returned a forbid lint level"), } diag_builder.emit(); }; @@ -216,7 +213,11 @@ impl<'s> LintLevelsBuilder<'s> { } } } - specs.insert(id, (level, src)); + if let Level::ForceWarn = old_level { + specs.insert(id, (old_level, old_src)); + } else { + specs.insert(id, (level, src)); + } } /// Pushes a list of AST lint attributes onto this context. diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index c91dc37b374..3ea5a3bcc3b 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -4,6 +4,8 @@ use rustc_errors::{pluralize, Applicability}; use rustc_hir as hir; use rustc_middle::ty; use rustc_parse_format::{ParseMode, Parser, Piece}; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_span::edition::Edition; use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol}; declare_lint! { @@ -30,6 +32,10 @@ declare_lint! { NON_FMT_PANIC, Warn, "detect single-argument panic!() invocations in which the argument is not a format string", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), + explain_reason: false, + }; report_in_external_macro } @@ -87,7 +93,8 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc cx.struct_span_lint(NON_FMT_PANIC, arg_span, |lint| { let mut l = lint.build("panic message is not a string literal"); - l.note("this is no longer accepted in Rust 2021"); + l.note("this usage of panic!() is deprecated; it will be a hard error in Rust 2021"); + l.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>"); if !span.contains(arg_span) { // No clue where this argument is coming from. l.emit(); diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index f909f159784..292833843e7 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml @@ -5,7 +5,6 @@ version = "0.0.0" edition = "2018" [dependencies] -log = { package = "tracing", version = "0.1" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index dbc9a11100f..9bb1109fc64 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3002,8 +3002,7 @@ declare_lint! { declare_lint! { /// The `disjoint_capture_migration` lint detects variables that aren't completely - /// captured when the feature `capture_disjoint_fields` is enabled and it affects the Drop - /// order of at least one path starting at this variable. + /// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable. /// It can also detect when a variable implements a trait, but one of its field does not and /// the field is captured by a closure and used with the assumption that said field implements /// the same trait as the root variable. @@ -3040,8 +3039,8 @@ declare_lint! { /// /// ### Explanation /// - /// In the above example `p.y` will be dropped at the end of `f` instead of with `c` if - /// the feature `capture_disjoint_fields` is enabled. + /// In the above example, `p.y` will be dropped at the end of `f` instead of + /// with `c` in Rust 2021. /// /// ### Example of auto-trait /// @@ -3049,7 +3048,7 @@ declare_lint! { /// #![deny(disjoint_capture_migration)] /// use std::thread; /// - /// struct Pointer (*mut i32); + /// struct Pointer(*mut i32); /// unsafe impl Send for Pointer {} /// /// fn main() { @@ -3065,12 +3064,16 @@ declare_lint! { /// /// ### Explanation /// - /// In the above example `fptr.0` is captured when feature `capture_disjoint_fields` is enabled. + /// In the above example, only `fptr.0` is captured in Rust 2021. /// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the /// field cannot be sent between thread safely. pub DISJOINT_CAPTURE_MIGRATION, Allow, - "Drop reorder and auto traits error because of `capture_disjoint_fields`" + "detects closures affected by Rust 2021 changes", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), + explain_reason: false, + }; } declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 3372bc716d2..89453e8e73a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -51,6 +51,7 @@ pub enum Applicability { pub enum Level { Allow, Warn, + ForceWarn, Deny, Forbid, } @@ -63,6 +64,7 @@ impl Level { match self { Level::Allow => "allow", Level::Warn => "warn", + Level::ForceWarn => "force-warns", Level::Deny => "deny", Level::Forbid => "forbid", } @@ -145,6 +147,11 @@ pub struct FutureIncompatibleInfo { /// The reason for the lint used by diagnostics to provide /// the right help message pub reason: FutureIncompatibilityReason, + /// Whether to explain the reason to the user. + /// + /// Set to false for lints that already include a more detailed + /// explanation. + pub explain_reason: bool, /// Information about a future breakage, which will /// be emitted in JSON messages to be displayed by Cargo /// for upstream deps @@ -185,6 +192,7 @@ impl FutureIncompatibleInfo { FutureIncompatibleInfo { reference: "", reason: FutureIncompatibilityReason::FutureReleaseError, + explain_reason: true, future_breakage: None, } } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 29fa0b70069..14b4ebf0736 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -23,7 +23,6 @@ rustc_target = { path = "../rustc_target" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -stable_deref_trait = "1.0.0" rustc_ast = { path = "../rustc_ast" } rustc_expand = { path = "../rustc_expand" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index c3afc9f048c..f7778d67d20 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -129,7 +129,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs) { - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -152,7 +152,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -170,7 +170,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } // Collect what we've got so far in the return vector. - let last_crate = tcx.crates().len(); + let last_crate = tcx.crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -184,7 +184,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // If the crate hasn't been included yet and it's not actually required // (e.g., it's an allocator) then we skip it here as well. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) @@ -281,7 +281,7 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> { // All crates are available in an rlib format, so we're just going to link // everything in explicitly so long as it's actually required. - let last_crate = tcx.crates().len(); + let last_crate = tcx.crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| { if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 5e116122179..27723a4b9d8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -312,7 +312,7 @@ pub fn provide(providers: &mut Providers) { // which is to say, its not deterministic in general. But // we believe that libstd is consistently assigned crate // num 1, so it should be enough to resolve #46112. - let mut crates: Vec<CrateNum> = (*tcx.crates()).to_owned(); + let mut crates: Vec<CrateNum> = (*tcx.crates(())).to_owned(); crates.sort(); for &cnum in crates.iter() { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 76007398000..86f056b2b2d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1223,7 +1223,12 @@ impl EncodeContext<'a, 'tcx> { let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind { FnData { asyncness: sig.header.asyncness, - constness: sig.header.constness, + // Can be inside `impl const Trait`, so using sig.header.constness is not reliable + constness: if self.tcx.is_const_fn_raw(def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }, param_names: self.encode_fn_param_names_for_body(body), } } else { @@ -1668,7 +1673,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { empty_proc_macro!(self); - let crates = self.tcx.crates(); + let crates = self.tcx.crates(()); let mut deps = crates .iter() diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 8cb30e72f79..90ad0256aeb 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -28,6 +28,5 @@ rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } chalk-ir = "0.55.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -measureme = "9.1.0" rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 649913dd025..57f507290e8 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -48,6 +48,7 @@ #![feature(associated_type_defaults)] #![feature(iter_zip)] #![feature(thread_local_const_init)] +#![feature(try_reserve)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 8180d853f60..7ac7720a7c5 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -1,7 +1,7 @@ use std::cmp; use crate::ich::StableHashingContext; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; @@ -28,9 +28,6 @@ pub enum LintLevelSource { /// The provided `Level` is the level specified on the command line. /// (The actual level may be lower due to `--cap-lints`.) CommandLine(Symbol, Level), - - /// Lint is being forced to warn no matter what. - ForceWarn(Symbol), } impl LintLevelSource { @@ -39,7 +36,6 @@ impl LintLevelSource { LintLevelSource::Default => symbol::kw::Default, LintLevelSource::Node(name, _, _) => name, LintLevelSource::CommandLine(name, _) => name, - LintLevelSource::ForceWarn(name) => name, } } @@ -48,7 +44,6 @@ impl LintLevelSource { LintLevelSource::Default => DUMMY_SP, LintLevelSource::Node(_, span, _) => span, LintLevelSource::CommandLine(_, _) => DUMMY_SP, - LintLevelSource::ForceWarn(_) => DUMMY_SP, } } } @@ -60,7 +55,6 @@ pub type LevelAndSource = (Level, LintLevelSource); pub struct LintLevelSets { pub list: Vec<LintSet>, pub lint_cap: Level, - pub force_warns: FxHashSet<LintId>, } #[derive(Debug)] @@ -79,11 +73,7 @@ pub enum LintSet { impl LintLevelSets { pub fn new() -> Self { - LintLevelSets { - list: Vec::new(), - lint_cap: Level::Forbid, - force_warns: FxHashSet::default(), - } + LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid } } pub fn get_lint_level( @@ -93,11 +83,6 @@ impl LintLevelSets { aux: Option<&FxHashMap<LintId, LevelAndSource>>, sess: &Session, ) -> LevelAndSource { - // Check whether we should always warn - if self.force_warns.contains(&LintId::of(lint)) { - return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name))); - } - let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); // If `level` is none then we actually assume the default level for this @@ -191,11 +176,11 @@ impl LintLevelMap { impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let LintLevelMap { ref sets, ref id_to_set, .. } = *self; + let LintLevelMap { ref sets, ref id_to_set } = *self; id_to_set.hash_stable(hcx, hasher); - let LintLevelSets { ref list, lint_cap, .. } = *sets; + let LintLevelSets { ref list, lint_cap } = *sets; lint_cap.hash_stable(hcx, hasher); @@ -273,8 +258,8 @@ pub fn struct_lint_level<'s, 'd>( return; } } - (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), - (Level::Warn, None) => sess.struct_warn(""), + (Level::Warn | Level::ForceWarn, Some(span)) => sess.struct_span_warn(span, ""), + (Level::Warn | Level::ForceWarn, None) => sess.struct_warn(""), (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), (Level::Deny | Level::Forbid, None) => sess.struct_err(""), }; @@ -316,6 +301,7 @@ pub fn struct_lint_level<'s, 'd>( Level::Deny => "-D", Level::Forbid => "-F", Level::Allow => "-A", + Level::ForceWarn => "--force-warns", }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { @@ -361,13 +347,6 @@ pub fn struct_lint_level<'s, 'd>( ); } } - LintLevelSource::ForceWarn(_) => { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - "warning forced by `force-warns` commandline option", - ); - } } err.code(DiagnosticId::Lint { name, has_future_breakage }); @@ -398,9 +377,14 @@ pub fn struct_lint_level<'s, 'd>( it will become a hard error in a future release!" .to_owned() }; - let citation = format!("for more information, see {}", future_incompatible.reference); - err.warn(&explanation); - err.note(&citation); + if future_incompatible.explain_reason { + err.warn(&explanation); + } + if !future_incompatible.reference.is_empty() { + let citation = + format!("for more information, see {}", future_incompatible.reference); + err.note(&citation); + } } // Finally, run `decorate`. This function is also responsible for emitting the diagnostic. diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index 1f40b227d91..e9bcbe016c7 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -229,7 +229,7 @@ pub type CrateStoreDyn = dyn CrateStore + sync::Sync; // positions. pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { let mut libs = tcx - .crates() + .crates(()) .iter() .cloned() .filter_map(|cnum| { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index ee3902991e9..f1b1bb9ab88 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -8,12 +8,15 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::sorted_map::SortedMap; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - read_target_uint, write_target_uint, AllocId, InterpError, Pointer, Scalar, ScalarMaybeUninit, - UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, + ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess, + UnsupportedOpInfo, }; +use crate::ty; /// This type represents an Allocation in the Miri/CTFE core engine. /// @@ -121,15 +124,33 @@ impl<Tag> Allocation<Tag> { Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } - pub fn uninit(size: Size, align: Align) -> Self { - Allocation { - bytes: vec![0; size.bytes_usize()], + /// Try to create an Allocation of `size` bytes, failing if there is not enough memory + /// available to the compiler to do so. + pub fn uninit(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'static, Self> { + let mut bytes = Vec::new(); + bytes.try_reserve(size.bytes_usize()).map_err(|_| { + // This results in an error that can happen non-deterministically, since the memory + // available to the compiler can change between runs. Normally queries are always + // deterministic. However, we can be non-determinstic here because all uses of const + // evaluation (including ConstProp!) will make compilation fail (via hard error + // or ICE) upon encountering a `MemoryExhausted` error. + if panic_on_fail { + panic!("Allocation::uninit called with panic_on_fail had allocation failure") + } + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpreation") + }); + InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) + })?; + bytes.resize(size.bytes_usize(), 0); + Ok(Allocation { + bytes, relocations: Relocations::new(), init_mask: InitMask::new(size, false), align, mutability: Mutability::Mut, extra: (), - } + }) } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index cb2a355697d..ab9239585c4 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -423,6 +423,8 @@ pub enum ResourceExhaustionInfo { /// /// The exact limit is set by the `const_eval_limit` attribute. StepLimitReached, + /// There is not enough memory to perform an allocation. + MemoryExhausted, } impl fmt::Display for ResourceExhaustionInfo { @@ -435,6 +437,9 @@ impl fmt::Display for ResourceExhaustionInfo { StepLimitReached => { write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)") } + MemoryExhausted => { + write!(f, "tried to allocate more memory than available to compiler") + } } } } @@ -525,7 +530,8 @@ impl InterpError<'_> { use InterpError::*; match *self { MachineStop(ref err) => err.is_hard_err(), - InterpError::UndefinedBehavior(_) => true, + UndefinedBehavior(_) => true, + ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) => true, _ => false, } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f66ff008801..0986a465729 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1444,7 +1444,7 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } - query all_crate_nums(_: ()) -> &'tcx [CrateNum] { + query crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } @@ -1559,9 +1559,22 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value } } + /// Evaluates whether the given type implements the given trait + /// in the given environment. + /// + /// The inputs are: + /// + /// - the def-id of the trait + /// - the self type + /// - the *other* type parameters of the trait, excluding the self-type + /// - the parameter environment + /// + /// FIXME. If the type, trait, or environment has inference variables, + /// this yields `EvaluatedToUnknown`. It should be refactored + /// to use canonicalization, really. query type_implements_trait( key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, ) - ) -> bool { + ) -> traits::EvaluationResult { desc { "evaluating `type_implements_trait` `{:?}`", key } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 892996189a6..257912ad57e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -11,7 +11,7 @@ use crate::middle; use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata}; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; +use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar}; use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::thir::Thir; use crate::traits; @@ -19,11 +19,12 @@ use crate::ty::query::{self, OnDiskCache, TyCtxtAt}; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; use crate::ty::TyKind::*; use crate::ty::{ - self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, - DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst, - InferTy, IntTy, IntVar, IntVid, List, MainDefinition, ParamConst, ParamTy, PolyFnSig, - Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, - TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, + self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, + ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar, + FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, + MainDefinition, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, + ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, + TyVid, TypeAndMut, UintTy, Visibility, }; use rustc_ast as ast; use rustc_attr as attr; @@ -483,6 +484,10 @@ pub struct TypeckResults<'tcx> { /// This hashset records all instances where we behave /// like this to allow `const_to_pat` to reliably handle this situation. pub treat_byte_string_as_slice: ItemLocalSet, + + /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` + /// on closure size. + pub closure_size_eval: FxHashMap<DefId, ClosureSizeProfileData<'tcx>>, } impl<'tcx> TypeckResults<'tcx> { @@ -509,6 +514,7 @@ impl<'tcx> TypeckResults<'tcx> { closure_fake_reads: Default::default(), generator_interior_types: ty::Binder::dummy(Default::default()), treat_byte_string_as_slice: Default::default(), + closure_size_eval: Default::default(), } } @@ -753,6 +759,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> { ref closure_fake_reads, ref generator_interior_types, ref treat_byte_string_as_slice, + ref closure_size_eval, } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { @@ -779,6 +786,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> { closure_fake_reads.hash_stable(hcx, hasher); generator_interior_types.hash_stable(hcx, hasher); treat_byte_string_as_slice.hash_stable(hcx, hasher); + closure_size_eval.hash_stable(hcx, hasher); }) } } @@ -1044,6 +1052,9 @@ pub struct GlobalCtxt<'tcx> { output_filenames: Arc<OutputFilenames>, pub main_def: Option<MainDefinition>, + + pub(super) vtables_cache: + Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>, } impl<'tcx> TyCtxt<'tcx> { @@ -1201,6 +1212,7 @@ impl<'tcx> TyCtxt<'tcx> { alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), main_def: resolutions.main_def, + vtables_cache: Default::default(), } } @@ -1255,10 +1267,6 @@ impl<'tcx> TyCtxt<'tcx> { self.stability_index(()) } - pub fn crates(self) -> &'tcx [CrateNum] { - self.all_crate_nums(()) - } - pub fn features(self) -> &'tcx rustc_feature::Features { self.features_query(()) } @@ -2815,7 +2823,7 @@ pub fn provide(providers: &mut ty::query::Providers) { tcx.stability().local_deprecation_entry(id) }; providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned(); - providers.all_crate_nums = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()); + providers.crates = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()); providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index eb6d163312c..a40210d5a36 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -pub struct BoundVarsCollector<'tcx> { - binder_index: ty::DebruijnIndex, - vars: BTreeMap<u32, ty::BoundVariableKind>, - // We may encounter the same variable at different levels of binding, so - // this can't just be `Ty` - visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, -} - -impl<'tcx> BoundVarsCollector<'tcx> { - pub fn new() -> Self { - BoundVarsCollector { - binder_index: ty::INNERMOST, - vars: BTreeMap::new(), - visited: SsoHashSet::default(), - } - } - - pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> { - let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0); - for i in 0..max { - if let None = self.vars.get(&i) { - panic!("Unknown variable: {:?}", i); - } - } - - tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) - } -} - -impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - type BreakTy = (); - - fn visit_binder<T: TypeFoldable<'tcx>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow<Self::BreakTy> { - self.binder_index.shift_in(1); - let result = t.super_visit_with(self); - self.binder_index.shift_out(1); - result - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if t.outer_exclusive_binder < self.binder_index - || !self.visited.insert((self.binder_index, t)) - { - return ControlFlow::CONTINUE; - } - use std::collections::btree_map::Entry; - match *t.kind() { - ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { - match self.vars.entry(bound_ty.var.as_u32()) { - Entry::Vacant(entry) => { - entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); - } - Entry::Occupied(entry) => match entry.get() { - ty::BoundVariableKind::Ty(_) => {} - _ => bug!("Conflicting bound vars"), - }, - } - } - - _ => (), - }; - - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - match r { - ty::ReLateBound(index, _br) if *index == self.binder_index => { - // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind` - bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br) - } - - _ => (), - }; - - r.super_visit_with(self) - } -} - pub struct ValidateBoundVars<'tcx> { bound_vars: &'tcx ty::List<ty::BoundVariableKind>, binder_index: ty::DebruijnIndex, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a2abbec7492..7036c05a593 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -18,6 +18,7 @@ pub use adt::*; pub use assoc::*; pub use closure::*; pub use generics::*; +pub use vtable::*; use crate::hir::exports::ExportMap; use crate::ich::StableHashingContext; @@ -94,6 +95,7 @@ pub mod relate; pub mod subst; pub mod trait_def; pub mod util; +pub mod vtable; pub mod walk; mod adt; @@ -126,7 +128,7 @@ pub struct ResolverOutputs { pub main_def: Option<MainDefinition>, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MainDefinition { pub res: Res<ast::NodeId>, pub is_import: bool, @@ -173,6 +175,25 @@ pub enum Visibility { Invisible, } +#[derive( + Clone, + Debug, + PartialEq, + Eq, + Copy, + Hash, + TyEncodable, + TyDecodable, + HashStable, + TypeFoldable +)] +pub struct ClosureSizeProfileData<'tcx> { + /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` + pub before_feature_tys: Ty<'tcx>, + /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` + pub after_feature_tys: Ty<'tcx>, +} + pub trait DefIdTree: Copy { fn parent(self, id: DefId) -> Option<DefId>; @@ -2009,19 +2030,3 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> { fmt::Display::fmt(&self.name, fmt) } } - -#[derive(Clone, Copy, Debug, PartialEq, HashStable)] -pub enum VtblEntry<'tcx> { - MetadataDropInPlace, - MetadataSize, - MetadataAlign, - Vacant, - Method(DefId, SubstsRef<'tcx>), -} - -pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] = - &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign]; - -pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; -pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; -pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index a4f736654af..11399506b96 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -88,23 +88,32 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> { param_env: ty::ParamEnv<'tcx>, } +impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { + fn normalize_generic_arg_after_erasing_regions( + &self, + arg: ty::GenericArg<'tcx>, + ) -> ty::GenericArg<'tcx> { + let arg = self.param_env.and(arg); + self.tcx.normalize_generic_arg_after_erasing_regions(arg) + } +} + impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let arg = self.param_env.and(ty.into()); - self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty() + self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty() } fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let arg = self.param_env.and(c.into()); - self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() + self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const() } #[inline] fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + // FIXME: This *probably* needs canonicalization too! let arg = self.param_env.and(c); self.tcx.normalize_mir_const_after_erasing_regions(arg) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 69e3b8c76c8..c59394a23d0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2248,7 +2248,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let queue = &mut Vec::new(); let mut seen_defs: DefIdSet = Default::default(); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; // Ignore crates that are not direct dependencies. diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 6df8e64fada..2bdb1ccac59 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -558,7 +558,7 @@ impl<'sess> OnDiskCache<'sess> { // maps to None. fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> { tcx.dep_graph.with_ignore(|| { - tcx.all_crate_nums(()) + tcx.crates(()) .iter() .chain(std::iter::once(&LOCAL_CRATE)) .map(|&cnum| { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5dc5080712e..6a7e349819a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,7 +5,6 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; -use crate::ty::fold::BoundVarsCollector; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; @@ -966,17 +965,10 @@ where /// binder. This is commonly used to 'inject' a value T into a /// different binding level. pub fn dummy(value: T) -> Binder<'tcx, T> { - debug_assert!(!value.has_escaping_bound_vars()); + assert!(!value.has_escaping_bound_vars()); Binder(value, ty::List::empty()) } - /// Wraps `value` in a binder, binding higher-ranked vars (if any). - pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> { - let mut collector = BoundVarsCollector::new(); - value.visit_with(&mut collector); - Binder(value, collector.into_vars(tcx)) - } - pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(vars); @@ -2189,7 +2181,7 @@ impl<'tcx> TyS<'tcx> { /// a miscompilation or unsoundness. /// /// When in doubt, use `VarianceDiagInfo::default()` -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VarianceDiagInfo<'tcx> { /// No additional information - this is the default. /// We will not add any additional information to error messages. @@ -2208,7 +2200,7 @@ pub enum VarianceDiagInfo<'tcx> { }, } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VarianceDiagMutKind { /// A mutable raw pointer (`*mut T`) RawPtr, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 79166472acf..ae86f51e6ac 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -215,7 +215,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. if !trait_id.is_local() { - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &(impl_def_id, simplified_self_ty) in tcx.implementations_of_trait((cnum, trait_id)).iter() { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7bf69b9e637..6344327e6aa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; use crate::ty::TyKind::*; -use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::Float as _; use rustc_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; @@ -816,6 +816,15 @@ impl<'tcx> ty::TyS<'tcx> { [component_ty] => component_ty, _ => self, }; + + // FIXME(#86868): We should be canonicalizing, or else moving this to a method of inference + // context, or *something* like that, but for now just avoid passing inference + // variables to queries that can't cope with them. Instead, conservatively + // return "true" (may change drop order). + if query_ty.needs_infer() { + return true; + } + // This doesn't depend on regions, so try to minimize distinct // query keys used. let erased = tcx.normalize_erasing_regions(param_env, query_ty); @@ -905,6 +914,10 @@ impl<'tcx> ty::TyS<'tcx> { } ty } + + pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex { + self.outer_exclusive_binder + } } pub enum ExplicitSelf<'tcx> { diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs new file mode 100644 index 00000000000..0940137a7c3 --- /dev/null +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -0,0 +1,107 @@ +use std::convert::TryFrom; + +use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; +use crate::ty::fold::TypeFoldable; +use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt}; +use rustc_ast::Mutability; + +#[derive(Clone, Copy, Debug, PartialEq, HashStable)] +pub enum VtblEntry<'tcx> { + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Vacant, + Method(DefId, SubstsRef<'tcx>), +} + +pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] = + &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign]; + +pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; +pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; +pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; + +impl<'tcx> TyCtxt<'tcx> { + /// Retrieves an allocation that represents the contents of a vtable. + /// There's a cache within `TyCtxt` so it will be deduplicated. + pub fn vtable_allocation( + self, + ty: Ty<'tcx>, + poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + ) -> AllocId { + let tcx = self; + let vtables_cache = tcx.vtables_cache.lock(); + if let Some(alloc_id) = vtables_cache.get(&(ty, poly_trait_ref)).cloned() { + return alloc_id; + } + drop(vtables_cache); + + // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674 + assert!( + !ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst()) + ); + let param_env = ty::ParamEnv::reveal_all(); + let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); + let trait_ref = tcx.erase_regions(trait_ref); + + tcx.vtable_entries(trait_ref) + } else { + COMMON_VTABLE_ENTRIES + }; + + let layout = + tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation"); + assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); + let size = layout.size.bytes(); + let align = layout.align.abi.bytes(); + + let ptr_size = tcx.data_layout.pointer_size; + let ptr_align = tcx.data_layout.pointer_align.abi; + + let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); + let mut vtable = + Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap(); + + // No need to do any alignment checks on the memory accesses below, because we know the + // allocation is correctly aligned as we created it above. Also we're only offsetting by + // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. + + for (idx, entry) in vtable_entries.iter().enumerate() { + let idx: u64 = u64::try_from(idx).unwrap(); + let scalar = match entry { + VtblEntry::MetadataDropInPlace => { + let instance = ty::Instance::resolve_drop_in_place(tcx, ty); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + fn_ptr.into() + } + VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(), + VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(), + VtblEntry::Vacant => continue, + VtblEntry::Method(def_id, substs) => { + // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674 + assert!(!substs.needs_subst()); + + // Prepare the fn ptr we write into the vtable. + let instance = + ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs) + .expect("resolution failed during building vtable representation") + .polymorphize(tcx); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + fn_ptr.into() + } + }; + vtable + .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar) + .expect("failed to build vtable representation"); + } + + vtable.mutability = Mutability::Not; + let alloc_id = tcx.create_memory_alloc(tcx.intern_const_alloc(vtable)); + let mut vtables_cache = self.vtables_cache.lock(); + vtables_cache.insert((ty, poly_trait_ref), alloc_id); + alloc_id + } +} diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index a0c9b43d5af..4be4372c039 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{ FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable}; +use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -1329,18 +1329,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = tcx.erase_regions(return_ty); // to avoid panics - if !return_ty.has_infer_types() { - if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) { - if tcx.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env)) - { - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) { - err.span_suggestion_hidden( - return_span, - "use `.collect()` to allocate the iterator", - format!("{}{}", snippet, ".collect::<Vec<_>>()"), - Applicability::MaybeIncorrect, - ); - } + if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) { + if tcx + .type_implements_trait((iter_trait, return_ty, ty_params, self.param_env)) + .must_apply_modulo_regions() + { + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) { + err.span_suggestion_hidden( + return_span, + "use `.collect()` to allocate the iterator", + format!("{}{}", snippet, ".collect::<Vec<_>>()"), + Applicability::MaybeIncorrect, + ); } } } diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 536dbad4f76..7a7dbe50e72 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -48,7 +48,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( ); let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); - let ret = ecx.allocate(layout, MemoryKind::Stack); + let ret = ecx.allocate(layout, MemoryKind::Stack)?; let name = with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))); diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 773df7d7b60..992e32e298f 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -201,6 +201,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryExtra = MemoryExtra; + const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error + fn load_mir( ecx: &InterpCx<'mir, 'tcx, Self>, instance: ty::InstanceDef<'tcx>, @@ -306,7 +308,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Size::from_bytes(size as u64), align, interpret::MemoryKind::Machine(MemoryKind::Heap), - ); + )?; ecx.write_scalar(Scalar::Ptr(ptr), dest)?; } _ => { diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs index 5575a97982f..03531a6b004 100644 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ b/compiler/rustc_mir/src/dataflow/mod.rs @@ -7,7 +7,7 @@ pub(crate) use self::drop_flag_effects::*; pub use self::framework::{ fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, - ResultsCursor, ResultsRefCursor, ResultsVisitor, + ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 6f7519e6156..801e4b1e478 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -2,7 +2,6 @@ use std::cell::Cell; use std::fmt; use std::mem; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; @@ -40,10 +39,6 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// The virtual memory system. pub memory: Memory<'mir, 'tcx, M>, - - /// A cache for deduplicating vtables - pub(super) vtables: - FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer<M::PointerTag>>, } // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread @@ -393,7 +388,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { tcx: tcx.at(root_span), param_env, memory: Memory::new(tcx, memory_extra), - vtables: FxHashMap::default(), } } diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs index 23c0fe97c5f..2862670dc7c 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_mir/src/interpret/intern.rs @@ -107,7 +107,6 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: match kind { MemoryKind::Stack | MemoryKind::Machine(const_eval::MemoryKind::Heap) - | MemoryKind::Vtable | MemoryKind::CallerLocation => {} } // Set allocation mutability as appropriate. This is used by LLVM to put things into @@ -429,7 +428,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, ()>, ) -> InterpResult<'tcx, &'tcx Allocation> { - let dest = self.allocate(layout, MemoryKind::Stack); + let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest)?; let ptr = dest.ptr.assert_ptr(); assert_eq!(ptr.offset, Size::ZERO); diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs index 792a4749108..4a3278030b5 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs @@ -91,7 +91,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None)) .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter())); let loc_layout = self.layout_of(loc_ty).unwrap(); - let location = self.allocate(loc_layout, MemoryKind::CallerLocation); + // This can fail if rustc runs out of memory right here. Trying to emit an error would be + // pointless, since that would require allocating more memory than a Location. + let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap(); // Initialize fields. self.write_immediate(file.to_ref(), &self.mplace_field(&location, 0).unwrap().into()) diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs index 0d01dc3c219..5b8c0788cbc 100644 --- a/compiler/rustc_mir/src/interpret/machine.rs +++ b/compiler/rustc_mir/src/interpret/machine.rs @@ -122,6 +122,9 @@ pub trait Machine<'mir, 'tcx>: Sized { /// that is added to the memory so that the work is not done twice. const GLOBAL_KIND: Option<Self::MemoryKind>; + /// Should the machine panic on allocation failures? + const PANIC_ON_ALLOC_FAIL: bool; + /// Whether memory accesses should be alignment-checked. fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 77de19ac674..cb929c21850 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -27,8 +27,6 @@ use crate::util::pretty; pub enum MemoryKind<T> { /// Stack memory. Error if deallocated except during a stack pop. Stack, - /// Memory backing vtables. Error if ever deallocated. - Vtable, /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated. CallerLocation, /// Additional memory kinds a machine wishes to distinguish from the builtin ones. @@ -40,7 +38,6 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> { fn may_leak(self) -> bool { match self { MemoryKind::Stack => false, - MemoryKind::Vtable => true, MemoryKind::CallerLocation => true, MemoryKind::Machine(k) => k.may_leak(), } @@ -51,7 +48,6 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MemoryKind::Stack => write!(f, "stack variable"), - MemoryKind::Vtable => write!(f, "vtable"), MemoryKind::CallerLocation => write!(f, "caller location"), MemoryKind::Machine(m) => write!(f, "{}", m), } @@ -211,9 +207,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind<M::MemoryKind>, - ) -> Pointer<M::PointerTag> { - let alloc = Allocation::uninit(size, align); - self.allocate_with(alloc, kind) + ) -> InterpResult<'static, Pointer<M::PointerTag>> { + let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; + Ok(self.allocate_with(alloc, kind)) } pub fn allocate_bytes( @@ -261,7 +257,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind); + let new_ptr = self.allocate(new_size, new_align, kind)?; let old_size = match old_size_and_align { Some((size, _align)) => size, None => self.get_raw(ptr.alloc_id)?.size(), diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 4c53510ed00..42a304ce412 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -982,7 +982,7 @@ where let (size, align) = self .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); - let ptr = self.memory.allocate(size, align, MemoryKind::Stack); + let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?; let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. @@ -1018,9 +1018,9 @@ where &mut self, layout: TyAndLayout<'tcx>, kind: MemoryKind<M::MemoryKind>, - ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); - MPlaceTy::from_aligned_ptr(ptr, layout) + ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> { + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; + Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) } /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation. diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs index a5bdeb55e78..aea9933b337 100644 --- a/compiler/rustc_mir/src/interpret/terminator.rs +++ b/compiler/rustc_mir/src/interpret/terminator.rs @@ -459,7 +459,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // Find and consult vtable let vtable = receiver_place.vtable(); - let drop_fn = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; + let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we // want for args[0]: We have to project to field 0 because we want @@ -472,7 +472,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { OpTy::from(ImmTy::from_immediate(receiver_place.ptr.into(), this_receiver_ptr)); trace!("Patched self operand to {:#?}", args[0]); // recurse with concrete function - self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind) + self.eval_fn_call(fn_val, caller_abi, &args, ret, unwind) } } } diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs index 072c252be2f..5332e615bc8 100644 --- a/compiler/rustc_mir/src/interpret/traits.rs +++ b/compiler/rustc_mir/src/interpret/traits.rs @@ -2,13 +2,13 @@ use std::convert::TryFrom; use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar}; use rustc_middle::ty::{ - self, Instance, Ty, VtblEntry, COMMON_VTABLE_ENTRIES, COMMON_VTABLE_ENTRIES_ALIGN, + self, Ty, COMMON_VTABLE_ENTRIES, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE, }; -use rustc_target::abi::{Align, LayoutOf, Size}; +use rustc_target::abi::{Align, Size}; use super::util::ensure_monomorphic_enough; -use super::{FnVal, InterpCx, Machine, MemoryKind}; +use super::{FnVal, InterpCx, Machine}; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for @@ -30,78 +30,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ensure_monomorphic_enough(*self.tcx, ty)?; ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; - if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) { - // This means we guarantee that there are no duplicate vtables, we will - // always use the same vtable for the same (Type, Trait) combination. - // That's not what happens in rustc, but emulating per-crate deduplication - // does not sound like it actually makes anything any better. - return Ok(vtable); - } - - let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { - let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); - let trait_ref = self.tcx.erase_regions(trait_ref); - - self.tcx.vtable_entries(trait_ref) - } else { - COMMON_VTABLE_ENTRIES - }; - - let layout = self.layout_of(ty)?; - assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); - let size = layout.size.bytes(); - let align = layout.align.abi.bytes(); - - let tcx = *self.tcx; - let ptr_size = self.pointer_size(); - let ptr_align = tcx.data_layout.pointer_align.abi; - // ///////////////////////////////////////////////////////////////////////////////////////// - // If you touch this code, be sure to also make the corresponding changes to - // `get_vtable` in `rust_codegen_llvm/meth.rs`. - // ///////////////////////////////////////////////////////////////////////////////////////// - let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); - let vtable = self.memory.allocate(vtable_size, ptr_align, MemoryKind::Vtable); - - let drop = Instance::resolve_drop_in_place(tcx, ty); - let drop = self.memory.create_fn_alloc(FnVal::Instance(drop)); - - // No need to do any alignment checks on the memory accesses below, because we know the - // allocation is correctly aligned as we created it above. Also we're only offsetting by - // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. - let scalars = vtable_entries - .iter() - .map(|entry| -> InterpResult<'tcx, _> { - match entry { - VtblEntry::MetadataDropInPlace => Ok(Some(drop.into())), - VtblEntry::MetadataSize => Ok(Some(Scalar::from_uint(size, ptr_size).into())), - VtblEntry::MetadataAlign => Ok(Some(Scalar::from_uint(align, ptr_size).into())), - VtblEntry::Vacant => Ok(None), - VtblEntry::Method(def_id, substs) => { - // Prepare the fn ptr we write into the vtable. - let instance = - ty::Instance::resolve_for_vtable(tcx, self.param_env, *def_id, substs) - .ok_or_else(|| err_inval!(TooGeneric))?; - let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); - Ok(Some(fn_ptr.into())) - } - } - }) - .collect::<Result<Vec<_>, _>>()?; - let mut vtable_alloc = - self.memory.get_mut(vtable.into(), vtable_size, ptr_align)?.expect("not a ZST"); - for (idx, scalar) in scalars.into_iter().enumerate() { - if let Some(scalar) = scalar { - let idx: u64 = u64::try_from(idx).unwrap(); - vtable_alloc.write_ptr_sized(ptr_size * idx, scalar)?; - } - } - - M::after_static_mem_initialized(self, vtable, vtable_size)?; + let vtable_allocation = self.tcx.vtable_allocation(ty, poly_trait_ref); - self.memory.mark_immutable(vtable.alloc_id)?; - assert!(self.vtables.insert((ty, poly_trait_ref), vtable).is_none()); + let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?; - Ok(vtable) + Ok(vtable_ptr) } /// Resolves the function at the specified slot in the provided diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index 1da17bddcb7..a58ded9cfd3 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -29,6 +29,7 @@ Rust MIR: a lowered representation of Rust. #![feature(option_get_or_insert_default)] #![feature(once_cell)] #![feature(control_flow_enum)] +#![feature(try_reserve)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 0ab9aa8e1bf..4bd431dcc6a 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -1071,6 +1071,13 @@ fn create_fn_mono_item<'tcx>( source: Span, ) -> Spanned<MonoItem<'tcx>> { debug!("create_fn_mono_item(instance={})", instance); + + let def_id = instance.def_id(); + if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) + { + monomorphize::util::dump_closure_profile(tcx, instance); + } + respan(source, MonoItem::Fn(instance.polymorphize(tcx))) } diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index 9ca4b6687f1..57d2723cf9c 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -7,6 +7,7 @@ use rustc_hir::lang_items::LangItem; pub mod collector; pub mod partitioning; pub mod polymorphize; +pub mod util; fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_mir/src/monomorphize/util.rs new file mode 100644 index 00000000000..799b4e18c24 --- /dev/null +++ b/compiler/rustc_mir/src/monomorphize/util.rs @@ -0,0 +1,73 @@ +use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt}; +use std::fs::OpenOptions; +use std::io::prelude::*; + +/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on +/// closure size into a CSV. +/// +/// During the same compile all closures dump the information in the same file +/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked. +crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { + let mut file = if let Ok(file) = OpenOptions::new() + .create(true) + .append(true) + .open(&format!("closure_profile_{}.csv", std::process::id())) + { + file + } else { + eprintln!("Cound't open file for writing closure profile"); + return; + }; + + let closure_def_id = closure_instance.def_id(); + let typeck_results = tcx.typeck(closure_def_id.expect_local()); + + if typeck_results.closure_size_eval.contains_key(&closure_def_id) { + let param_env = ty::ParamEnv::reveal_all(); + + let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = + typeck_results.closure_size_eval[&closure_def_id]; + + let before_feature_tys = tcx.subst_and_normalize_erasing_regions( + closure_instance.substs, + param_env, + before_feature_tys, + ); + let after_feature_tys = tcx.subst_and_normalize_erasing_regions( + closure_instance.substs, + param_env, + after_feature_tys, + ); + + let new_size = tcx + .layout_of(param_env.and(after_feature_tys)) + .map(|l| format!("{:?}", l.size.bytes())) + .unwrap_or_else(|e| format!("Failed {:?}", e)); + + let old_size = tcx + .layout_of(param_env.and(before_feature_tys)) + .map(|l| format!("{:?}", l.size.bytes())) + .unwrap_or_else(|e| format!("Failed {:?}", e)); + + let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_span = tcx.hir().span(closure_hir_id); + let src_file = tcx.sess.source_map().span_to_filename(closure_span); + let line_nos = tcx + .sess + .source_map() + .span_to_lines(closure_span) + .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last())) + .unwrap_or_else(|e| format!("{:?}", e)); + + if let Err(e) = writeln!( + file, + "{}, {}, {}, {:?}", + old_size, + new_size, + src_file.prefer_local(), + line_nos + ) { + eprintln!("Error writting to file {}", e.to_string()) + } + } +} diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 4fbd27c89d9..6216ff6656e 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - Binder::bind( - TraitPredicate { - trait_ref: TraitRef::from_method(tcx, trait_id, substs), - }, - tcx, - ), + Binder::dummy(TraitPredicate { trait_ref }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index b56c247127c..e9b68754bdf 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -181,6 +181,7 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> { compile_time_machine!(<'mir, 'tcx>); + const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`) type MemoryKind = !; @@ -393,7 +394,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { .filter(|ret_layout| { !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) }) - .map(|ret_layout| ecx.allocate(ret_layout, MemoryKind::Stack).into()); + .map(|ret_layout| { + ecx.allocate(ret_layout, MemoryKind::Stack) + .expect("couldn't perform small allocation") + .into() + }); ecx.push_stack_frame( Instance::new(def_id, substs), diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index cb1203393b3..17401c24ddd 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -819,7 +819,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( ) -> std::fmt::Result { let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE); // Number of chars needed to represent all line numbers. - let pos_width = format!("{:x}", alloc.size().bytes()).len(); + let pos_width = hex_number_length(alloc.size().bytes()); if num_lines > 0 { write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?; @@ -1018,3 +1018,23 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> { tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect() } } + +/// Calc converted u64 decimal into hex and return it's length in chars +/// +/// ```ignore (cannot-test-private-function) +/// assert_eq!(1, hex_number_length(0)); +/// assert_eq!(1, hex_number_length(1)); +/// assert_eq!(2, hex_number_length(16)); +/// ``` +fn hex_number_length(x: u64) -> usize { + if x == 0 { + return 1; + } + let mut length = 0; + let mut x_left = x; + while x_left > 0 { + x_left /= 16; + length += 1; + } + length +} diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 5511cd4c73b..bedb8b1c58b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -217,6 +217,10 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ty::ClosureKind::FnOnce => {} } + // We won't be building MIR if the closure wasn't local + let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_span = tcx.hir().span(closure_hir_id); + let (capture_index, capture) = if let Some(capture_details) = find_capture_matching_projections( typeck_results, @@ -226,7 +230,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ) { capture_details } else { - if !tcx.features().capture_disjoint_fields { + if !enable_precise_capture(tcx, closure_span) { bug!( "No associated capture found for {:?}[{:#?}] even though \ capture_disjoint_fields isn't enabled", @@ -242,8 +246,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( return Err(from_builder); }; - let closure_ty = typeck_results - .node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); + let closure_ty = typeck_results.node_type(closure_hir_id); let substs = match closure_ty.kind() { ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), @@ -780,3 +783,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } + +/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if +/// user is using Rust Edition 2021 or higher. +fn enable_precise_capture(tcx: TyCtxt<'_>, closure_span: Span) -> bool { + tcx.features().capture_disjoint_fields || closure_span.rust_2021() +} diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c887729c355..60c21757194 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -19,4 +19,3 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ast = { path = "../rustc_ast" } unicode-normalization = "0.1.11" -smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 4069fb2127e..c69d4886bd6 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -17,6 +17,5 @@ rustc_target = { path = "../rustc_target" } rustc_ast = { path = "../rustc_ast" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_lexer = { path = "../rustc_lexer" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index da713566c31..d783852aaca 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -13,6 +13,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; @@ -59,12 +60,73 @@ impl NonConstExpr { fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let mut vis = CheckConstVisitor::new(tcx); tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor()); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckConstTraitVisitor::new(tcx)); } pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_const_bodies, ..*providers }; } +struct CheckConstTraitVisitor<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> CheckConstTraitVisitor<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + CheckConstTraitVisitor { tcx } + } +} + +impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> { + /// check for const trait impls, and errors if the impl uses provided/default functions + /// of the trait being implemented; as those provided functions can be non-const. + fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { + let _: Option<_> = try { + if let hir::ItemKind::Impl(ref imp) = item.kind { + if let hir::Constness::Const = imp.constness { + let did = imp.of_trait.as_ref()?.trait_def_id()?; + let trait_fn_cnt = self + .tcx + .associated_item_def_ids(did) + .iter() + .filter(|did| { + matches!( + self.tcx.associated_item(**did), + ty::AssocItem { kind: ty::AssocKind::Fn, .. } + ) + }) + .count(); + + let impl_fn_cnt = imp + .items + .iter() + .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. })) + .count(); + + // number of trait functions unequal to functions in impl, + // meaning that one or more provided/default functions of the + // trait are used. + if trait_fn_cnt != impl_fn_cnt { + self.tcx + .sess + .struct_span_err( + item.span, + "const trait implementations may not use default functions", + ) + .emit(); + } + } + } + }; + } + + fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {} + + fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {} + + fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {} +} + #[derive(Copy, Clone)] struct CheckConstVisitor<'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index f345d45d178..ddcc6fc123f 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -121,7 +121,7 @@ fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap<Symbol, De let mut collector = FxHashMap::default(); // Collect diagnostic items in other crates. - for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) { + for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() { collect_item(tcx, &mut collector, name, def_id); } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index ca6a7561f3e..34ea5e9abd4 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -2,7 +2,7 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID}; +use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -148,6 +148,20 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } else if let Some((hir_id, _)) = visitor.attr_main_fn { Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main)) } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) { + // non-local main imports are handled below + if def_id.is_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) { + tcx.sess + .struct_span_err( + tcx.hir().span(hir_id), + "the `main` function cannot be declared in an `extern` block", + ) + .emit(); + return None; + } + } + if tcx.main_def.unwrap().is_import && !tcx.features().imported_main { let span = tcx.main_def.unwrap().span; feature_err( diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 118fcca4508..d8abffc5f64 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -309,7 +309,7 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let mut collector = LanguageItemCollector::new(tcx); // Collect lang items in other crates. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { collector.collect_item(item_index, def_id); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 28633faa205..cadb8d23580 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -10,6 +10,7 @@ #![feature(iter_zip)] #![feature(nll)] #![feature(min_specialization)] +#![feature(try_blocks)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index ca9b83876b4..5830245e837 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -938,7 +938,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if !remaining_lib_features.is_empty() { check_features(&mut remaining_lib_features, &local_defined_features); - for &cnum in tcx.crates() { + for &cnum in tcx.crates(()) { if remaining_lib_features.is_empty() { break; } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index de369ba9bbb..629513c7cfe 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -53,7 +53,7 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { } let mut missing = FxHashSet::default(); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 383e30ca29f..5be06dfdc77 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -11,17 +11,10 @@ doctest = false measureme = "9.0.0" rustc-rayon-core = "0.3.1" tracing = "0.1" -rustc_ast = { path = "../rustc_ast" } -rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } -rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" } -rustc_session = { path = "../rustc_session" } -rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 03b578d4ade..76979ab50b9 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1962,6 +1962,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { hir::GenericParamKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. + } | hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Elided } ) }) { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 297383bfed1..4c3cd67ddc6 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -109,9 +109,9 @@ impl<'tcx> SaveContext<'tcx> { // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec<ExternalCrateData> { - let mut result = Vec::with_capacity(self.tcx.crates().len()); + let mut result = Vec::with_capacity(self.tcx.crates(()).len()); - for &n in self.tcx.crates().iter() { + for &n in self.tcx.crates(()).iter() { let span = match self.tcx.extern_crate(n.as_def_id()) { Some(&ExternCrate { span, .. }) => span, None => { diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 4c72920502f..571fd581d3f 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -5,7 +5,6 @@ version = "0.0.0" edition = "2018" [dependencies] -bitflags = "1.2.1" getopts = "0.2" rustc_macros = { path = "../rustc_macros" } tracing = "0.1" diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index e144c8f168e..4c40d0c367e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1209,6 +1209,8 @@ options! { "show backtraces for panics during proc-macro execution (default: no)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code (default: no)"), + profile_closures: bool = (false, parse_no_flag, [UNTRACKED], + "profile size of closures"), profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], "file path to emit profiling data at runtime when using 'profile' \ (default based on relative source path)"), diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 7b7878e9c7f..226fde2343a 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -133,6 +133,8 @@ pub struct ParseSess { pub reached_eof: Lock<bool>, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>, + /// File paths accessed during the build. + pub file_depinfo: Lock<FxHashSet<Symbol>>, /// All the type ascriptions expressions that have had a suggestion for likely path typo. pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>, /// Whether cfg(version) should treat the current release as incomplete @@ -165,6 +167,7 @@ impl ParseSess { symbol_gallery: SymbolGallery::default(), reached_eof: Lock::new(false), env_depinfo: Default::default(), + file_depinfo: Default::default(), type_ascription_path_suggestions: Default::default(), assume_incomplete_release: false, proc_macro_quoted_spans: Default::default(), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d8a58ee18cd..f792e319867 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -792,18 +792,6 @@ impl Session { !self.target.is_like_windows && !self.target.is_like_osx } - pub fn must_not_eliminate_frame_pointers(&self) -> bool { - // "mcount" function relies on stack pointer. - // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>. - if self.instrument_mcount() { - true - } else if let Some(x) = self.opts.cg.force_frame_pointers { - x - } else { - !self.target.eliminate_frame_pointer - } - } - pub fn must_emit_unwind_tables(&self) -> bool { // This is used to control the emission of the `uwtable` attribute on // LLVM functions. diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 08645990c48..4552f14de8b 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -17,6 +17,6 @@ scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "0.1.2" tracing = "0.1" -sha-1 = "0.9" +sha1 = { package = "sha-1", version = "0.9" } sha2 = "0.9" -md-5 = "0.9" +md5 = { package = "md-5", version = "0.9" } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 32031ac7071..77a3ad931d5 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -461,9 +461,13 @@ impl SourceMap { } pub fn is_multiline(&self, sp: Span) -> bool { - let lo = self.lookup_char_pos(sp.lo()); - let hi = self.lookup_char_pos(sp.hi()); - lo.line != hi.line + let lo = self.lookup_source_file_idx(sp.lo()); + let hi = self.lookup_source_file_idx(sp.hi()); + if lo != hi { + return true; + } + let f = (*self.files.borrow().source_files)[lo].clone(); + f.lookup_line(sp.lo()) != f.lookup_line(sp.hi()) } pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> { diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 3df5f161319..53d4dc2922f 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -12,7 +12,6 @@ tracing = "0.1" punycode = "0.4.0" rustc-demangle = "0.1.18" -rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 828f1ac0a79..1a9d04a75ec 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -3,9 +3,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_target::abi::Integer; use rustc_target::spec::abi::Abi; use std::fmt::Write; @@ -553,11 +555,9 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Uint(_) | ty::Bool | ty::Char => { ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty) } - ty::Int(_) => { - let param_env = ty::ParamEnv::reveal_all(); - ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| { - let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size; - let val = sz.sign_extend(b) as i128; + ty::Int(ity) => { + ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| { + let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128; if val < 0 { neg = true; } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index feadd4e891c..bf3ec8f9160 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -20,6 +20,10 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), arch: arch.to_string(), - options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { + mcount: "\u{1}mcount".to_string(), + frame_pointer: FramePointer::NonLeaf, + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index 5682039b865..9fa8ef69d81 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,5 +1,5 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let base = opts("ios", Arch::Arm64); @@ -13,6 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. 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 8a832546d09..a43eb99a1d7 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,5 +1,5 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let base = opts("ios", Arch::Arm64_macabi); @@ -13,6 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. 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 2187015b627..586e4043d79 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,5 +1,5 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let base = opts("ios", Arch::Arm64_sim); @@ -21,6 +21,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index cb6c06b3711..934f3370369 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,5 +1,5 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let base = opts("tvos", Arch::Arm64); @@ -13,6 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, ..base }, } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 8530db179d9..0c8a89210ff 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{SplitDebuginfo, TargetOptions}; +use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -27,7 +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, + frame_pointer: FramePointer::Always, has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs index bef2fce7c83..998d6ffe0fc 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/freebsd_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{FramePointer, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { @@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions { families: vec!["unix".to_string()], has_rpath: true, position_independent_executables: true, - eliminate_frame_pointer: false, // FIXME 43575 + frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit... relro_level: RelroLevel::Full, abi_return_struct_as_int: true, dwarf_version: Some(2), diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 06d71db4af2..f2635f0656d 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions}; +use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -8,7 +8,7 @@ pub fn target() -> Target { base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs index 7002d88c512..92c3a1554ac 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); @@ -6,7 +6,7 @@ pub fn target() -> Target { base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]); base.max_atomic_width = Some(64); - base.eliminate_frame_pointer = false; // Required for backtraces + base.frame_pointer = FramePointer::Always; // Required for backtraces base.linker = Some("i686-w64-mingw32-gcc".to_string()); // Mark all dynamic libraries and executables as compatible with the larger 4GiB address diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs index 228976779f0..d95cb6a82d5 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); @@ -21,7 +21,7 @@ pub fn target() -> Target { // // This may or may not be related to this bug: // https://llvm.org/bugs/show_bug.cgi?id=30879 - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; Target { llvm_target: "i686-unknown-linux-musl".to_string(), diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs index 426df59882d..27a0ac585e3 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); @@ -6,7 +6,7 @@ pub fn target() -> Target { base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]); base.max_atomic_width = Some(64); - base.eliminate_frame_pointer = false; // Required for backtraces + base.frame_pointer = FramePointer::Always; // Required for backtraces // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs index 9d9da50be7a..f598f0f38f3 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/illumos_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { @@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions { is_like_solaris: true, linker_is_gnu: false, limit_rdylib_exports: false, // Linker doesn't support this - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, eh_frame_header: false, late_link_args, diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs index 145aa4a5894..a332e3b847a 100644 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs @@ -1,4 +1,5 @@ -use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType}; pub fn opts() -> TargetOptions { TargetOptions { @@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions { panic_strategy: PanicStrategy::Abort, // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved stack_probes: StackProbeType::Call, - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, position_independent_executables: true, needs_plt: true, relro_level: RelroLevel::Full, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0bf89c3f93b..cfdae9623f3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -671,6 +671,42 @@ impl ToJson for SanitizerSet { } } +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum FramePointer { + /// Forces the machine code generator to always preserve the frame pointers. + Always, + /// Forces the machine code generator to preserve the frame pointers except for the leaf + /// functions (i.e. those that don't call other functions). + NonLeaf, + /// Allows the machine code generator to omit the frame pointers. + /// + /// This option does not guarantee that the frame pointers will be omitted. + MayOmit, +} + +impl FromStr for FramePointer { + type Err = (); + fn from_str(s: &str) -> Result<Self, ()> { + Ok(match s { + "always" => Self::Always, + "non-leaf" => Self::NonLeaf, + "may-omit" => Self::MayOmit, + _ => return Err(()), + }) + } +} + +impl ToJson for FramePointer { + fn to_json(&self) -> Json { + match *self { + Self::Always => "always", + Self::NonLeaf => "non-leaf", + Self::MayOmit => "may-omit", + } + .to_json() + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -1068,8 +1104,8 @@ pub struct TargetOptions { pub tls_model: TlsModel, /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false. pub disable_redzone: bool, - /// Eliminate frame pointers from stack frames if possible. Defaults to true. - pub eliminate_frame_pointer: bool, + /// Frame pointer mode for this target. Defaults to `MayOmit`. + pub frame_pointer: FramePointer, /// Emit each function in its own section. Defaults to true. pub function_sections: bool, /// String to prepend to the name of every dynamic library. Defaults to "lib". @@ -1330,7 +1366,7 @@ impl Default for TargetOptions { code_model: None, tls_model: TlsModel::GeneralDynamic, disable_redzone: false, - eliminate_frame_pointer: true, + frame_pointer: FramePointer::MayOmit, function_sections: true, dll_prefix: "lib".to_string(), dll_suffix: ".so".to_string(), @@ -1833,6 +1869,16 @@ impl Target { } } + if let Some(fp) = obj.remove_key("frame-pointer") { + if let Some(s) = Json::as_string(&fp) { + base.frame_pointer = s + .parse() + .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?; + } else { + incorrect_type.push("frame-pointer".to_string()) + } + } + key!(is_builtin, bool); key!(c_int_width = "target-c-int-width"); key!(os); @@ -1864,7 +1910,6 @@ impl Target { key!(code_model, CodeModel)?; key!(tls_model, TlsModel)?; key!(disable_redzone, bool); - key!(eliminate_frame_pointer, bool); key!(function_sections, bool); key!(dll_prefix); key!(dll_suffix); @@ -2128,7 +2173,7 @@ impl ToJson for Target { target_option_val!(code_model); target_option_val!(tls_model); target_option_val!(disable_redzone); - target_option_val!(eliminate_frame_pointer); + target_option_val!(frame_pointer); target_option_val!(function_sections); target_option_val!(dll_prefix); target_option_val!(dll_suffix); diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs index 29b415e7726..70e9e4aed92 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/openbsd_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{FramePointer, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, abi_return_struct_as_int: true, position_independent_executables: true, - eliminate_frame_pointer: false, // FIXME 43575 + frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit... relro_level: RelroLevel::Full, dwarf_version: Some(2), ..Default::default() diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs index ec24807fec4..fbe4dd5b501 100644 --- a/compiler/rustc_target/src/spec/thumb_base.rs +++ b/compiler/rustc_target/src/spec/thumb_base.rs @@ -27,7 +27,8 @@ // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of // build scripts / gcc flags. -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; pub fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults @@ -52,7 +53,7 @@ pub fn opts() -> TargetOptions { emit_debug_gdb_scripts: false, // LLVM is eager to trash the link register when calling `noreturn` functions, which // breaks debugging. Preserve LR by default to prevent that from happening. - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index dc7597fe7b2..60fd42970c7 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,10 +1,11 @@ -use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "core2".to_string(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; base.pre_link_args.insert( LinkerFlavor::Gcc, vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()], 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 5c35b515f3d..dc765f5228b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2396,7 +2396,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { normalized_ty, ); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) && impls_future { + if self.predicate_may_hold(&try_obligation) + && impls_future.must_apply_modulo_regions() + { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.ends_with('?') { err.span_suggestion_verbose( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d65a596a827..e48aab6f46f 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -542,8 +542,7 @@ fn vtable_trait_first_method_offset<'tcx>( } /// Check whether a `ty` implements given trait(trait_def_id). -/// -/// NOTE: Always return `false` for a type which needs inference. +/// See query definition for details. fn type_implements_trait<'tcx>( tcx: TyCtxt<'tcx>, key: ( @@ -552,7 +551,7 @@ fn type_implements_trait<'tcx>( SubstsRef<'tcx>, ParamEnv<'tcx>, ), -) -> bool { +) -> EvaluationResult { let (trait_def_id, ty, params, param_env) = key; debug!( @@ -562,13 +561,22 @@ fn type_implements_trait<'tcx>( let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) }; + // FIXME(#86868): If there are inference variables anywhere, just give up and assume + // we don't know the answer. This works around the ICEs that would result from + // using those inference variables within the `infer_ctxt` we create below. + // Really we should be using canonicalized variables, or perhaps removing + // this query altogether. + if (trait_ref, param_env).needs_infer() { + return EvaluationResult::EvaluatedToUnknown; + } + let obligation = Obligation { cause: ObligationCause::dummy(), param_env, recursion_depth: 0, predicate: trait_ref.without_const().to_predicate(tcx), }; - tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) + tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation)) } pub fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 388413ae06b..352829234a4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1301,7 +1301,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( ty: self_ty.ptr_metadata_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false) + confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ea5eb2b6866..6cecff4b89d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -492,7 +492,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => Ok(EvaluatedToAmbig), }, - ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => { + ty::PredicateKind::TypeOutlives(pred) => { + if pred.0.is_global() { + Ok(EvaluatedToOk) + } else { + Ok(EvaluatedToOkModuloRegions) + } + } + + ty::PredicateKind::RegionOutlives(..) => { // We do not consider region relationships when evaluating trait matches. Ok(EvaluatedToOkModuloRegions) } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 874289d0293..469ac04e545 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -2,14 +2,114 @@ use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::{sym, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; +use rustc_data_structures::sso::SsoHashSet; +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; +use std::ops::ControlFlow; + use tracing::debug; +// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used +// outside of `resolve_associated_item`. It's just to address #64494, +// #83765, and #85848 which are creating bound types/regions that lose +// their `Binder` *unintentionally*. +// It's ideal to remove `BoundVarsCollector` and just use +// `ty::Binder::*` methods but we use this stopgap until we figure out +// the "real" fix. +struct BoundVarsCollector<'tcx> { + binder_index: ty::DebruijnIndex, + vars: BTreeMap<u32, ty::BoundVariableKind>, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> BoundVarsCollector<'tcx> { + fn new() -> Self { + BoundVarsCollector { + binder_index: ty::INNERMOST, + vars: BTreeMap::new(), + visited: SsoHashSet::default(), + } + } + + fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> { + let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0); + for i in 0..max { + if let None = self.vars.get(&i) { + panic!("Unknown variable: {:?}", i); + } + } + + tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) + } +} + +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { + type BreakTy = (); + + fn visit_binder<T: TypeFoldable<'tcx>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow<Self::BreakTy> { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + if t.outer_exclusive_binder() < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::CONTINUE; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + match self.vars.entry(bound_ty.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Ty(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => { + match self.vars.entry(br.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Region(br.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Region(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + r.super_visit_with(self) + } +} + #[instrument(level = "debug", skip(tcx))] fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, @@ -115,7 +215,12 @@ fn resolve_associated_item<'tcx>( ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?; + + // See FIXME on `BoundVarsCollector`. + let mut bound_vars_collector = BoundVarsCollector::new(); + trait_ref.visit_with(&mut bound_vars_collector); + let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx)); + let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 67a692eceac..313571274c3 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(control_flow_enum)] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(nll)] diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index ebc7b0d0d99..0373033bd28 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -402,7 +402,7 @@ fn instance_def_size_estimate<'tcx>( match instance_def { InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { let mir = tcx.instance_mir(instance_def); - mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum() + mir.basic_blocks().iter().map(|bb| bb.statements.len() + 1).sum() } // Estimate the size of other compiler-generated shims to be 1. _ => 1, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 10a7d69d5d3..2e42d65cce2 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1694,7 +1694,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)), + || traits::supertraits(tcx, ty::Binder::dummy(trait_ref)), || "Self".to_string(), assoc_ident, span, diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 3cbc3d231f8..a09fad3b6b7 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -440,16 +440,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); let expr_ty = fcx.tcx.erase_regions(expr_ty); let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]); - // Check for infer types because cases like `Option<{integer}>` would - // panic otherwise. - if !expr_ty.has_infer_types() - && !ty.has_infer_types() - && fcx.tcx.type_implements_trait(( - from_trait, - ty, - ty_params, - fcx.param_env, - )) + if fcx + .tcx + .type_implements_trait((from_trait, ty, ty_params, fcx.param_env)) + .must_apply_modulo_regions() { label = false; err.span_suggestion( diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 236fec94bdb..afa4d0f1c4d 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1481,6 +1481,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, can_suggest, + fcx.tcx.hir().get_parent_item(id), ); } if !pointing_at_return_type { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 95a1bfbbb01..12d0c14a3d5 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -222,12 +222,7 @@ fn compare_predicate_entailment<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs); - let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars( - impl_m_span, - infer::HigherRankedType, - ty::Binder::bind(impl_m_own_bounds.predicates, tcx), - ); - for predicate in impl_m_own_bounds { + for predicate in impl_m_own_bounds.predicates { let traits::Normalized { value: predicate, obligations } = traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate); @@ -258,14 +253,14 @@ fn compare_predicate_entailment<'tcx>( ); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index f69839bf859..cfe1d1c6871 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -682,9 +682,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); - let encl_item = self.tcx.hir().expect_item(encl_item_id); - if let hir::ItemKind::Fn(..) = encl_item.kind { + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), + span: encl_fn_span, + .. + })) + | Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), + span: encl_fn_span, + .. + })) + | Some(hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), + span: encl_fn_span, + .. + })) = self.tcx.hir().find(encl_item_id) + { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. @@ -698,7 +712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let encl_body = self.tcx.hir().body(encl_body_id); err.encl_body_span = Some(encl_body.value.span); - err.encl_fn_span = Some(encl_item.span); + err.encl_fn_span = Some(*encl_fn_span); } self.tcx.sess.emit_err(err); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index d6b1e56316b..54aab271fdb 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -52,9 +52,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut pointing_at_return_type = false; if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { - pointing_at_return_type = - self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + pointing_at_return_type = self.suggest_missing_return_type( + err, + &fn_decl, + expected, + found, + can_suggest, + fn_id, + ); self.suggest_missing_break_or_return_expr( err, expr, &fn_decl, expected, found, blk_id, fn_id, ); @@ -433,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, + fn_id: hir::HirId, ) -> bool { // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). @@ -465,7 +472,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty); debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); - if ty.kind() == expected.kind() { + let bound_vars = self.tcx.late_bound_vars(fn_id); + let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); + let ty = self.normalize_associated_types_in(sp, ty); + if self.can_coerce(expected, ty) { err.span_label(sp, format!("expected `{}` because of return type", expected)); return true; } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index a259fc6a488..882d5d54b7c 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,11 +3,11 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfTypeArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; -use rustc_errors::struct_span_err; +use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; @@ -21,41 +21,54 @@ fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, n_tps: usize, + n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - match it.kind { - hir::ForeignItemKind::Fn(..) => {} + let (own_counts, span) = match &it.kind { + hir::ForeignItemKind::Fn(.., generics) => { + let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts(); + (own_counts, generics.span) + } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") .span_label(it.span, "expected a function") .emit(); return; } - } + }; - let i_n_tps = tcx.generics_of(it.def_id).own_counts().types; - if i_n_tps != n_tps { - let span = match it.kind { - hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span, - _ => bug!(), - }; + let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool { + if found != expected { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToIntrinsic { + span, + found, + expected, + expected_pluralize: pluralize!(expected), + descr, + }); + false + } else { + true + } + }; - tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic { - span, - found: i_n_tps, - expected: n_tps, - }); - return; + if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") + && gen_count_ok(own_counts.types, n_tps, "type") + && gen_count_ok(own_counts.consts, 0, "const") + { + let fty = tcx.mk_fn_ptr(sig); + let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } - - let fty = tcx.mk_fn_ptr(sig); - let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); - require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } /// Returns the unsafety of the given intrinsic. pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { match intrinsic { + // When adding a new intrinsic to this list, + // it's usually worth updating that intrinsic's documentation + // to note that it's safe to call, since + // safe extern fns are otherwise unprecedented. sym::abort | sym::size_of | sym::min_align_of @@ -121,7 +134,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") { let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -143,7 +156,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, hir::Unsafety::Unsafe) + (n_tps, 0, inputs, output, hir::Unsafety::Unsafe) } else { let unsafety = intrinsic_operation_unsafety(intrinsic_name); let (n_tps, inputs, output) = match intrinsic_name { @@ -372,11 +385,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, unsafety) + (n_tps, 0, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -472,5 +485,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) Abi::PlatformIntrinsic, ); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, sig) } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index f546a0d8963..75299bae5dd 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, (method_sig, method_predicates)); + let method_sig = ty::Binder::dummy(method_sig); // Make sure nobody calls `drop()` explicitly. self.enforce_illegal_method_limitations(&pick); @@ -119,12 +120,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if illegal_sized_bound.is_none() { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); - self.add_obligations(method_ty, all_substs, method_predicates); + self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates); } // Create the final `MethodCallee`. - let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig }; + let callee = MethodCallee { + def_id: pick.item.def_id, + substs: all_substs, + sig: method_sig.skip_binder(), + }; ConfirmResult { callee, illegal_sized_bound } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index be6bc625d89..2136d925423 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index 4c925a6f237..e8748dd062f 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -57,6 +57,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { return; } + + // if it's an inherent `self` method (not `&self` or `&mut self`), it will take + // precedence over the `TryInto` impl, and thus won't break in 2021 edition + if pick.autoderefs == 0 && pick.autoref_or_ptr_adjustment.is_none() { + return; + } + // Inherent impls only require not relying on autoref and autoderef in order to // ensure that the trait implementation won't be used self.tcx.struct_span_lint_hir( diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 3cb4ac8e182..7f4754448ba 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1591,7 +1591,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { _ => {} } } - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id)); } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 581aa087be9..e5f18778f43 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -42,7 +42,9 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts}; +use rustc_middle::ty::{ + self, ClosureSizeProfileData, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts, +}; use rustc_session::lint; use rustc_span::sym; use rustc_span::{MultiSpan, Span, Symbol}; @@ -175,6 +177,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span); } + let after_feature_tys = self.final_upvar_tys(closure_def_id); + // We now fake capture information for all variables that are mentioned within the closure // We do this after handling migrations so that min_captures computes before if !enable_precise_capture(self.tcx, span) { @@ -203,6 +207,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.compute_min_captures(closure_def_id, capture_clause, capture_information); } + let before_feature_tys = self.final_upvar_tys(closure_def_id); + if let Some(closure_substs) = infer_kind { // Unify the (as yet unbound) type variable in the closure // substs with the kind we inferred. @@ -258,6 +264,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); self.typeck_results.borrow_mut().closure_fake_reads.insert(closure_def_id, fake_reads); + if self.tcx.sess.opts.debugging_opts.profile_closures { + self.typeck_results.borrow_mut().closure_size_eval.insert( + closure_def_id, + ClosureSizeProfileData { + before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()), + after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()), + }, + ); + } + // If we are also inferred the closure kind here, // process any deferred resolutions. let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id); @@ -495,11 +511,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |lint| { let mut diagnostics_builder = lint.build( format!( - "{} affected for closure because of `capture_disjoint_fields`", + "{} will change in Rust 2021", reasons ) .as_str(), ); + diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>"); let closure_body_span = self.tcx.hir().span(body_id.hir_id); let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(closure_body_span) { @@ -944,12 +961,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]); - self.tcx.type_implements_trait(( - drop_trait, - ty, - ty_params, - self.tcx.param_env(closure_def_id.expect_local()), - )) + self.tcx + .type_implements_trait(( + drop_trait, + ty, + ty_params, + self.tcx.param_env(closure_def_id.expect_local()), + )) + .must_apply_modulo_regions() }; let is_drop_defined_for_ty = is_drop_defined_for_ty(base_path_ty); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 7436edccf84..0e063c86f2f 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1087,14 +1087,9 @@ fn check_method_receiver<'fcx, 'tcx>( debug!("check_method_receiver: sig={:?}", sig); let self_ty = fcx.normalize_associated_types_in(span, self_ty); - let self_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx)); let receiver_ty = sig.inputs()[0]; - let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty); - let receiver_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx)); if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 032cc7ee233..589570f1cb7 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } wbcx.visit_body(body); wbcx.visit_min_capture_map(); + wbcx.eval_closure_size(); wbcx.visit_fake_reads_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); @@ -333,6 +334,19 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { + fn eval_closure_size(&mut self) { + let mut res: FxHashMap<DefId, ClosureSizeProfileData<'tcx>> = Default::default(); + for (closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() { + let closure_hir_id = + self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + + let data = self.resolve(*data, &closure_hir_id); + + res.insert(*closure_def_id, data); + } + + self.typeck_results.closure_size_eval = res; + } fn visit_min_capture_map(&mut self) { let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher( self.fcx.typeck_results.borrow().closure_min_captures.len(), diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 91e65cffc58..b0e5453b7db 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1737,11 +1737,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ty::ReErased => tcx.lifetimes.re_static, _ => r, }); + let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); let mut diag = bad_placeholder_type(tcx, visitor.0, "return type"); - let ret_ty = fn_sig.output(); + let ret_ty = fn_sig.skip_binder().output(); if ret_ty != tcx.ty_error() { if !ret_ty.is_closure() { let ret_ty_str = match ret_ty.kind() { @@ -1767,7 +1768,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } diag.emit(); - ty::Binder::bind(fn_sig, tcx) + fn_sig } None => <dyn AstConv<'_>>::ty_of_fn( &icx, @@ -1811,10 +1812,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id()); let inputs = data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); - ty::Binder::bind( - tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), - tcx, - ) + ty::Binder::dummy(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + )) } Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { @@ -2098,7 +2102,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP param.bounds.iter().for_each(|bound| match bound { hir::GenericBound::Outlives(lt) => { let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, <, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx); + let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound)); predicates.insert((outlives.to_predicate(tcx), lt.span)); } _ => bug!(), diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 1a21c085d53..1e6a240b2f8 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfTypeArgumentsToInstrinsic { - #[message = "intrinsic has wrong number of type \ +pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { + #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] - #[label = "expected {expected} type parameter"] + #[label = "expected {expected} {descr} parameter{expected_pluralize}"] pub span: Span, pub found: usize, pub expected: usize, + pub expected_pluralize: &'a str, + pub descr: &'a str, } #[derive(SessionDiagnostic)] diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1a58ad51f78..ea216786ea2 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1243,6 +1243,20 @@ impl<'a, T> Cursor<'a, T> { prev.map(|prev| &(*prev.as_ptr()).element) } } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front(&self) -> Option<&'a T> { + self.list.front() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back(&self) -> Option<&'a T> { + self.list.back() + } } impl<'a, T> CursorMut<'a, T> { @@ -1506,6 +1520,135 @@ impl<'a, T> CursorMut<'a, T> { self.index = 0; unsafe { self.list.split_off_before_node(self.current, split_off_idx) } } + + /// Appends an element to the front of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in O(1) time. + // `push_front` continues to point to "ghost" when it addes a node to mimic + // the behavior of `insert_before` on an empty list. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn push_front(&mut self, elt: T) { + // Safety: We know that `push_front` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_front(elt); + self.index += 1; + } + + /// Appends an element to the back of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn push_back(&mut self, elt: T) { + // Safety: We know that `push_back` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_back(elt); + if self.current().is_none() { + // The index of "ghost" is the length of the list, so we just need + // to increment self.index to reflect the new length of the list. + self.index += 1; + } + } + + /// Removes the first element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the front element. In that case, it + /// points to the new front element. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn pop_front(&mut self) -> Option<T> { + // We can't check if current is empty, we must check the list directly. + // It is possible for `self.current == None` and the list to be + // non-empty. + if self.list.is_empty() { + None + } else { + // We can't point to the node that we pop. Copying the behavior of + // `remove_current`, we move on the the next node in the sequence. + // If the list is of length 1 then we end pointing to the "ghost" + // node at index 0, which is expected. + if self.list.head == self.current { + self.move_next(); + } else { + self.index -= 1; + } + self.list.pop_front() + } + } + + /// Removes the last element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the back element. In that case, it + /// points to the "ghost" element. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn pop_back(&mut self) -> Option<T> { + if self.list.is_empty() { + None + } else { + if self.list.tail == self.current { + // The index now reflects the length of the list. It was the + // length of the list minus 1, but now the list is 1 smaller. No + // change is needed for `index`. + self.current = None; + } else if self.current.is_none() { + self.index = self.list.len - 1; + } + self.list.pop_back() + } + } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front(&self) -> Option<&T> { + self.list.front() + } + + /// Provides a mutable reference to the front element of the cursor's + /// parent list, or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front_mut(&mut self) -> Option<&mut T> { + self.list.front_mut() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back(&self) -> Option<&T> { + self.list.back() + } + + /// Provides a mutable reference to back element of the cursor's parent + /// list, or `None` if the list is empty. + /// + /// # Examples + /// Building and mutating a list with a cursor, then getting the back element: + /// ``` + /// #![feature(linked_list_cursors)] + /// use std::collections::LinkedList; + /// let mut dl = LinkedList::new(); + /// dl.push_front(3); + /// dl.push_front(2); + /// dl.push_front(1); + /// let mut cursor = dl.cursor_front_mut(); + /// *cursor.current().unwrap() = 99; + /// *cursor.back_mut().unwrap() = 0; + /// let mut contents = dl.into_iter(); + /// assert_eq!(contents.next(), Some(99)); + /// assert_eq!(contents.next(), Some(2)); + /// assert_eq!(contents.next(), Some(0)); + /// assert_eq!(contents.next(), None); + /// ``` + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back_mut(&mut self) -> Option<&mut T> { + self.list.back_mut() + } } /// An iterator produced by calling `drain_filter` on LinkedList. diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index ad643a7bdf1..5a65ed7a962 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -428,3 +428,50 @@ fn test_cursor_mut_insert() { check_links(&m); assert_eq!(m.iter().cloned().collect::<Vec<_>>(), &[200, 201, 202, 203, 1, 100, 101]); } + +#[test] +fn test_cursor_push_front_back() { + let mut ll: LinkedList<u32> = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + let mut c = ll.cursor_front_mut(); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.index(), Some(0)); + c.push_front(0); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.peek_prev(), Some(&mut 0)); + assert_eq!(c.index(), Some(1)); + c.push_back(11); + drop(c); + let p = ll.cursor_back().front().unwrap(); + assert_eq!(p, &0); + assert_eq!(ll, (0..12).collect()); + check_links(&ll); +} + +#[test] +fn test_cursor_pop_front_back() { + let mut ll: LinkedList<u32> = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6]); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.pop_front(), Some(1)); + c.move_prev(); + c.move_prev(); + c.move_prev(); + assert_eq!(c.pop_back(), Some(6)); + let c = c.as_cursor(); + assert_eq!(c.front(), Some(&2)); + assert_eq!(c.back(), Some(&5)); + assert_eq!(c.index(), Some(1)); + drop(c); + assert_eq!(ll, (2..6).collect()); + check_links(&ll); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.current(), Some(&mut 5)); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(5)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(4)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 2); +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7b0291c5f2e..e8bd4bcb01f 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -136,8 +136,7 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)] #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] -#![cfg_attr(bootstrap, feature(try_trait))] -#![cfg_attr(not(bootstrap), feature(try_trait_v2))] +#![feature(try_trait_v2)] #![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 2e2c9b76bd4..d11d4031f77 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -463,7 +463,6 @@ impl<T, A: Allocator> RawVec<T, A> { Ok(()) } - #[cfg(not(no_global_oom_handling))] fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f131182a896..e116ab6483c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -262,6 +262,7 @@ use core::marker::{self, PhantomData, Unpin, Unsize}; use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +#[cfg(not(no_global_oom_handling))] use core::pin::Pin; use core::ptr::{self, NonNull}; #[cfg(not(no_global_oom_handling))] @@ -346,6 +347,7 @@ impl<T> Rc<T> { /// /// let five = Rc::new(5); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> Rc<T> { // There is an implicit weak pointer owned by all the strong @@ -381,6 +383,7 @@ impl<T> Rc<T> { /// } /// } /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "arc_new_cyclic", issue = "75861")] pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> { // Construct the inner in the "uninitialized" state with a single @@ -577,6 +580,7 @@ impl<T> Rc<T> { } /// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] pub fn pin(value: T) -> Pin<Rc<T>> { unsafe { Pin::new_unchecked(Rc::new(value)) } @@ -1473,6 +1477,7 @@ impl<T: ?Sized> Clone for Rc<T> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: Default> Default for Rc<T> { /// Creates a new `Rc<T>`, with the `Default` value for `T`. @@ -1731,6 +1736,7 @@ impl<T: ?Sized> fmt::Pointer for Rc<T> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl<T> From<T> for Rc<T> { /// Converts a generic type `T` into a `Rc<T>` diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index a34f530762d..d0cf6244756 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2769,33 +2769,31 @@ impl<'a> Drain<'a> { /// # Examples /// /// ``` - /// #![feature(string_drain_as_str)] /// let mut s = String::from("abc"); /// let mut drain = s.drain(..); /// assert_eq!(drain.as_str(), "abc"); /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` - #[unstable(feature = "string_drain_as_str", issue = "76905")] // Note: uncomment AsRef impls below when stabilizing. + #[stable(feature = "string_drain_as_str", since = "1.55.0")] pub fn as_str(&self) -> &str { self.iter.as_str() } } -// Uncomment when stabilizing `string_drain_as_str`. -// #[unstable(feature = "string_drain_as_str", issue = "76905")] -// impl<'a> AsRef<str> for Drain<'a> { -// fn as_ref(&self) -> &str { -// self.as_str() -// } -// } -// -// #[unstable(feature = "string_drain_as_str", issue = "76905")] -// impl<'a> AsRef<[u8]> for Drain<'a> { -// fn as_ref(&self) -> &[u8] { -// self.as_str().as_bytes() -// } -// } +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef<str> for Drain<'a> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef<[u8]> for Drain<'a> { + fn as_ref(&self) -> &[u8] { + self.as_str().as_bytes() + } +} #[stable(feature = "drain", since = "1.6.0")] impl Iterator for Drain<'_> { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 742a9d7ba01..4b34a7dc894 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -19,6 +19,7 @@ use core::marker::{PhantomData, Unpin, Unsize}; use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +#[cfg(not(no_global_oom_handling))] use core::pin::Pin; use core::ptr::{self, NonNull}; #[cfg(not(no_global_oom_handling))] @@ -332,6 +333,7 @@ impl<T> Arc<T> { /// /// let five = Arc::new(5); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(data: T) -> Arc<T> { @@ -365,6 +367,7 @@ impl<T> Arc<T> { /// me: me.clone(), /// }); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "arc_new_cyclic", issue = "75861")] pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> { @@ -485,6 +488,7 @@ impl<T> Arc<T> { /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] pub fn pin(data: T) -> Pin<Arc<T>> { unsafe { Pin::new_unchecked(Arc::new(data)) } @@ -2274,6 +2278,7 @@ impl<T: ?Sized> fmt::Pointer for Arc<T> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: Default> Default for Arc<T> { /// Creates a new `Arc<T>`, with the `Default` value for `T`. @@ -2298,6 +2303,7 @@ impl<T: ?Sized + Hash> Hash for Arc<T> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl<T> From<T> for Arc<T> { /// Converts a `T` into an `Arc<T>` diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index ece3cde0015..ba65f0fadbd 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -1,6 +1,7 @@ use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp}; use crate::mem::MaybeUninit; use crate::num::flt2dec; +use crate::num::fmt as numfmt; // Don't inline this so callers don't use the stack space this function // requires unless they have to. @@ -15,7 +16,7 @@ where T: flt2dec::DecodableFloat, { let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64 - let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit<numfmt::Part<'_>>; 4] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_exact_fixed_str( flt2dec::strategy::grisu::format_exact, *num, @@ -41,7 +42,7 @@ where { // enough for f32 and f64 let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array(); - let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit<numfmt::Part<'_>>; 4] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_shortest_str( flt2dec::strategy::grisu::format_shortest, *num, @@ -85,7 +86,7 @@ where T: flt2dec::DecodableFloat, { let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64 - let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit<numfmt::Part<'_>>; 6] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_exact_exp_str( flt2dec::strategy::grisu::format_exact, *num, @@ -112,7 +113,7 @@ where { // enough for f32 and f64 let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array(); - let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit<numfmt::Part<'_>>; 6] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_shortest_exp_str( flt2dec::strategy::grisu::format_shortest, *num, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9ed49c1e302..48142f66915 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -7,13 +7,16 @@ use crate::char::EscapeDebugExtArgs; use crate::iter; use crate::marker::PhantomData; use crate::mem; -use crate::num::flt2dec; +use crate::num::fmt as numfmt; use crate::ops::Deref; use crate::result; use crate::str; mod builders; +#[cfg(not(no_fp_fmt_parse))] mod float; +#[cfg(no_fp_fmt_parse)] +mod nofloat; mod num; #[stable(feature = "fmt_flags_align", since = "1.28.0")] @@ -1423,7 +1426,7 @@ impl<'a> Formatter<'a> { /// Takes the formatted parts and applies the padding. /// Assumes that the caller already has rendered the parts with required precision, /// so that `self.precision` can be ignored. - fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result { + fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { if let Some(mut width) = self.width { // for the sign-aware zero padding, we render the sign first and // behave as if we had no sign from the beginning. @@ -1463,14 +1466,14 @@ impl<'a> Formatter<'a> { } } - fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result { + fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { - // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`. - // It's safe to use for `flt2dec::Part::Num` since every char `c` is between + // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`. + // It's safe to use for `numfmt::Part::Num` since every char `c` is between // `b'0'` and `b'9'`, which means `s` is valid UTF-8. - // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)` + // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)` // since `buf` should be plain ASCII, but it's possible for someone to pass - // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a + // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a // public function. // FIXME: Determine whether this could result in UB. buf.write_str(unsafe { str::from_utf8_unchecked(s) }) @@ -1481,7 +1484,7 @@ impl<'a> Formatter<'a> { } for part in formatted.parts { match *part { - flt2dec::Part::Zero(mut nzeroes) => { + numfmt::Part::Zero(mut nzeroes) => { const ZEROES: &str = // 64 zeroes "0000000000000000000000000000000000000000000000000000000000000000"; while nzeroes > ZEROES.len() { @@ -1492,7 +1495,7 @@ impl<'a> Formatter<'a> { self.buf.write_str(&ZEROES[..nzeroes])?; } } - flt2dec::Part::Num(mut v) => { + numfmt::Part::Num(mut v) => { let mut s = [0; 5]; let len = part.len(); for c in s[..len].iter_mut().rev() { @@ -1501,7 +1504,7 @@ impl<'a> Formatter<'a> { } write_bytes(self.buf, &s[..len])?; } - flt2dec::Part::Copy(buf) => { + numfmt::Part::Copy(buf) => { write_bytes(self.buf, buf)?; } } diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs new file mode 100644 index 00000000000..cfb94cd9de5 --- /dev/null +++ b/library/core/src/fmt/nofloat.rs @@ -0,0 +1,15 @@ +use crate::fmt::{Debug, Formatter, Result}; + +macro_rules! floating { + ($ty:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { + panic!("floating point support is turned off"); + } + } + }; +} + +floating! { f32 } +floating! { f64 } diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index cdd731fdd4d..db45640df48 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -2,7 +2,7 @@ use crate::fmt; use crate::mem::MaybeUninit; -use crate::num::flt2dec; +use crate::num::fmt as numfmt; use crate::ops::{Div, Rem, Sub}; use crate::ptr; use crate::slice; @@ -406,9 +406,9 @@ macro_rules! impl_Exp { }; let parts = &[ - flt2dec::Part::Copy(buf_slice), - flt2dec::Part::Zero(added_precision), - flt2dec::Part::Copy(exp_slice) + numfmt::Part::Copy(buf_slice), + numfmt::Part::Zero(added_precision), + numfmt::Part::Copy(exp_slice) ]; let sign = if !is_nonnegative { "-" @@ -417,7 +417,7 @@ macro_rules! impl_Exp { } else { "" }; - let formatted = flt2dec::Formatted{sign, parts}; + let formatted = numfmt::Formatted{sign, parts}; f.pad_formatted_parts(&formatted) } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index baa0952c8bb..b4311bbe5f4 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -712,6 +712,11 @@ extern "rust-intrinsic" { /// Aborts the execution of the process. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// A more user-friendly and stable version of this operation is /// [`std::process::abort`](../../std/process/fn.abort.html). pub fn abort() -> !; @@ -745,6 +750,11 @@ extern "rust-intrinsic" { /// /// Any use other than with `if` statements will probably not have an effect. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn likely(b: bool) -> bool; @@ -754,6 +764,11 @@ extern "rust-intrinsic" { /// /// Any use other than with `if` statements will probably not have an effect. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn unlikely(b: bool) -> bool; @@ -765,6 +780,11 @@ extern "rust-intrinsic" { /// The size of a type in bytes. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// More specifically, this is the offset in bytes between successive /// items of the same type, including alignment padding. /// @@ -774,6 +794,11 @@ extern "rust-intrinsic" { /// The minimum alignment of a type. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of<T>() -> usize; @@ -796,6 +821,11 @@ extern "rust-intrinsic" { /// Gets a static string slice containing the name of a type. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name<T: ?Sized>() -> &'static str; @@ -804,6 +834,11 @@ extern "rust-intrinsic" { /// function will return the same value for a type regardless of whichever /// crate it is invoked in. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] pub fn type_id<T: ?Sized + 'static>() -> u64; @@ -829,6 +864,11 @@ extern "rust-intrinsic" { /// Gets a reference to a static `Location` indicating where it was called. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// Consider using [`core::panic::Location::caller`] instead. #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] pub fn caller_location() -> &'static crate::panic::Location<'static>; @@ -837,6 +877,11 @@ extern "rust-intrinsic" { /// /// This exists solely for [`mem::forget_unsized`]; normal `forget` uses /// `ManuallyDrop` instead. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")] pub fn forget<T: ?Sized>(_: T); @@ -1090,6 +1135,11 @@ extern "rust-intrinsic" { /// If the actual type neither requires drop glue nor implements /// `Copy`, then the return value of this function is unspecified. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")] pub fn needs_drop<T>() -> bool; @@ -1310,21 +1360,41 @@ extern "rust-intrinsic" { /// Returns the minimum of two `f32` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f32::min`] pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f64::min`] pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f32::max`] pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f64::max`] pub fn maxnumf64(x: f64, y: f64) -> f64; @@ -1438,6 +1508,11 @@ extern "rust-intrinsic" { /// Returns the number of bits set in an integer type `T` /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] @@ -1446,6 +1521,11 @@ extern "rust-intrinsic" { /// Returns the number of leading unset bits (zeroes) in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `leading_zeros` method. For example, /// [`u32::leading_zeros`] @@ -1497,6 +1577,11 @@ extern "rust-intrinsic" { /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `trailing_zeros` method. For example, /// [`u32::trailing_zeros`] @@ -1548,6 +1633,11 @@ extern "rust-intrinsic" { /// Reverses the bytes in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] @@ -1556,6 +1646,11 @@ extern "rust-intrinsic" { /// Reverses the bits in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] @@ -1564,6 +1659,11 @@ extern "rust-intrinsic" { /// Performs checked integer addition. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] @@ -1572,6 +1672,11 @@ extern "rust-intrinsic" { /// Performs checked integer subtraction /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] @@ -1580,6 +1685,11 @@ extern "rust-intrinsic" { /// Performs checked integer multiplication /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] @@ -1649,6 +1759,11 @@ extern "rust-intrinsic" { /// Performs rotate left. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] @@ -1657,6 +1772,11 @@ extern "rust-intrinsic" { /// Performs rotate right. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] @@ -1665,6 +1785,11 @@ extern "rust-intrinsic" { /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] @@ -1672,6 +1797,11 @@ extern "rust-intrinsic" { pub fn wrapping_add<T: Copy>(a: T, b: T) -> T; /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] @@ -1679,6 +1809,11 @@ extern "rust-intrinsic" { pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T; /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] @@ -1687,6 +1822,11 @@ extern "rust-intrinsic" { /// Computes `a + b`, saturating at numeric bounds. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] @@ -1694,6 +1834,11 @@ extern "rust-intrinsic" { pub fn saturating_add<T: Copy>(a: T, b: T) -> T; /// Computes `a - b`, saturating at numeric bounds. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] @@ -1703,6 +1848,11 @@ extern "rust-intrinsic" { /// Returns the value of the discriminant for the variant in 'v'; /// if `T` has no discriminant, returns `0`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant; @@ -1710,6 +1860,11 @@ extern "rust-intrinsic" { /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns `0`. Uninhabited variants will be counted. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`]. #[rustc_const_unstable(feature = "variant_count", issue = "73662")] pub fn variant_count<T>() -> usize; @@ -1732,10 +1887,20 @@ extern "rust-intrinsic" { pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize; /// See documentation of `<*const T>::guaranteed_eq` for details. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool; /// See documentation of `<*const T>::guaranteed_ne` for details. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool; diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 69bd2996efe..91fa1a9ad35 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -130,7 +130,6 @@ where } #[inline] - #[cfg(not(bootstrap))] fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -151,28 +150,6 @@ where } #[inline] - #[cfg(bootstrap)] - fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try<Output = B>, - { - let _use_the_import: ControlFlow<()>; - match self.peeked.take() { - Some(None) => try { init }, - Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { - Ok(acc) => f(acc, v), - Err(e) => { - self.peeked = Some(Some(v)); - R::from_error(e) - } - }, - None => self.iter.try_rfold(init, f), - } - } - - #[inline] fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 41d9993abaa..0032e8c3e47 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2439,7 +2439,6 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - #[cfg(not(bootstrap))] fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E> where Self: Sized, @@ -2466,32 +2465,6 @@ pub trait Iterator { self.try_fold((), check(f)).break_value().transpose() } - /// We're bootstrapping. - #[inline] - #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - #[cfg(bootstrap)] - fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error> - where - Self: Sized, - F: FnMut(&Self::Item) -> R, - R: Try<Output = bool>, - { - #[inline] - fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, R::Error>> - where - F: FnMut(&T) -> R, - R: Try<Output = bool>, - { - move |(), x| match f(&x).into_result() { - Ok(false) => ControlFlow::CONTINUE, - Ok(true) => ControlFlow::Break(Ok(x)), - Err(x) => ControlFlow::Break(Err(x)), - } - } - - self.try_fold((), check(f)).break_value().transpose() - } - /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 73959291481..866cd5ec535 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -87,7 +87,6 @@ #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] -#![cfg_attr(bootstrap, feature(const_fn))] #![feature(const_option)] #![feature(const_precise_live_drops)] #![feature(const_ptr_offset)] @@ -112,7 +111,6 @@ #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(duration_consts_2)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(fundamental)] #![feature(intra_doc_pointers)] @@ -165,7 +163,6 @@ #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 #![feature(no_coverage)] // rust-lang/rust#84605 -#![cfg_attr(bootstrap, feature(target_feature_11))] #![deny(unsafe_op_in_unsafe_fn)] #![deny(or_patterns_back_compat)] @@ -258,7 +255,6 @@ pub mod option; pub mod panic; pub mod panicking; pub mod pin; -pub mod raw; pub mod result; #[unstable(feature = "async_stream", issue = "79024")] pub mod stream; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 2b240455043..271565693d6 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -31,7 +31,7 @@ use crate::hash::Hasher; /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")] -#[cfg_attr(not(bootstrap), lang = "send")] +#[lang = "send"] #[rustc_on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs index 6232ea3e44c..1ff2e8c8228 100644 --- a/library/core/src/num/flt2dec/mod.rs +++ b/library/core/src/num/flt2dec/mod.rs @@ -124,6 +124,7 @@ functions. pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded}; +use super::fmt::{Formatted, Part}; use crate::mem::MaybeUninit; pub mod decoder; @@ -170,107 +171,6 @@ pub fn round_up(d: &mut [u8]) -> Option<u8> { } } -/// Formatted parts. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Part<'a> { - /// Given number of zero digits. - Zero(usize), - /// A literal number up to 5 digits. - Num(u16), - /// A verbatim copy of given bytes. - Copy(&'a [u8]), -} - -impl<'a> Part<'a> { - /// Returns the exact byte length of given part. - pub fn len(&self) -> usize { - match *self { - Part::Zero(nzeroes) => nzeroes, - Part::Num(v) => { - if v < 1_000 { - if v < 10 { - 1 - } else if v < 100 { - 2 - } else { - 3 - } - } else { - if v < 10_000 { 4 } else { 5 } - } - } - Part::Copy(buf) => buf.len(), - } - } - - /// Writes a part into the supplied buffer. - /// Returns the number of written bytes, or `None` if the buffer is not enough. - /// (It may still leave partially written bytes in the buffer; do not rely on that.) - pub fn write(&self, out: &mut [u8]) -> Option<usize> { - let len = self.len(); - if out.len() >= len { - match *self { - Part::Zero(nzeroes) => { - for c in &mut out[..nzeroes] { - *c = b'0'; - } - } - Part::Num(mut v) => { - for c in out[..len].iter_mut().rev() { - *c = b'0' + (v % 10) as u8; - v /= 10; - } - } - Part::Copy(buf) => { - out[..buf.len()].copy_from_slice(buf); - } - } - Some(len) - } else { - None - } - } -} - -/// Formatted result containing one or more parts. -/// This can be written to the byte buffer or converted to the allocated string. -#[allow(missing_debug_implementations)] -#[derive(Clone)] -pub struct Formatted<'a> { - /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. - pub sign: &'static str, - /// Formatted parts to be rendered after a sign and optional zero padding. - pub parts: &'a [Part<'a>], -} - -impl<'a> Formatted<'a> { - /// Returns the exact byte length of combined formatted result. - pub fn len(&self) -> usize { - let mut len = self.sign.len(); - for part in self.parts { - len += part.len(); - } - len - } - - /// Writes all formatted parts into the supplied buffer. - /// Returns the number of written bytes, or `None` if the buffer is not enough. - /// (It may still leave partially written bytes in the buffer; do not rely on that.) - pub fn write(&self, out: &mut [u8]) -> Option<usize> { - if out.len() < self.sign.len() { - return None; - } - out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); - - let mut written = self.sign.len(); - for part in self.parts { - let len = part.write(&mut out[written..])?; - written += len; - } - Some(written) - } -} - /// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form /// with at least given number of fractional digits. The result is stored to /// the supplied parts array and a slice of written parts is returned. diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs new file mode 100644 index 00000000000..578288bda25 --- /dev/null +++ b/library/core/src/num/fmt.rs @@ -0,0 +1,108 @@ +//! Shared utilties used by both float and integer formatting. +#![doc(hidden)] +#![unstable( + feature = "numfmt", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +/// Formatted parts. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Part<'a> { + /// Given number of zero digits. + Zero(usize), + /// A literal number up to 5 digits. + Num(u16), + /// A verbatim copy of given bytes. + Copy(&'a [u8]), +} + +impl<'a> Part<'a> { + /// Returns the exact byte length of given part. + pub fn len(&self) -> usize { + match *self { + Part::Zero(nzeroes) => nzeroes, + Part::Num(v) => { + if v < 1_000 { + if v < 10 { + 1 + } else if v < 100 { + 2 + } else { + 3 + } + } else { + if v < 10_000 { 4 } else { 5 } + } + } + Part::Copy(buf) => buf.len(), + } + } + + /// Writes a part into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option<usize> { + let len = self.len(); + if out.len() >= len { + match *self { + Part::Zero(nzeroes) => { + for c in &mut out[..nzeroes] { + *c = b'0'; + } + } + Part::Num(mut v) => { + for c in out[..len].iter_mut().rev() { + *c = b'0' + (v % 10) as u8; + v /= 10; + } + } + Part::Copy(buf) => { + out[..buf.len()].copy_from_slice(buf); + } + } + Some(len) + } else { + None + } + } +} + +/// Formatted result containing one or more parts. +/// This can be written to the byte buffer or converted to the allocated string. +#[allow(missing_debug_implementations)] +#[derive(Clone)] +pub struct Formatted<'a> { + /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. + pub sign: &'static str, + /// Formatted parts to be rendered after a sign and optional zero padding. + pub parts: &'a [Part<'a>], +} + +impl<'a> Formatted<'a> { + /// Returns the exact byte length of combined formatted result. + pub fn len(&self) -> usize { + let mut len = self.sign.len(); + for part in self.parts { + len += part.len(); + } + len + } + + /// Writes all formatted parts into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option<usize> { + if out.len() < self.sign.len() { + return None; + } + out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); + + let mut written = self.sign.len(); + for part in self.parts { + let len = part.write(&mut out[written..])?; + written += len; + } + Some(written) + } +} diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 02434b781e4..81d00c281ad 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -25,10 +25,15 @@ macro_rules! unlikely { } // All these modules are technically private and only exposed for coretests: +#[cfg(not(no_fp_fmt_parse))] pub mod bignum; +#[cfg(not(no_fp_fmt_parse))] pub mod dec2flt; +#[cfg(not(no_fp_fmt_parse))] pub mod diy_float; +#[cfg(not(no_fp_fmt_parse))] pub mod flt2dec; +pub mod fmt; #[macro_use] mod int_macros; // import int_impl! @@ -43,6 +48,7 @@ mod wrapping; pub use wrapping::Wrapping; #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(no_fp_fmt_parse))] pub use dec2flt::ParseFloatError; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index c26b5c67710..c2270c864df 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -51,39 +51,17 @@ use crate::{convert, ops}; pub enum ControlFlow<B, C = ()> { /// Move on to the next phase of the operation as normal. #[stable(feature = "control_flow_enum_type", since = "1.55.0")] - #[cfg_attr(not(bootstrap), lang = "Continue")] + #[lang = "Continue"] Continue(C), /// Exit the operation without running subsequent phases. #[stable(feature = "control_flow_enum_type", since = "1.55.0")] - #[cfg_attr(not(bootstrap), lang = "Break")] + #[lang = "Break"] Break(B), // Yes, the order of the variants doesn't match the type parameters. // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>` // is a no-op conversion in the `Try` implementation. } -#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] -#[cfg(bootstrap)] -impl<B, C> ops::TryV1 for ControlFlow<B, C> { - type Output = C; - type Error = B; - #[inline] - fn into_result(self) -> Result<Self::Output, Self::Error> { - match self { - ControlFlow::Continue(y) => Ok(y), - ControlFlow::Break(x) => Err(x), - } - } - #[inline] - fn from_error(v: Self::Error) -> Self { - ControlFlow::Break(v) - } - #[inline] - fn from_ok(v: Self::Output) -> Self { - ControlFlow::Continue(v) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl<B, C> ops::TryV2 for ControlFlow<B, C> { type Output = C; @@ -184,31 +162,9 @@ impl<B, C> ControlFlow<B, C> { } } -#[cfg(bootstrap)] -impl<R: ops::TryV1> ControlFlow<R, R::Output> { - /// Create a `ControlFlow` from any type implementing `Try`. - #[inline] - pub(crate) fn from_try(r: R) -> Self { - match R::into_result(r) { - Ok(v) => ControlFlow::Continue(v), - Err(v) => ControlFlow::Break(R::from_error(v)), - } - } - - /// Convert a `ControlFlow` into any type implementing `Try`; - #[inline] - pub(crate) fn into_try(self) -> R { - match self { - ControlFlow::Continue(v) => R::from_ok(v), - ControlFlow::Break(v) => v, - } - } -} - /// These are used only as part of implementing the iterator adapters. /// They have mediocre names and non-obvious semantics, so aren't /// currently on a path to potential stabilization. -#[cfg(not(bootstrap))] impl<R: ops::TryV2> ControlFlow<R, R::Output> { /// Create a `ControlFlow` from any type implementing `Try`. #[inline] diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 139a8c0eec9..85e04740d96 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -147,8 +147,6 @@ mod function; mod generator; mod index; mod range; -#[cfg(bootstrap)] -mod r#try; mod try_trait; mod unsize; @@ -183,19 +181,10 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[stable(feature = "inclusive_range", since = "1.26.0")] pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -pub use self::r#try::Try; - -#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -#[cfg(bootstrap)] -pub(crate) use self::r#try::Try as TryV1; - #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::FromResidual; #[unstable(feature = "try_trait_v2", issue = "84277")] -#[cfg(not(bootstrap))] pub use self::try_trait::Try; #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index bb948376bc7..9bf0382312e 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -737,14 +737,13 @@ impl<T: Clone> Bound<&T> { /// # Examples /// /// ``` - /// #![feature(bound_cloned)] /// use std::ops::Bound::*; /// use std::ops::RangeBounds; /// /// assert_eq!((1..12).start_bound(), Included(&1)); /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` - #[unstable(feature = "bound_cloned", issue = "61356")] + #[stable(feature = "bound_cloned", since = "1.55.0")] pub fn cloned(self) -> Bound<T> { match self { Bound::Unbounded => Bound::Unbounded, diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs deleted file mode 100644 index 9d659e78d3c..00000000000 --- a/library/core/src/ops/try.rs +++ /dev/null @@ -1,61 +0,0 @@ -/// A trait for customizing the behavior of the `?` operator. -/// -/// A type implementing `Try` is one that has a canonical way to view it -/// in terms of a success/failure dichotomy. This trait allows both -/// extracting those success or failure values from an existing instance and -/// creating a new instance from a success or failure value. -#[unstable(feature = "try_trait", issue = "42327")] -#[rustc_on_unimplemented( - on( - all( - any(from_method = "from_error", from_method = "from_ok"), - from_desugaring = "QuestionMark" - ), - message = "the `?` operator can only be used in {ItemContext} \ - that returns `Result` or `Option` \ - (or another type that implements `{Try}`)", - label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", - enclosing_scope = "this function should return `Result` or `Option` to accept `?`" - ), - on( - all(from_method = "into_result", from_desugaring = "QuestionMark"), - message = "the `?` operator can only be applied to values \ - that implement `{Try}`", - label = "the `?` operator cannot be applied to type `{Self}`" - ) -)] -#[doc(alias = "?")] -#[cfg_attr(bootstrap, lang = "try")] -pub trait Try { - /// The type of this value when viewed as successful. - #[unstable(feature = "try_trait", issue = "42327")] - type Output; // This no longer follows its RFC, but is only used in bootstrap. - /// The type of this value when viewed as failed. - #[unstable(feature = "try_trait", issue = "42327")] - type Error; - - /// Applies the "?" operator. A return of `Ok(t)` means that the - /// execution should continue normally, and the result of `?` is the - /// value `t`. A return of `Err(e)` means that execution should branch - /// to the innermost enclosing `catch`, or return from the function. - /// - /// If an `Err(e)` result is returned, the value `e` will be "wrapped" - /// in the return type of the enclosing scope (which must itself implement - /// `Try`). Specifically, the value `X::from_error(From::from(e))` - /// is returned, where `X` is the return type of the enclosing function. - #[cfg_attr(bootstrap, lang = "into_result")] - #[unstable(feature = "try_trait", issue = "42327")] - fn into_result(self) -> Result<Self::Output, Self::Error>; - - /// Wrap an error value to construct the composite result. For example, - /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. - #[cfg_attr(bootstrap, lang = "from_error")] - #[unstable(feature = "try_trait", issue = "42327")] - fn from_error(v: Self::Error) -> Self; - - /// Wrap an OK value to construct the composite result. For example, - /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. - #[cfg_attr(bootstrap, lang = "from_ok")] - #[unstable(feature = "try_trait", issue = "42327")] - fn from_ok(v: Self::Output) -> Self; -} diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 0eec52a8701..bd46fb6f2cf 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -128,7 +128,7 @@ use crate::ops::ControlFlow; ) )] #[doc(alias = "?")] -#[cfg_attr(not(bootstrap), lang = "Try")] +#[lang = "Try"] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] @@ -186,7 +186,7 @@ pub trait Try: FromResidual { /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); /// assert_eq!(r, Some(4)); /// ``` - #[cfg_attr(not(bootstrap), lang = "from_output")] + #[lang = "from_output"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_output(output: Self::Output) -> Self; @@ -213,7 +213,7 @@ pub trait Try: FromResidual { /// ControlFlow::Break(ControlFlow::Break(3)), /// ); /// ``` - #[cfg_attr(not(bootstrap), lang = "branch")] + #[lang = "branch"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; } @@ -334,7 +334,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> { /// ControlFlow::Break(5), /// ); /// ``` - #[cfg_attr(not(bootstrap), lang = "from_residual")] + #[lang = "from_residual"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_residual(residual: R) -> Self; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index aedfe88f688..13de1cb3092 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1636,38 +1636,6 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { } } -/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish -/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can -/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that -/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result. -#[rustc_diagnostic_item = "none_error"] -#[unstable(feature = "try_trait", issue = "42327")] -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[cfg(bootstrap)] -pub struct NoneError; - -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -impl<T> ops::TryV1 for Option<T> { - type Output = T; - type Error = NoneError; - - #[inline] - fn into_result(self) -> Result<T, NoneError> { - self.ok_or(NoneError) - } - - #[inline] - fn from_ok(v: T) -> Self { - Some(v) - } - - #[inline] - fn from_error(_: NoneError) -> Self { - None - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl<T> ops::TryV2 for Option<T> { type Output = T; diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs deleted file mode 100644 index 6d1e28f4cd7..00000000000 --- a/library/core/src/raw.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![allow(missing_docs)] -#![unstable(feature = "raw", issue = "27751")] -#![rustc_deprecated( - since = "1.53.0", - reason = "use pointer metadata APIs instead https://github.com/rust-lang/rust/issues/81513" -)] - -//! Contains struct definitions for the layout of compiler built-in types. -//! -//! They can be used as targets of transmutes in unsafe code for manipulating -//! the raw representations directly. -//! -//! Their definition should always match the ABI defined in -//! `rustc_middle::ty::layout`. - -/// The representation of a trait object like `&dyn SomeTrait`. -/// -/// This struct has the same layout as types like `&dyn SomeTrait` and -/// `Box<dyn AnotherTrait>`. -/// -/// `TraitObject` is guaranteed to match layouts, but it is not the -/// type of trait objects (e.g., the fields are not directly accessible -/// on a `&dyn SomeTrait`) nor does it control that layout (changing the -/// definition will not change the layout of a `&dyn SomeTrait`). It is -/// only designed to be used by unsafe code that needs to manipulate -/// the low-level details. -/// -/// There is no way to refer to all trait objects generically, so the only -/// way to create values of this type is with functions like -/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true -/// trait object from a `TraitObject` value is with `transmute`. -/// -/// [transmute]: crate::intrinsics::transmute -/// -/// Synthesizing a trait object with mismatched types—one where the -/// vtable does not correspond to the type of the value to which the -/// data pointer points—is highly likely to lead to undefined -/// behavior. -/// -/// # Examples -/// -/// ``` -/// #![feature(raw)] -/// -/// use std::{mem, raw}; -/// -/// // an example trait -/// trait Foo { -/// fn bar(&self) -> i32; -/// } -/// -/// impl Foo for i32 { -/// fn bar(&self) -> i32 { -/// *self + 1 -/// } -/// } -/// -/// let value: i32 = 123; -/// -/// // let the compiler make a trait object -/// let object: &dyn Foo = &value; -/// -/// // look at the raw representation -/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) }; -/// -/// // the data pointer is the address of `value` -/// assert_eq!(raw_object.data as *const i32, &value as *const _); -/// -/// let other_value: i32 = 456; -/// -/// // construct a new object, pointing to a different `i32`, being -/// // careful to use the `i32` vtable from `object` -/// let synthesized: &dyn Foo = unsafe { -/// mem::transmute(raw::TraitObject { -/// data: &other_value as *const _ as *mut (), -/// vtable: raw_object.vtable, -/// }) -/// }; -/// -/// // it should work just as if we had constructed a trait object out of -/// // `other_value` directly -/// assert_eq!(synthesized.bar(), 457); -/// ``` -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(missing_debug_implementations)] -pub struct TraitObject { - pub data: *mut (), - pub vtable: *mut (), -} diff --git a/library/core/src/result.rs b/library/core/src/result.rs index babd0a0b552..325efe721e3 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1626,28 +1626,6 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { } } -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -impl<T, E> ops::TryV1 for Result<T, E> { - type Output = T; - type Error = E; - - #[inline] - fn into_result(self) -> Self { - self - } - - #[inline] - fn from_ok(v: T) -> Self { - Ok(v) - } - - #[inline] - fn from_error(v: E) -> Self { - Err(v) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl<T, E> ops::TryV2 for Result<T, E> { type Output = T; diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 05ff7bb120d..a51d1420748 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -156,7 +156,7 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")] #[rustc_allow_const_fn_unstable(const_fn_transmute)] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 9cf89623d88..fc0a4e74797 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -26,7 +26,21 @@ pub enum Poll<T> { } impl<T> Poll<T> { - /// Changes the ready value of this `Poll` with the closure provided. + /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value. + /// + /// # Examples + /// + /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original: + /// + /// [`String`]: ../../std/string/struct.String.html + /// ``` + /// # use core::task::Poll; + /// let poll_some_string = Poll::Ready(String::from("Hello, World!")); + /// // `Poll::map` takes self *by value*, consuming `poll_some_string` + /// let poll_some_len = poll_some_string.map(|s| s.len()); + /// + /// assert_eq!(poll_some_len, Poll::Ready(13)); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map<U, F>(self, f: F) -> Poll<U> where @@ -38,7 +52,18 @@ impl<T> Poll<T> { } } - /// Returns `true` if this is `Poll::Ready` + /// Returns `true` if the poll is a [`Poll::Ready`] value. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll<u32> = Poll::Ready(2); + /// assert_eq!(x.is_ready(), true); + /// + /// let x: Poll<u32> = Poll::Pending; + /// assert_eq!(x.is_ready(), false); + /// ``` #[inline] #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] @@ -46,7 +71,20 @@ impl<T> Poll<T> { matches!(*self, Poll::Ready(_)) } - /// Returns `true` if this is `Poll::Pending` + /// Returns `true` if the poll is a [`Pending`] value. + /// + /// [`Pending`]: Poll::Pending + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll<u32> = Poll::Ready(2); + /// assert_eq!(x.is_pending(), false); + /// + /// let x: Poll<u32> = Poll::Pending; + /// assert_eq!(x.is_pending(), true); + /// ``` #[inline] #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] @@ -56,7 +94,20 @@ impl<T> Poll<T> { } impl<T, E> Poll<Result<T, E>> { - /// Changes the success value of this `Poll` with the closure provided. + /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a + /// function to a contained `Poll::Ready(Ok)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse()); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Ok(144))); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>> where @@ -69,7 +120,21 @@ impl<T, E> Poll<Result<T, E>> { } } - /// Changes the error value of this `Poll` with the closure provided. + /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by + /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse()); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Err(0))); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>> where @@ -84,7 +149,20 @@ impl<T, E> Poll<Result<T, E>> { } impl<T, E> Poll<Option<Result<T, E>>> { - /// Changes the success value of this `Poll` with the closure provided. + /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by + /// applying a function to a contained `Poll::Ready(Some(Ok))` value, + /// leaving all other variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse())); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Some(Ok(144)))); + /// ``` #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> where @@ -98,7 +176,22 @@ impl<T, E> Poll<Option<Result<T, E>>> { } } - /// Changes the error value of this `Poll` with the closure provided. + /// Maps a `Poll::Ready<Option<Result<T, E>>>` to + /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a + /// contained `Poll::Ready(Some(Err))` value, leaving all other variants + /// untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse())); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Some(Err(0)))); + /// ``` #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> where @@ -128,32 +221,6 @@ impl<T> From<T> for Poll<T> { } } -#[stable(feature = "futures_api", since = "1.36.0")] -#[cfg(bootstrap)] -impl<T, E> ops::TryV1 for Poll<Result<T, E>> { - type Output = Poll<T>; - type Error = E; - - #[inline] - fn into_result(self) -> Result<Self::Output, Self::Error> { - match self { - Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)), - Poll::Ready(Err(e)) => Err(e), - Poll::Pending => Ok(Poll::Pending), - } - } - - #[inline] - fn from_error(e: Self::Error) -> Self { - Poll::Ready(Err(e)) - } - - #[inline] - fn from_ok(x: Self::Output) -> Self { - x.map(Ok) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl<T, E> ops::TryV2 for Poll<Result<T, E>> { type Output = Poll<T>; @@ -184,33 +251,6 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol } } -#[stable(feature = "futures_api", since = "1.36.0")] -#[cfg(bootstrap)] -impl<T, E> ops::TryV1 for Poll<Option<Result<T, E>>> { - type Output = Poll<Option<T>>; - type Error = E; - - #[inline] - fn into_result(self) -> Result<Self::Output, Self::Error> { - match self { - Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))), - Poll::Ready(Some(Err(e))) => Err(e), - Poll::Ready(None) => Ok(Poll::Ready(None)), - Poll::Pending => Ok(Poll::Pending), - } - } - - #[inline] - fn from_error(e: Self::Error) -> Self { - Poll::Ready(Some(Err(e))) - } - - #[inline] - fn from_ok(x: Self::Output) -> Self { - x.map(|x| x.map(Ok)) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> { type Output = Poll<Option<T>>; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 56af3848584..f9d331063f4 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -4,7 +4,6 @@ #![feature(array_map)] #![feature(array_windows)] #![feature(bool_to_option)] -#![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] #![feature(cfg_panic)] @@ -30,7 +29,6 @@ #![feature(try_find)] #![feature(is_sorted)] #![feature(pattern)] -#![feature(raw)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] #![feature(maybe_uninit_uninit_array)] @@ -38,6 +36,7 @@ #![feature(maybe_uninit_extra)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] +#![feature(numfmt)] #![feature(step_trait)] #![feature(str_internals)] #![feature(test)] diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index dfdbc9305d2..c780bb32ca9 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -97,28 +97,6 @@ fn test_transmute_copy() { assert_eq!(1, unsafe { transmute_copy(&1) }); } -// Remove this test when `std::raw` is removed. -// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs -#[allow(deprecated)] -#[test] -fn test_transmute() { - trait Foo { - fn dummy(&self) {} - } - impl Foo for isize {} - - let a = box 100isize as Box<dyn Foo>; - unsafe { - let x: ::core::raw::TraitObject = transmute(a); - assert!(*(x.data as *const isize) == 100); - let _x: Box<dyn Foo> = transmute(x); - } - - unsafe { - assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]); - } -} - #[test] #[allow(dead_code)] fn test_discriminant_send_sync() { diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs index 960a7ca5ff5..4874e8ec09f 100644 --- a/library/core/tests/num/flt2dec/mod.rs +++ b/library/core/tests/num/flt2dec/mod.rs @@ -2,10 +2,11 @@ use std::mem::MaybeUninit; use std::{fmt, str}; use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded}; -use core::num::flt2dec::{round_up, Formatted, Part, Sign, MAX_SIG_DIGITS}; +use core::num::flt2dec::{round_up, Sign, MAX_SIG_DIGITS}; use core::num::flt2dec::{ to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str, }; +use core::num::fmt::{Formatted, Part}; pub use test::Bencher; diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index f4e5e7751b8..612f083a5c1 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -391,7 +391,6 @@ fn result_opt_conversions() { } #[test] -#[cfg(not(bootstrap))] // Needs the V2 trait fn result_try_trait_v2_branch() { use core::num::NonZeroU32; use core::ops::{ControlFlow::*, Try}; diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index d32a3f1f832..3622bc8294b 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -23,7 +23,6 @@ #![feature(unwind_attributes)] #![feature(abi_thiscall)] #![feature(rustc_attrs)] -#![feature(raw)] #![panic_runtime] #![feature(panic_runtime)] // `real_imp` is unused with Miri, so silence warnings. diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs index 717201aef10..d82669d3e23 100644 --- a/library/proc_macro/src/bridge/buffer.rs +++ b/library/proc_macro/src/bridge/buffer.rs @@ -6,35 +6,6 @@ use std::ops::{Deref, DerefMut}; use std::slice; #[repr(C)] -struct Slice<'a, T> { - data: &'a [T; 0], - len: usize, -} - -unsafe impl<'a, T: Sync> Sync for Slice<'a, T> {} -unsafe impl<'a, T: Sync> Send for Slice<'a, T> {} - -impl<T> Copy for Slice<'a, T> {} -impl<T> Clone for Slice<'a, T> { - fn clone(&self) -> Self { - *self - } -} - -impl<T> From<&'a [T]> for Slice<'a, T> { - fn from(xs: &'a [T]) -> Self { - Slice { data: unsafe { &*(xs.as_ptr() as *const [T; 0]) }, len: xs.len() } - } -} - -impl<T> Deref for Slice<'a, T> { - type Target = [T]; - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } - } -} - -#[repr(C)] pub struct Buffer<T: Copy> { data: *mut T, len: usize, diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index a2953b68564..b968d44fe48 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -55,6 +55,7 @@ macro_rules! with_api { FreeFunctions { fn drop($self: $S::FreeFunctions); fn track_env_var(var: &str, value: Option<&str>); + fn track_path(path: &str); }, TokenStream { fn drop($self: $S::TokenStream); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 7586229504c..53fd58a29d8 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -31,7 +31,6 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] -#![feature(bound_cloned)] #![recursion_limit = "256"] #[unstable(feature = "proc_macro_internals", issue = "27812")] @@ -1235,3 +1234,17 @@ pub mod tracked_env { value } } + +/// Tracked access to additional files. +#[unstable(feature = "track_path", issue = "73921")] +pub mod tracked_path { + + /// Track a file explicitly. + /// + /// Commonly used for tracking asset preprocessing. + #[unstable(feature = "track_path", issue = "73921")] + pub fn path<P: AsRef<str>>(path: P) { + let path: &str = path.as_ref(); + crate::bridge::client::FreeFunctions::track_path(path); + } +} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 9076656f64e..36910143dc9 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -880,8 +880,7 @@ impl OpenOptions { /// This function will return an error under a number of different /// circumstances. Some of these error conditions are listed here, together /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not - /// part of the compatibility contract of the function, especially the - /// [`Other`] kind might change to more specific kinds in the future. + /// part of the compatibility contract of the function. /// /// * [`NotFound`]: The specified file does not exist and neither `create` /// or `create_new` is set. @@ -895,9 +894,11 @@ impl OpenOptions { /// exists. /// * [`InvalidInput`]: Invalid combinations of open options (truncate /// without write access, no access mode set, etc.). - /// * [`Other`]: One of the directory components of the specified file path + /// + /// The following errors don't match any existing [`io::ErrorKind`] at the moment: + /// * One of the directory components of the specified file path /// was not, in fact, a directory. - /// * [`Other`]: Filesystem-level errors: full disk, write permission + /// * Filesystem-level errors: full disk, write permission /// requested on a read-only file system, exceeded disk quota, too many /// open files, too long filename, too many symbolic links in the /// specified path (Unix-like systems only), etc. @@ -913,7 +914,6 @@ impl OpenOptions { /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists /// [`InvalidInput`]: io::ErrorKind::InvalidInput /// [`NotFound`]: io::ErrorKind::NotFound - /// [`Other`]: io::ErrorKind::Other /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> { @@ -2216,7 +2216,7 @@ impl DirBuilder { Some(p) => self.create_dir_all(p)?, None => { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"failed to create whole tree", )); } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index ce8d3a56f7a..127b7bf34a3 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1329,7 +1329,8 @@ fn metadata_access_times() { match (a.created(), b.created()) { (Ok(t1), Ok(t2)) => assert!(t1 <= t2), (Err(e1), Err(e2)) - if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other + if e1.kind() == ErrorKind::Uncategorized + && e2.kind() == ErrorKind::Uncategorized || e1.kind() == ErrorKind::Unsupported && e2.kind() == ErrorKind::Unsupported => {} (a, b) => { diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 56e6f08268c..829ef3d98bb 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -105,6 +105,12 @@ pub enum ErrorKind { /// The connection was reset by the remote server. #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, + /// The remote host is not reachable. + #[unstable(feature = "io_error_more", issue = "86442")] + HostUnreachable, + /// The network containing the remote host is not reachable. + #[unstable(feature = "io_error_more", issue = "86442")] + NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] ConnectionAborted, @@ -119,6 +125,9 @@ pub enum ErrorKind { /// local. #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, + /// The system's networking is down. + #[unstable(feature = "io_error_more", issue = "86442")] + NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] BrokenPipe, @@ -129,6 +138,38 @@ pub enum ErrorKind { /// requested to not occur. #[stable(feature = "rust1", since = "1.0.0")] WouldBlock, + /// A filesystem object is, unexpectedly, not a directory. + /// + /// For example, a filesystem path was specified where one of the intermediate directory + /// components was, in fact, a plain file. + #[unstable(feature = "io_error_more", issue = "86442")] + NotADirectory, + /// The filesystem object is, unexpectedly, a directory. + /// + /// A directory was specified when a non-directory was expected. + #[unstable(feature = "io_error_more", issue = "86442")] + IsADirectory, + /// A non-empty directory was specified where an empty directory was expected. + #[unstable(feature = "io_error_more", issue = "86442")] + DirectoryNotEmpty, + /// The filesystem or storage medium is read-only, but a write operation was attempted. + #[unstable(feature = "io_error_more", issue = "86442")] + ReadOnlyFilesystem, + /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. + /// + /// There was a loop (or excessively long chain) resolving a filesystem object + /// or file IO object. + /// + /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the + /// system-specific limit on the depth of symlink traversal. + #[unstable(feature = "io_error_more", issue = "86442")] + FilesystemLoop, + /// Stale network file handle. + /// + /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated + /// by problems with the network or server. + #[unstable(feature = "io_error_more", issue = "86442")] + StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] InvalidInput, @@ -158,17 +199,78 @@ pub enum ErrorKind { /// [`Ok(0)`]: Ok #[stable(feature = "rust1", since = "1.0.0")] WriteZero, + /// The underlying storage (typically, a filesystem) is full. + /// + /// This does not include out of quota errors. + #[unstable(feature = "io_error_more", issue = "86442")] + StorageFull, + /// Seek on unseekable file. + /// + /// Seeking was attempted on an open file handle which is not suitable for seeking - for + /// example, on Unix, a named pipe opened with `File::open`. + #[unstable(feature = "io_error_more", issue = "86442")] + NotSeekable, + /// Filesystem quota was exceeded. + #[unstable(feature = "io_error_more", issue = "86442")] + FilesystemQuotaExceeded, + /// File larger than allowed or supported. + /// + /// This might arise from a hard limit of the underlying filesystem or file access API, or from + /// an administratively imposed resource limitation. Simple disk full, and out of quota, have + /// their own errors. + #[unstable(feature = "io_error_more", issue = "86442")] + FileTooLarge, + /// Resource is busy. + #[unstable(feature = "io_error_more", issue = "86442")] + ResourceBusy, + /// Executable file is busy. + /// + /// An attempt was made to write to a file which is also in use as a running program. (Not all + /// operating systems detect this situation.) + #[unstable(feature = "io_error_more", issue = "86442")] + ExecutableFileBusy, + /// Deadlock (avoided). + /// + /// A file locking operation would result in deadlock. This situation is typically detected, if + /// at all, on a best-effort basis. + #[unstable(feature = "io_error_more", issue = "86442")] + Deadlock, + /// Cross-device or cross-filesystem (hard) link or rename. + #[unstable(feature = "io_error_more", issue = "86442")] + CrossesDevices, + /// Too many (hard) links to the same filesystem object. + /// + /// The filesystem does not support making so many hardlinks to the same file. + #[unstable(feature = "io_error_more", issue = "86442")] + TooManyLinks, + /// Filename too long. + /// + /// The limit might be from the underlying filesystem or API, or an administratively imposed + /// resource limit. + #[unstable(feature = "io_error_more", issue = "86442")] + FilenameTooLong, + /// Program argument list too long. + /// + /// When trying to run an external program, a system or process limit on the size of the + /// arguments would have been exceeded. + #[unstable(feature = "io_error_more", issue = "86442")] + ArgumentListTooLong, /// This operation was interrupted. /// /// Interrupted operations can typically be retried. #[stable(feature = "rust1", since = "1.0.0")] Interrupted, - /// Any I/O error not part of this list. + + /// A custom error that does not fall under any other I/O error kind. /// - /// Errors that are `Other` now may move to a different or a new - /// [`ErrorKind`] variant in the future. It is not recommended to match - /// an error against `Other` and to expect any additional characteristics, - /// e.g., a specific [`Error::raw_os_error`] return value. + /// This can be used to construct your own [`Error`]s that do not match any + /// [`ErrorKind`]. + /// + /// This [`ErrorKind`] is not used by the standard library. + /// + /// Errors from the standard library that do not fall under any of the I/O + /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. + /// New [`ErrorKind`]s might be added in the future for some of those. #[stable(feature = "rust1", since = "1.0.0")] Other, @@ -191,31 +293,62 @@ pub enum ErrorKind { /// to allocate enough memory. #[stable(feature = "out_of_memory_error", since = "1.54.0")] OutOfMemory, + + /// Any I/O error from the standard library that's not part of this list. + /// + /// Errors that are `Uncategorized` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Uncategorized`; use a wildcard match (`_`) instead. + #[unstable(feature = "io_error_uncategorized", issue = "none")] + #[doc(hidden)] + Uncategorized, } impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { + use ErrorKind::*; match *self { - ErrorKind::NotFound => "entity not found", - ErrorKind::PermissionDenied => "permission denied", - ErrorKind::ConnectionRefused => "connection refused", - ErrorKind::ConnectionReset => "connection reset", - ErrorKind::ConnectionAborted => "connection aborted", - ErrorKind::NotConnected => "not connected", - ErrorKind::AddrInUse => "address in use", - ErrorKind::AddrNotAvailable => "address not available", - ErrorKind::BrokenPipe => "broken pipe", - ErrorKind::AlreadyExists => "entity already exists", - ErrorKind::WouldBlock => "operation would block", - ErrorKind::InvalidInput => "invalid input parameter", - ErrorKind::InvalidData => "invalid data", - ErrorKind::TimedOut => "timed out", - ErrorKind::WriteZero => "write zero", - ErrorKind::Interrupted => "operation interrupted", - ErrorKind::Other => "other os error", - ErrorKind::UnexpectedEof => "unexpected end of file", - ErrorKind::Unsupported => "unsupported", - ErrorKind::OutOfMemory => "out of memory", + AddrInUse => "address in use", + AddrNotAvailable => "address not available", + AlreadyExists => "entity already exists", + ArgumentListTooLong => "argument list too long", + BrokenPipe => "broken pipe", + ResourceBusy => "resource busy", + ConnectionAborted => "connection aborted", + ConnectionRefused => "connection refused", + ConnectionReset => "connection reset", + CrossesDevices => "cross-device link or rename", + Deadlock => "deadlock", + DirectoryNotEmpty => "directory not empty", + ExecutableFileBusy => "executable file busy", + FilenameTooLong => "filename too long", + FilesystemQuotaExceeded => "filesystem quota exceeded", + FileTooLarge => "file too large", + HostUnreachable => "host unreachable", + Interrupted => "operation interrupted", + InvalidData => "invalid data", + InvalidInput => "invalid input parameter", + IsADirectory => "is a directory", + NetworkDown => "network down", + NetworkUnreachable => "network unreachable", + NotADirectory => "not a directory", + StorageFull => "no storage space", + NotConnected => "not connected", + NotFound => "entity not found", + Other => "other error", + OutOfMemory => "out of memory", + PermissionDenied => "permission denied", + ReadOnlyFilesystem => "read-only filesystem or storage medium", + StaleNetworkFileHandle => "stale network file handle", + FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", + NotSeekable => "seek on unseekable file", + TimedOut => "timed out", + TooManyLinks => "too many links", + Uncategorized => "uncategorized error", + UnexpectedEof => "unexpected end of file", + Unsupported => "unsupported", + WouldBlock => "operation would block", + WriteZero => "write zero", } } } @@ -538,7 +671,7 @@ impl Error { /// } /// /// fn main() { - /// // Will print "Other". + /// // Will print "Uncategorized". /// print_error(Error::last_os_error()); /// // Will print "AddrInUse". /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 00b85604a3f..63233613b4b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -277,6 +277,8 @@ pub use self::error::{Error, ErrorKind, Result}; pub use self::stdio::set_output_capture; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout}; +#[unstable(feature = "stdio_locked", issue = "none")] +pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{StderrLock, StdinLock, StdoutLock}; #[unstable(feature = "print_internals", issue = "none")] @@ -1416,6 +1418,27 @@ pub trait Write { /// The default implementation calls [`write`] with either the first nonempty /// buffer provided, or an empty one if none exists. /// + /// # Examples + /// + /// ```no_run + /// use std::io::IoSlice; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut data1 = [1; 8]; + /// let mut data2 = [15; 8]; + /// let io_slice1 = IoSlice::new(&mut data1); + /// let io_slice2 = IoSlice::new(&mut data2); + /// + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write_vectored(&[io_slice1, io_slice2])?; + /// Ok(()) + /// } + /// ``` + /// /// [`write`]: Write::write #[stable(feature = "iovec", since = "1.36.0")] fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { @@ -1644,7 +1667,7 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(Error::new_const(ErrorKind::Other, &"formatter error")) + Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error")) } } } diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 2b0d2b7e0be..293f0e31ce0 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -310,6 +310,48 @@ pub fn stdin() -> Stdin { } } +/// Constructs a new locked handle to the standard input of the current +/// process. +/// +/// Each handle returned is a guard granting locked access to a shared +/// global buffer whose access is synchronized via a mutex. If you need +/// more explicit control over locking, for example, in a multi-threaded +/// program, use the [`io::stdin`] function to obtain an unlocked handle, +/// along with the [`Stdin::lock`] method. +/// +/// The lock is released when the returned guard goes out of scope. The +/// returned guard also implements the [`Read`] and [`BufRead`] traits for +/// accessing the underlying data. +/// +/// **Note**: The mutex locked by this handle is not reentrant. Even in a +/// single-threaded program, calling other code that accesses [`Stdin`] +/// could cause a deadlock or panic, if this locked handle is held across +/// that call. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Read}; +/// +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// let mut handle = io::stdin_locked(); +/// +/// handle.read_to_string(&mut buffer)?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "none")] +pub fn stdin_locked() -> StdinLock<'static> { + stdin().into_locked() +} + impl Stdin { /// Locks this handle to the standard input stream, returning a readable /// guard. @@ -334,7 +376,7 @@ impl Stdin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock<'_> { - StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + self.lock_any() } /// Locks this handle and reads a line of input, appending it to the specified buffer. @@ -367,6 +409,43 @@ impl Stdin { pub fn read_line(&self, buf: &mut String) -> io::Result<usize> { self.lock().read_line(buf) } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `Mutex` is static. + fn lock_any<'a>(&self) -> StdinLock<'a> { + StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + } + + /// Consumes this handle to the standard input stream, locking the + /// shared global buffer associated with the stream and returning a + /// readable guard. + /// + /// The lock is released when the returned guard goes out of scope. The + /// returned guard also implements the [`Read`] and [`BufRead`] traits + /// for accessing the underlying data. + /// + /// It is often simpler to directly get a locked handle using the + /// [`stdin_locked`] function instead, unless nearby code also needs to + /// use an unlocked handle. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdio_locked)] + /// use std::io::{self, Read}; + /// + /// fn main() -> io::Result<()> { + /// let mut buffer = String::new(); + /// let mut handle = io::stdin().into_locked(); + /// + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "none")] + pub fn into_locked(self) -> StdinLock<'static> { + self.lock_any() + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -558,6 +637,42 @@ pub fn stdout() -> Stdout { } } +/// Constructs a new locked handle to the standard output of the current +/// process. +/// +/// Each handle returned is a guard granting locked access to a shared +/// global buffer whose access is synchronized via a mutex. If you need +/// more explicit control over locking, for example, in a multi-threaded +/// program, use the [`io::stdout`] function to obtain an unlocked handle, +/// along with the [`Stdout::lock`] method. +/// +/// The lock is released when the returned guard goes out of scope. The +/// returned guard also implements the [`Write`] trait for writing data. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Write}; +/// +/// fn main() -> io::Result<()> { +/// let mut handle = io::stdout_locked(); +/// +/// handle.write_all(b"hello world")?; +/// +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "none")] +pub fn stdout_locked() -> StdoutLock<'static> { + stdout().into_locked() +} + pub fn cleanup() { if let Some(instance) = STDOUT.get() { // Flush the data and disable buffering during shutdown @@ -595,8 +710,45 @@ impl Stdout { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock<'_> { + self.lock_any() + } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. + fn lock_any<'a>(&self) -> StdoutLock<'a> { StdoutLock { inner: self.inner.lock() } } + + /// Consumes this handle to the standard output stream, locking the + /// shared global buffer associated with the stream and returning a + /// writable guard. + /// + /// The lock is released when the returned lock goes out of scope. The + /// returned guard also implements the [`Write`] trait for writing data. + /// + /// It is often simpler to directly get a locked handle using the + /// [`io::stdout_locked`] function instead, unless nearby code also + /// needs to use an unlocked handle. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdio_locked)] + /// use std::io::{self, Write}; + /// + /// fn main() -> io::Result<()> { + /// let mut handle = io::stdout().into_locked(); + /// + /// handle.write_all(b"hello world")?; + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "none")] + pub fn into_locked(self) -> StdoutLock<'static> { + self.lock_any() + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -769,6 +921,35 @@ pub fn stderr() -> Stderr { } } +/// Constructs a new locked handle to the standard error of the current +/// process. +/// +/// This handle is not buffered. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Example +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Write}; +/// +/// fn main() -> io::Result<()> { +/// let mut handle = io::stderr_locked(); +/// +/// handle.write_all(b"hello world")?; +/// +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "none")] +pub fn stderr_locked() -> StderrLock<'static> { + stderr().into_locked() +} + impl Stderr { /// Locks this handle to the standard error stream, returning a writable /// guard. @@ -792,8 +973,42 @@ impl Stderr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock<'_> { + self.lock_any() + } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. + fn lock_any<'a>(&self) -> StderrLock<'a> { StderrLock { inner: self.inner.lock() } } + + /// Locks and consumes this handle to the standard error stream, + /// returning a writable guard. + /// + /// The lock is released when the returned guard goes out of scope. The + /// returned guard also implements the [`Write`] trait for writing + /// data. + /// + /// # Examples + /// + /// ``` + /// #![feature(stdio_locked)] + /// use std::io::{self, Write}; + /// + /// fn foo() -> io::Result<()> { + /// let stderr = io::stderr(); + /// let mut handle = stderr.into_locked(); + /// + /// handle.write_all(b"hello world")?; + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "none")] + pub fn into_locked(self) -> StderrLock<'static> { + self.lock_any() + } } #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/library/std/src/io/stdio/tests.rs b/library/std/src/io/stdio/tests.rs index 04af500268f..b1df6b7131c 100644 --- a/library/std/src/io/stdio/tests.rs +++ b/library/std/src/io/stdio/tests.rs @@ -1,5 +1,6 @@ use super::*; use crate::panic::{RefUnwindSafe, UnwindSafe}; +use crate::sync::mpsc::sync_channel; use crate::thread; #[test] @@ -45,3 +46,121 @@ fn panic_doesnt_poison() { let _a = stderr(); let _a = _a.lock(); } + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stderr() { + test_lock(stderr, stderr_locked); +} +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stdin() { + test_lock(stdin, stdin_locked); +} +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stdout() { + test_lock(stdout, stdout_locked); +} + +// Helper trait to make lock testing function generic. +trait Stdio<'a>: 'static +where + Self::Lock: 'a, +{ + type Lock; + fn lock(&'a self) -> Self::Lock; +} +impl<'a> Stdio<'a> for Stderr { + type Lock = StderrLock<'a>; + fn lock(&'a self) -> StderrLock<'a> { + self.lock() + } +} +impl<'a> Stdio<'a> for Stdin { + type Lock = StdinLock<'a>; + fn lock(&'a self) -> StdinLock<'a> { + self.lock() + } +} +impl<'a> Stdio<'a> for Stdout { + type Lock = StdoutLock<'a>; + fn lock(&'a self) -> StdoutLock<'a> { + self.lock() + } +} + +// Helper trait to make lock testing function generic. +trait StdioOwnedLock: 'static {} +impl StdioOwnedLock for StderrLock<'static> {} +impl StdioOwnedLock for StdinLock<'static> {} +impl StdioOwnedLock for StdoutLock<'static> {} + +// Tests locking on stdio handles by starting two threads and checking that +// they block each other appropriately. +fn test_lock<T, U>(get_handle: fn() -> T, get_locked: fn() -> U) +where + T: for<'a> Stdio<'a>, + U: StdioOwnedLock, +{ + // State enum to track different phases of the test, primarily when + // each lock is acquired and released. + #[derive(Debug, PartialEq)] + enum State { + Start1, + Acquire1, + Start2, + Release1, + Acquire2, + Release2, + } + use State::*; + // Logging vector to be checked to make sure lock acquisitions and + // releases happened in the correct order. + let log = Arc::new(Mutex::new(Vec::new())); + let ((tx1, rx1), (tx2, rx2)) = (sync_channel(0), sync_channel(0)); + let th1 = { + let (log, tx) = (Arc::clone(&log), tx1); + thread::spawn(move || { + log.lock().unwrap().push(Start1); + let handle = get_handle(); + { + let locked = handle.lock(); + log.lock().unwrap().push(Acquire1); + tx.send(Acquire1).unwrap(); // notify of acquisition + tx.send(Release1).unwrap(); // wait for release command + log.lock().unwrap().push(Release1); + } + tx.send(Acquire1).unwrap(); // wait for th2 acquire + { + let locked = handle.lock(); + log.lock().unwrap().push(Acquire1); + } + log.lock().unwrap().push(Release1); + }) + }; + let th2 = { + let (log, tx) = (Arc::clone(&log), tx2); + thread::spawn(move || { + tx.send(Start2).unwrap(); // wait for start command + let locked = get_locked(); + log.lock().unwrap().push(Acquire2); + tx.send(Acquire2).unwrap(); // notify of acquisition + tx.send(Release2).unwrap(); // wait for release command + log.lock().unwrap().push(Release2); + }) + }; + assert_eq!(rx1.recv().unwrap(), Acquire1); // wait for th1 acquire + log.lock().unwrap().push(Start2); + assert_eq!(rx2.recv().unwrap(), Start2); // block th2 + assert_eq!(rx1.recv().unwrap(), Release1); // release th1 + assert_eq!(rx2.recv().unwrap(), Acquire2); // wait for th2 acquire + assert_eq!(rx1.recv().unwrap(), Acquire1); // block th1 + assert_eq!(rx2.recv().unwrap(), Release2); // release th2 + th2.join().unwrap(); + th1.join().unwrap(); + assert_eq!( + *log.lock().unwrap(), + [Start1, Acquire1, Start2, Release1, Acquire2, Release2, Acquire1, Release1] + ); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1cfa71e250f..6f389f000af 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -268,7 +268,6 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(float_interpolation)] #![feature(fn_traits)] #![feature(format_args_nl)] @@ -304,7 +303,6 @@ #![feature(pin_static_ref)] #![feature(prelude_import)] #![feature(ptr_internals)] -#![feature(raw)] #![feature(ready_macro)] #![feature(rustc_attrs)] #![feature(rustc_private)] @@ -456,9 +454,6 @@ pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future)] -pub use core::raw; -#[stable(feature = "rust1", since = "1.0.0")] pub use core::result; #[unstable(feature = "async_stream", issue = "79024")] pub use core::stream; diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index abe9bc24cec..387a3617e5e 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -342,7 +342,7 @@ fn double_bind() { Err(e) => { assert!( e.kind() == ErrorKind::ConnectionRefused - || e.kind() == ErrorKind::Other + || e.kind() == ErrorKind::Uncategorized || e.kind() == ErrorKind::AddrInUse, "unknown error: {} {:?}", e, diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index ba4057bd34c..7f26f419a4b 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -532,5 +532,6 @@ pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> } fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) + f.to_str() + .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8")) } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 9e3880dfd41..ee069eefd45 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -133,7 +133,7 @@ pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! { /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be /// implemented for any closed over variables passed to `catch_unwind`. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "unwind_safe")] +#[cfg_attr(not(test), lang = "unwind_safe")] #[rustc_on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary" @@ -149,7 +149,7 @@ pub auto trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// [`UnwindSafe`] trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "ref_unwind_safe")] +#[cfg_attr(not(test), lang = "ref_unwind_safe")] #[rustc_on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ transferrable across a catch_unwind boundary", diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 6f523728d7b..b46d3dfc1e7 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -452,7 +452,7 @@ impl fmt::Debug for ChildStderr { /// /// let output = if cfg!(target_os = "windows") { /// Command::new("cmd") -/// .args(&["/C", "echo hello"]) +/// .args(["/C", "echo hello"]) /// .output() /// .expect("failed to execute process") /// } else { @@ -609,7 +609,7 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .args(&["-l", "-a"]) + /// .args(["-l", "-a"]) /// .spawn() /// .expect("ls command failed to start"); /// ``` @@ -1658,8 +1658,7 @@ impl Child { /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] /// error is returned. /// - /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function, - /// especially the [`Other`] kind might change to more specific kinds in the future. + /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function. /// /// This is equivalent to sending a SIGKILL on Unix platforms. /// @@ -1680,7 +1679,6 @@ impl Child { /// /// [`ErrorKind`]: io::ErrorKind /// [`InvalidInput`]: io::ErrorKind::InvalidInput - /// [`Other`]: io::ErrorKind::Other #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index e7c5479ab9b..e1d6324c17e 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -217,26 +217,6 @@ impl<T> Mutex<T> { data: UnsafeCell::new(t), } } - - /// Immediately drops the guard, and consequently unlocks the mutex. - /// - /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. - /// Alternately, the guard will be automatically dropped when it goes out of scope. - /// - /// ``` - /// #![feature(mutex_unlock)] - /// - /// use std::sync::Mutex; - /// let mutex = Mutex::new(0); - /// - /// let mut guard = mutex.lock().unwrap(); - /// *guard += 20; - /// Mutex::unlock(guard); - /// ``` - #[unstable(feature = "mutex_unlock", issue = "81872")] - pub fn unlock(guard: MutexGuard<'_, T>) { - drop(guard); - } } impl<T: ?Sized> Mutex<T> { @@ -333,6 +313,26 @@ impl<T: ?Sized> Mutex<T> { } } + /// Immediately drops the guard, and consequently unlocks the mutex. + /// + /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. + /// Alternately, the guard will be automatically dropped when it goes out of scope. + /// + /// ``` + /// #![feature(mutex_unlock)] + /// + /// use std::sync::Mutex; + /// let mutex = Mutex::new(0); + /// + /// let mut guard = mutex.lock().unwrap(); + /// *guard += 20; + /// Mutex::unlock(guard); + /// ``` + #[unstable(feature = "mutex_unlock", issue = "81872")] + pub fn unlock(guard: MutexGuard<'_, T>) { + drop(guard); + } + /// Determines whether the mutex is poisoned. /// /// If another thread is active, the mutex can still become poisoned at any diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 15a76bbd2c9..10c19424953 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -149,7 +149,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { x if x == 1 as i32 => ErrorKind::PermissionDenied, x if x == 32 as i32 => ErrorKind::BrokenPipe, x if x == 110 as i32 => ErrorKind::TimedOut, - _ => ErrorKind::Other, + _ => ErrorKind::Uncategorized, } } diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 5f8839157ea..3f0c99cf742 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -15,7 +15,7 @@ use crate::time::Duration; pub fn init() -> io::Result<()> { if abi::network_init() < 0 { return Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initialize network interface", )); } @@ -51,7 +51,7 @@ impl TcpStream { match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initiate a connection on a socket", )), } @@ -65,7 +65,7 @@ impl TcpStream { ) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initiate a connection on a socket", )), } @@ -73,7 +73,9 @@ impl TcpStream { pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> { abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) + .map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value") + }) } pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> { @@ -81,12 +83,12 @@ impl TcpStream { *self.0.as_inner(), duration.map(|d| d.as_millis() as u64), ) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result<Option<Duration>> { let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value") })?; Ok(duration.map(|d| Duration::from_millis(d))) @@ -94,7 +96,7 @@ impl TcpStream { pub fn write_timeout(&self) -> io::Result<Option<Duration>> { let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value") })?; Ok(duration.map(|d| Duration::from_millis(d))) @@ -102,7 +104,7 @@ impl TcpStream { pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { abi::tcpstream::peek(*self.0.as_inner(), buf) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peek failed")) } pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> { @@ -113,8 +115,9 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter_mut() { - let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?; + let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket") + })?; if ret != 0 { size += ret; @@ -138,7 +141,7 @@ impl TcpStream { for i in ioslice.iter() { size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to write on socket") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to write on socket") })?; } @@ -152,13 +155,13 @@ impl TcpStream { pub fn peer_addr(&self) -> io::Result<SocketAddr> { let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed")); + return Err(io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed")); } }; @@ -170,8 +173,9 @@ impl TcpStream { } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket")) + abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket") + }) } pub fn duplicate(&self) -> io::Result<TcpStream> { @@ -180,22 +184,22 @@ impl TcpStream { pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed")) } pub fn nodelay(&self) -> io::Result<bool> { abi::tcpstream::nodelay(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"nodelay failed")) } pub fn set_ttl(&self, tll: u32) -> io::Result<()> { abi::tcpstream::set_tll(*self.0.as_inner(), tll) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to set TTL")) } pub fn ttl(&self) -> io::Result<u32> { abi::tcpstream::get_tll(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to get TTL")) } pub fn take_error(&self) -> io::Result<Option<io::Error>> { @@ -203,8 +207,9 @@ impl TcpStream { } pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode")) + abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode") + }) } } @@ -230,12 +235,12 @@ impl TcpListener { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new_const(ErrorKind::Other, &"accept failed")); + return Err(io::Error::new_const(ErrorKind::Uncategorized, &"accept failed")); } }; diff --git a/library/std/src/sys/hermit/stdio.rs b/library/std/src/sys/hermit/stdio.rs index 6bff13ca92c..33b8390431f 100644 --- a/library/std/src/sys/hermit/stdio.rs +++ b/library/std/src/sys/hermit/stdio.rs @@ -40,7 +40,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -52,7 +52,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -81,7 +81,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print")) } else { Ok(len as usize) } @@ -93,7 +93,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print")) } else { Ok(len as usize) } diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index 6da79d19f59..8be25f84999 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -39,7 +39,7 @@ impl Thread { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. drop(Box::from_raw(p)); - Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Unable to create thread!")) } else { Ok(Thread { tid: tid }) }; diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index cdfceca19fc..fce6b420732 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -70,7 +70,7 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> { static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { Err(crate::io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"operation can't be trusted to have any effect on SGX", )) } else { @@ -115,11 +115,11 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } else if code == Error::Interrupted as _ { ErrorKind::Interrupted } else if code == Error::Other as _ { - ErrorKind::Other + ErrorKind::Uncategorized } else if code == Error::UnexpectedEof as _ { ErrorKind::UnexpectedEof } else { - ErrorKind::Other + ErrorKind::Uncategorized } } diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 5ccedece0f8..3a69aa039ef 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -466,7 +466,7 @@ pub struct LookupHost(!); impl LookupHost { fn new(host: String) -> io::Result<LookupHost> { - Err(io::Error::new(io::ErrorKind::Other, NonIpSockAddr { host })) + Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host })) } pub fn port(&self) -> u16 { diff --git a/library/std/src/sys/sgx/stdio.rs b/library/std/src/sys/sgx/stdio.rs index 548e28a43d6..8ccf043b5b5 100644 --- a/library/std/src/sys/sgx/stdio.rs +++ b/library/std/src/sys/sgx/stdio.rs @@ -65,7 +65,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - // FIXME: Rust normally maps Unix EBADF to `Other` + // FIXME: Rust normally maps Unix EBADF to `Uncategorized` err.raw_os_error() == Some(abi::Error::BrokenPipe as _) } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index f8ca67c844c..a428ce94c8e 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -358,7 +358,7 @@ impl FileAttr { })) } else { Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"creation time is not available for the filesystem", )) }; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 27d44abeb74..f3535b27128 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -133,29 +133,51 @@ pub use crate::sys::android::signal; pub use libc::signal; pub fn decode_error_kind(errno: i32) -> ErrorKind { + use ErrorKind::*; match errno as libc::c_int { - libc::ECONNREFUSED => ErrorKind::ConnectionRefused, - libc::ECONNRESET => ErrorKind::ConnectionReset, - libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, - libc::EPIPE => ErrorKind::BrokenPipe, - libc::ENOTCONN => ErrorKind::NotConnected, - libc::ECONNABORTED => ErrorKind::ConnectionAborted, - libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - libc::EADDRINUSE => ErrorKind::AddrInUse, - libc::ENOENT => ErrorKind::NotFound, - libc::EINTR => ErrorKind::Interrupted, - libc::EINVAL => ErrorKind::InvalidInput, - libc::ETIMEDOUT => ErrorKind::TimedOut, - libc::EEXIST => ErrorKind::AlreadyExists, - libc::ENOSYS => ErrorKind::Unsupported, - libc::ENOMEM => ErrorKind::OutOfMemory, + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => FilesystemQuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => FilenameTooLong, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + libc::ENOTEMPTY => DirectoryNotEmpty, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + + libc::EACCES | libc::EPERM => PermissionDenied, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match // clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock, + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, - _ => ErrorKind::Other, + _ => Uncategorized, } } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index d5a15964c08..753cad55ce7 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -38,7 +38,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned() }; Err(io::Error::new( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &format!("failed to lookup address information: {}", detail)[..], )) } @@ -178,7 +178,7 @@ impl Socket { if pollfd.revents & libc::POLLHUP != 0 { let e = self.take_error()?.unwrap_or_else(|| { io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"no error set after POLLHUP", ) }); diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 41ca9762390..71fec79347a 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -279,7 +279,7 @@ pub fn current_exe() -> io::Result<PathBuf> { ))?; if path_len <= 1 { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"KERN_PROC_PATHNAME sysctl returned zero-length string", )); } @@ -302,7 +302,7 @@ pub fn current_exe() -> io::Result<PathBuf> { return crate::fs::read_link(curproc_exe); } Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"/proc/curproc/exe doesn't point to regular file.", )) } @@ -320,7 +320,10 @@ pub fn current_exe() -> io::Result<PathBuf> { cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?; argv.set_len(argv_len as usize); if argv[0].is_null() { - return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available")); + return Err(io::Error::new_const( + io::ErrorKind::Uncategorized, + &"no current exe available", + )); } let argv0 = CStr::from_ptr(argv[0]).to_bytes(); if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') { @@ -335,7 +338,7 @@ pub fn current_exe() -> io::Result<PathBuf> { pub fn current_exe() -> io::Result<PathBuf> { match crate::fs::read_link("/proc/self/exe") { Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"no /proc/self/exe available. Is /proc mounted?", )), other => other, @@ -422,7 +425,7 @@ pub fn current_exe() -> io::Result<PathBuf> { _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::<image_info>() as i32); if result != 0 { use crate::io::ErrorKind; - Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path")) + Err(io::Error::new_const(ErrorKind::Uncategorized, &"Error getting executable path")) } else { let name = CStr::from_ptr(info.name.as_ptr()).to_bytes(); Ok(PathBuf::from(OsStr::from_bytes(name))) diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 6e72a7c632e..4e6c301d29f 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -30,7 +30,7 @@ pub fn unsupported_err() -> std_io::Error { } pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { - crate::io::ErrorKind::Other + crate::io::ErrorKind::Uncategorized } pub fn abort_internal() -> ! { diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 45e38f68b8c..8ffa1c88d88 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -648,7 +648,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> { through which {:?} could be opened", p ); - return Err(io::Error::new(io::ErrorKind::Other, msg)); + return Err(io::Error::new(io::ErrorKind::Uncategorized, msg)); } let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); @@ -670,7 +670,8 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> { } pub fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) + f.to_str() + .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8")) } pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 45a829c0cd2..4af99bfa464 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -58,7 +58,7 @@ pub use common::*; pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; if errno > u16::MAX as i32 || errno < 0 { - return Other; + return Uncategorized; } match errno as u16 { wasi::ERRNO_CONNREFUSED => ConnectionRefused, @@ -77,7 +77,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { wasi::ERRNO_AGAIN => WouldBlock, wasi::ERRNO_NOSYS => Unsupported, wasi::ERRNO_NOMEM => OutOfMemory, - _ => Other, + _ => Uncategorized, } } diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index 09714835104..a66ab083757 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -1,4 +1,3 @@ -use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 193c28c7673..63f9be7b7e3 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -10,6 +10,10 @@ use crate::ptr; use libc::{c_void, size_t, wchar_t}; +#[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this +mod errors; +pub use errors::*; + pub use self::EXCEPTION_DISPOSITION::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; @@ -70,6 +74,10 @@ pub type ADDRESS_FAMILY = USHORT; pub const TRUE: BOOL = 1; pub const FALSE: BOOL = 0; +pub const CSTR_LESS_THAN: c_int = 1; +pub const CSTR_EQUAL: c_int = 2; +pub const CSTR_GREATER_THAN: c_int = 3; + pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1; pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10; pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400; @@ -134,19 +142,6 @@ pub const WSASYS_STATUS_LEN: usize = 128; pub const WSAPROTOCOL_LEN: DWORD = 255; pub const INVALID_SOCKET: SOCKET = !0; -pub const WSAEACCES: c_int = 10013; -pub const WSAEINVAL: c_int = 10022; -pub const WSAEWOULDBLOCK: c_int = 10035; -pub const WSAEPROTOTYPE: c_int = 10041; -pub const WSAEADDRINUSE: c_int = 10048; -pub const WSAEADDRNOTAVAIL: c_int = 10049; -pub const WSAECONNABORTED: c_int = 10053; -pub const WSAECONNRESET: c_int = 10054; -pub const WSAENOTCONN: c_int = 10057; -pub const WSAESHUTDOWN: c_int = 10058; -pub const WSAETIMEDOUT: c_int = 10060; -pub const WSAECONNREFUSED: c_int = 10061; - pub const MAX_PROTOCOL_CHAIN: DWORD = 7; pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; @@ -166,42 +161,6 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; pub const PROGRESS_CONTINUE: DWORD = 0; -// List of Windows system error codes with descriptions: -// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes -pub const ERROR_FILE_NOT_FOUND: DWORD = 2; -pub const ERROR_PATH_NOT_FOUND: DWORD = 3; -pub const ERROR_ACCESS_DENIED: DWORD = 5; -pub const ERROR_INVALID_HANDLE: DWORD = 6; -pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8; -pub const ERROR_OUTOFMEMORY: DWORD = 14; -pub const ERROR_NO_MORE_FILES: DWORD = 18; -pub const ERROR_SHARING_VIOLATION: u32 = 32; -pub const ERROR_HANDLE_EOF: DWORD = 38; -pub const ERROR_FILE_EXISTS: DWORD = 80; -pub const ERROR_INVALID_PARAMETER: DWORD = 87; -pub const ERROR_BROKEN_PIPE: DWORD = 109; -pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; -pub const ERROR_SEM_TIMEOUT: DWORD = 121; -pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; -pub const ERROR_ALREADY_EXISTS: DWORD = 183; -pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; -pub const ERROR_NO_DATA: DWORD = 232; -pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; -pub const ERROR_OPERATION_ABORTED: DWORD = 995; -pub const ERROR_IO_PENDING: DWORD = 997; -pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; -pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; -pub const ERROR_TIMEOUT: DWORD = 1460; -pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; -pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; -pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; -pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; -pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; -pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; -pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; -pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; -pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; - pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT; pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; @@ -1015,6 +974,14 @@ extern "system" { pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK); pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN; pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN; + + pub fn CompareStringOrdinal( + lpString1: LPCWSTR, + cchCount1: c_int, + lpString2: LPCWSTR, + cchCount2: c_int, + bIgnoreCase: BOOL, + ) -> c_int; } #[link(name = "ws2_32")] diff --git a/library/std/src/sys/windows/c/errors.rs b/library/std/src/sys/windows/c/errors.rs new file mode 100644 index 00000000000..23dcc119db9 --- /dev/null +++ b/library/std/src/sys/windows/c/errors.rs @@ -0,0 +1,1883 @@ +// List of Windows system error codes with descriptions: +// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes + +#![allow(dead_code)] + +use super::{c_int, DWORD}; + +pub const ERROR_DIRECTORY_NOT_SUPPORTED: DWORD = 336; +pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; +pub const ERROR_DISK_QUOTA_EXCEEDED: DWORD = 1295; +pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; +pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; + +// The followiung list was obtained from +// `/usr/x86_64-w64-mingw32/include/winerror.h` +// in the Debian package +// mingw-w64_6.0.0-3_all.deb +// +// The header of that file says: +// * This file has no copyright assigned and is placed in the Public Domain. +// * This file is part of the mingw-w64 runtime package. +// * No warranty is given; refer to the file DISCLAIMER.PD within this package. +// +// The text here is the result of the following rune: +// grep -P '#define ERROR' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs +// grep -P '#define WSA' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs +// and then using some manually-invented but rather obvious editor search-and-replace +// invocations, plus some straightforward manual fixups, to turn it into Rust syntax +// and remove all the duplicates from the manual table above. + +pub const ERROR_SUCCESS: DWORD = 0; +pub const ERROR_INVALID_FUNCTION: DWORD = 1; +pub const ERROR_FILE_NOT_FOUND: DWORD = 2; +pub const ERROR_PATH_NOT_FOUND: DWORD = 3; +pub const ERROR_TOO_MANY_OPEN_FILES: DWORD = 4; +pub const ERROR_ACCESS_DENIED: DWORD = 5; +pub const ERROR_INVALID_HANDLE: DWORD = 6; +pub const ERROR_ARENA_TRASHED: DWORD = 7; +pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8; +pub const ERROR_INVALID_BLOCK: DWORD = 9; +pub const ERROR_BAD_ENVIRONMENT: DWORD = 10; +pub const ERROR_BAD_FORMAT: DWORD = 11; +pub const ERROR_INVALID_ACCESS: DWORD = 12; +pub const ERROR_INVALID_DATA: DWORD = 13; +pub const ERROR_OUTOFMEMORY: DWORD = 14; +pub const ERROR_INVALID_DRIVE: DWORD = 15; +pub const ERROR_CURRENT_DIRECTORY: DWORD = 16; +pub const ERROR_NOT_SAME_DEVICE: DWORD = 17; +pub const ERROR_NO_MORE_FILES: DWORD = 18; +pub const ERROR_WRITE_PROTECT: DWORD = 19; +pub const ERROR_BAD_UNIT: DWORD = 20; +pub const ERROR_NOT_READY: DWORD = 21; +pub const ERROR_BAD_COMMAND: DWORD = 22; +pub const ERROR_CRC: DWORD = 23; +pub const ERROR_BAD_LENGTH: DWORD = 24; +pub const ERROR_SEEK: DWORD = 25; +pub const ERROR_NOT_DOS_DISK: DWORD = 26; +pub const ERROR_SECTOR_NOT_FOUND: DWORD = 27; +pub const ERROR_OUT_OF_PAPER: DWORD = 28; +pub const ERROR_WRITE_FAULT: DWORD = 29; +pub const ERROR_READ_FAULT: DWORD = 30; +pub const ERROR_GEN_FAILURE: DWORD = 31; +pub const ERROR_SHARING_VIOLATION: DWORD = 32; +pub const ERROR_LOCK_VIOLATION: DWORD = 33; +pub const ERROR_WRONG_DISK: DWORD = 34; +pub const ERROR_SHARING_BUFFER_EXCEEDED: DWORD = 36; +pub const ERROR_HANDLE_EOF: DWORD = 38; +pub const ERROR_HANDLE_DISK_FULL: DWORD = 39; +pub const ERROR_NOT_SUPPORTED: DWORD = 50; +pub const ERROR_REM_NOT_LIST: DWORD = 51; +pub const ERROR_DUP_NAME: DWORD = 52; +pub const ERROR_BAD_NETPATH: DWORD = 53; +pub const ERROR_NETWORK_BUSY: DWORD = 54; +pub const ERROR_DEV_NOT_EXIST: DWORD = 55; +pub const ERROR_TOO_MANY_CMDS: DWORD = 56; +pub const ERROR_ADAP_HDW_ERR: DWORD = 57; +pub const ERROR_BAD_NET_RESP: DWORD = 58; +pub const ERROR_UNEXP_NET_ERR: DWORD = 59; +pub const ERROR_BAD_REM_ADAP: DWORD = 60; +pub const ERROR_PRINTQ_FULL: DWORD = 61; +pub const ERROR_NO_SPOOL_SPACE: DWORD = 62; +pub const ERROR_PRINT_CANCELLED: DWORD = 63; +pub const ERROR_NETNAME_DELETED: DWORD = 64; +pub const ERROR_NETWORK_ACCESS_DENIED: DWORD = 65; +pub const ERROR_BAD_DEV_TYPE: DWORD = 66; +pub const ERROR_BAD_NET_NAME: DWORD = 67; +pub const ERROR_TOO_MANY_NAMES: DWORD = 68; +pub const ERROR_TOO_MANY_SESS: DWORD = 69; +pub const ERROR_SHARING_PAUSED: DWORD = 70; +pub const ERROR_REQ_NOT_ACCEP: DWORD = 71; +pub const ERROR_REDIR_PAUSED: DWORD = 72; +pub const ERROR_FILE_EXISTS: DWORD = 80; +pub const ERROR_CANNOT_MAKE: DWORD = 82; +pub const ERROR_FAIL_I24: DWORD = 83; +pub const ERROR_OUT_OF_STRUCTURES: DWORD = 84; +pub const ERROR_ALREADY_ASSIGNED: DWORD = 85; +pub const ERROR_INVALID_PASSWORD: DWORD = 86; +pub const ERROR_INVALID_PARAMETER: DWORD = 87; +pub const ERROR_NET_WRITE_FAULT: DWORD = 88; +pub const ERROR_NO_PROC_SLOTS: DWORD = 89; +pub const ERROR_TOO_MANY_SEMAPHORES: DWORD = 100; +pub const ERROR_EXCL_SEM_ALREADY_OWNED: DWORD = 101; +pub const ERROR_SEM_IS_SET: DWORD = 102; +pub const ERROR_TOO_MANY_SEM_REQUESTS: DWORD = 103; +pub const ERROR_INVALID_AT_INTERRUPT_TIME: DWORD = 104; +pub const ERROR_SEM_OWNER_DIED: DWORD = 105; +pub const ERROR_SEM_USER_LIMIT: DWORD = 106; +pub const ERROR_DISK_CHANGE: DWORD = 107; +pub const ERROR_DRIVE_LOCKED: DWORD = 108; +pub const ERROR_BROKEN_PIPE: DWORD = 109; +pub const ERROR_OPEN_FAILED: DWORD = 110; +pub const ERROR_BUFFER_OVERFLOW: DWORD = 111; +pub const ERROR_DISK_FULL: DWORD = 112; +pub const ERROR_NO_MORE_SEARCH_HANDLES: DWORD = 113; +pub const ERROR_INVALID_TARGET_HANDLE: DWORD = 114; +pub const ERROR_INVALID_CATEGORY: DWORD = 117; +pub const ERROR_INVALID_VERIFY_SWITCH: DWORD = 118; +pub const ERROR_BAD_DRIVER_LEVEL: DWORD = 119; +pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; +pub const ERROR_SEM_TIMEOUT: DWORD = 121; +pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; +pub const ERROR_INVALID_NAME: DWORD = 123; +pub const ERROR_INVALID_LEVEL: DWORD = 124; +pub const ERROR_NO_VOLUME_LABEL: DWORD = 125; +pub const ERROR_MOD_NOT_FOUND: DWORD = 126; +pub const ERROR_PROC_NOT_FOUND: DWORD = 127; +pub const ERROR_WAIT_NO_CHILDREN: DWORD = 128; +pub const ERROR_CHILD_NOT_COMPLETE: DWORD = 129; +pub const ERROR_DIRECT_ACCESS_HANDLE: DWORD = 130; +pub const ERROR_NEGATIVE_SEEK: DWORD = 131; +pub const ERROR_SEEK_ON_DEVICE: DWORD = 132; +pub const ERROR_IS_JOIN_TARGET: DWORD = 133; +pub const ERROR_IS_JOINED: DWORD = 134; +pub const ERROR_IS_SUBSTED: DWORD = 135; +pub const ERROR_NOT_JOINED: DWORD = 136; +pub const ERROR_NOT_SUBSTED: DWORD = 137; +pub const ERROR_JOIN_TO_JOIN: DWORD = 138; +pub const ERROR_SUBST_TO_SUBST: DWORD = 139; +pub const ERROR_JOIN_TO_SUBST: DWORD = 140; +pub const ERROR_SUBST_TO_JOIN: DWORD = 141; +pub const ERROR_BUSY_DRIVE: DWORD = 142; +pub const ERROR_SAME_DRIVE: DWORD = 143; +pub const ERROR_DIR_NOT_ROOT: DWORD = 144; +pub const ERROR_DIR_NOT_EMPTY: DWORD = 145; +pub const ERROR_IS_SUBST_PATH: DWORD = 146; +pub const ERROR_IS_JOIN_PATH: DWORD = 147; +pub const ERROR_PATH_BUSY: DWORD = 148; +pub const ERROR_IS_SUBST_TARGET: DWORD = 149; +pub const ERROR_SYSTEM_TRACE: DWORD = 150; +pub const ERROR_INVALID_EVENT_COUNT: DWORD = 151; +pub const ERROR_TOO_MANY_MUXWAITERS: DWORD = 152; +pub const ERROR_INVALID_LIST_FORMAT: DWORD = 153; +pub const ERROR_LABEL_TOO_LONG: DWORD = 154; +pub const ERROR_TOO_MANY_TCBS: DWORD = 155; +pub const ERROR_SIGNAL_REFUSED: DWORD = 156; +pub const ERROR_DISCARDED: DWORD = 157; +pub const ERROR_NOT_LOCKED: DWORD = 158; +pub const ERROR_BAD_THREADID_ADDR: DWORD = 159; +pub const ERROR_BAD_ARGUMENTS: DWORD = 160; +pub const ERROR_BAD_PATHNAME: DWORD = 161; +pub const ERROR_SIGNAL_PENDING: DWORD = 162; +pub const ERROR_MAX_THRDS_REACHED: DWORD = 164; +pub const ERROR_LOCK_FAILED: DWORD = 167; +pub const ERROR_BUSY: DWORD = 170; +pub const ERROR_CANCEL_VIOLATION: DWORD = 173; +pub const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: DWORD = 174; +pub const ERROR_INVALID_SEGMENT_NUMBER: DWORD = 180; +pub const ERROR_INVALID_ORDINAL: DWORD = 182; +pub const ERROR_ALREADY_EXISTS: DWORD = 183; +pub const ERROR_INVALID_FLAG_NUMBER: DWORD = 186; +pub const ERROR_SEM_NOT_FOUND: DWORD = 187; +pub const ERROR_INVALID_STARTING_CODESEG: DWORD = 188; +pub const ERROR_INVALID_STACKSEG: DWORD = 189; +pub const ERROR_INVALID_MODULETYPE: DWORD = 190; +pub const ERROR_INVALID_EXE_SIGNATURE: DWORD = 191; +pub const ERROR_EXE_MARKED_INVALID: DWORD = 192; +pub const ERROR_BAD_EXE_FORMAT: DWORD = 193; +pub const ERROR_ITERATED_DATA_EXCEEDS_64k: DWORD = 194; +pub const ERROR_INVALID_MINALLOCSIZE: DWORD = 195; +pub const ERROR_DYNLINK_FROM_INVALID_RING: DWORD = 196; +pub const ERROR_IOPL_NOT_ENABLED: DWORD = 197; +pub const ERROR_INVALID_SEGDPL: DWORD = 198; +pub const ERROR_AUTODATASEG_EXCEEDS_64k: DWORD = 199; +pub const ERROR_RING2SEG_MUST_BE_MOVABLE: DWORD = 200; +pub const ERROR_RELOC_CHAIN_XEEDS_SEGLIM: DWORD = 201; +pub const ERROR_INFLOOP_IN_RELOC_CHAIN: DWORD = 202; +pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; +pub const ERROR_NO_SIGNAL_SENT: DWORD = 205; +pub const ERROR_FILENAME_EXCED_RANGE: DWORD = 206; +pub const ERROR_RING2_STACK_IN_USE: DWORD = 207; +pub const ERROR_META_EXPANSION_TOO_LONG: DWORD = 208; +pub const ERROR_INVALID_SIGNAL_NUMBER: DWORD = 209; +pub const ERROR_THREAD_1_INACTIVE: DWORD = 210; +pub const ERROR_LOCKED: DWORD = 212; +pub const ERROR_TOO_MANY_MODULES: DWORD = 214; +pub const ERROR_NESTING_NOT_ALLOWED: DWORD = 215; +pub const ERROR_EXE_MACHINE_TYPE_MISMATCH: DWORD = 216; +pub const ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY: DWORD = 217; +pub const ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY: DWORD = 218; +pub const ERROR_FILE_CHECKED_OUT: DWORD = 220; +pub const ERROR_CHECKOUT_REQUIRED: DWORD = 221; +pub const ERROR_BAD_FILE_TYPE: DWORD = 222; +pub const ERROR_FILE_TOO_LARGE: DWORD = 223; +pub const ERROR_FORMS_AUTH_REQUIRED: DWORD = 224; +pub const ERROR_PIPE_LOCAL: DWORD = 229; +pub const ERROR_BAD_PIPE: DWORD = 230; +pub const ERROR_PIPE_BUSY: DWORD = 231; +pub const ERROR_NO_DATA: DWORD = 232; +pub const ERROR_PIPE_NOT_CONNECTED: DWORD = 233; +pub const ERROR_MORE_DATA: DWORD = 234; +pub const ERROR_VC_DISCONNECTED: DWORD = 240; +pub const ERROR_INVALID_EA_NAME: DWORD = 254; +pub const ERROR_EA_LIST_INCONSISTENT: DWORD = 255; +pub const ERROR_NO_MORE_ITEMS: DWORD = 259; +pub const ERROR_CANNOT_COPY: DWORD = 266; +pub const ERROR_DIRECTORY: DWORD = 267; +pub const ERROR_EAS_DIDNT_FIT: DWORD = 275; +pub const ERROR_EA_FILE_CORRUPT: DWORD = 276; +pub const ERROR_EA_TABLE_FULL: DWORD = 277; +pub const ERROR_INVALID_EA_HANDLE: DWORD = 278; +pub const ERROR_EAS_NOT_SUPPORTED: DWORD = 282; +pub const ERROR_NOT_OWNER: DWORD = 288; +pub const ERROR_TOO_MANY_POSTS: DWORD = 298; +pub const ERROR_PARTIAL_COPY: DWORD = 299; +pub const ERROR_OPLOCK_NOT_GRANTED: DWORD = 300; +pub const ERROR_INVALID_OPLOCK_PROTOCOL: DWORD = 301; +pub const ERROR_DISK_TOO_FRAGMENTED: DWORD = 302; +pub const ERROR_DELETE_PENDING: DWORD = 303; +pub const ERROR_INVALID_TOKEN: DWORD = 315; +pub const ERROR_MR_MID_NOT_FOUND: DWORD = 317; +pub const ERROR_SCOPE_NOT_FOUND: DWORD = 318; +pub const ERROR_INVALID_ADDRESS: DWORD = 487; +pub const ERROR_ARITHMETIC_OVERFLOW: DWORD = 534; +pub const ERROR_PIPE_CONNECTED: DWORD = 535; +pub const ERROR_PIPE_LISTENING: DWORD = 536; +pub const ERROR_WAKE_SYSTEM: DWORD = 730; +pub const ERROR_WAIT_1: DWORD = 731; +pub const ERROR_WAIT_2: DWORD = 732; +pub const ERROR_WAIT_3: DWORD = 733; +pub const ERROR_WAIT_63: DWORD = 734; +pub const ERROR_ABANDONED_WAIT_0: DWORD = 735; +pub const ERROR_ABANDONED_WAIT_63: DWORD = 736; +pub const ERROR_USER_APC: DWORD = 737; +pub const ERROR_KERNEL_APC: DWORD = 738; +pub const ERROR_ALERTED: DWORD = 739; +pub const ERROR_EA_ACCESS_DENIED: DWORD = 994; +pub const ERROR_OPERATION_ABORTED: DWORD = 995; +pub const ERROR_IO_INCOMPLETE: DWORD = 996; +pub const ERROR_IO_PENDING: DWORD = 997; +pub const ERROR_NOACCESS: DWORD = 998; +pub const ERROR_SWAPERROR: DWORD = 999; +pub const ERROR_STACK_OVERFLOW: DWORD = 1001; +pub const ERROR_INVALID_MESSAGE: DWORD = 1002; +pub const ERROR_CAN_NOT_COMPLETE: DWORD = 1003; +pub const ERROR_INVALID_FLAGS: DWORD = 1004; +pub const ERROR_UNRECOGNIZED_VOLUME: DWORD = 1005; +pub const ERROR_FILE_INVALID: DWORD = 1006; +pub const ERROR_FULLSCREEN_MODE: DWORD = 1007; +pub const ERROR_NO_TOKEN: DWORD = 1008; +pub const ERROR_BADDB: DWORD = 1009; +pub const ERROR_BADKEY: DWORD = 1010; +pub const ERROR_CANTOPEN: DWORD = 1011; +pub const ERROR_CANTREAD: DWORD = 1012; +pub const ERROR_CANTWRITE: DWORD = 1013; +pub const ERROR_REGISTRY_RECOVERED: DWORD = 1014; +pub const ERROR_REGISTRY_CORRUPT: DWORD = 1015; +pub const ERROR_REGISTRY_IO_FAILED: DWORD = 1016; +pub const ERROR_NOT_REGISTRY_FILE: DWORD = 1017; +pub const ERROR_KEY_DELETED: DWORD = 1018; +pub const ERROR_NO_LOG_SPACE: DWORD = 1019; +pub const ERROR_KEY_HAS_CHILDREN: DWORD = 1020; +pub const ERROR_CHILD_MUST_BE_VOLATILE: DWORD = 1021; +pub const ERROR_NOTIFY_ENUM_DIR: DWORD = 1022; +pub const ERROR_DEPENDENT_SERVICES_RUNNING: DWORD = 1051; +pub const ERROR_INVALID_SERVICE_CONTROL: DWORD = 1052; +pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; +pub const ERROR_SERVICE_NO_THREAD: DWORD = 1054; +pub const ERROR_SERVICE_DATABASE_LOCKED: DWORD = 1055; +pub const ERROR_SERVICE_ALREADY_RUNNING: DWORD = 1056; +pub const ERROR_INVALID_SERVICE_ACCOUNT: DWORD = 1057; +pub const ERROR_SERVICE_DISABLED: DWORD = 1058; +pub const ERROR_CIRCULAR_DEPENDENCY: DWORD = 1059; +pub const ERROR_SERVICE_DOES_NOT_EXIST: DWORD = 1060; +pub const ERROR_SERVICE_CANNOT_ACCEPT_CTRL: DWORD = 1061; +pub const ERROR_SERVICE_NOT_ACTIVE: DWORD = 1062; +pub const ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: DWORD = 1063; +pub const ERROR_EXCEPTION_IN_SERVICE: DWORD = 1064; +pub const ERROR_DATABASE_DOES_NOT_EXIST: DWORD = 1065; +pub const ERROR_SERVICE_SPECIFIC_ERROR: DWORD = 1066; +pub const ERROR_PROCESS_ABORTED: DWORD = 1067; +pub const ERROR_SERVICE_DEPENDENCY_FAIL: DWORD = 1068; +pub const ERROR_SERVICE_LOGON_FAILED: DWORD = 1069; +pub const ERROR_SERVICE_START_HANG: DWORD = 1070; +pub const ERROR_INVALID_SERVICE_LOCK: DWORD = 1071; +pub const ERROR_SERVICE_MARKED_FOR_DELETE: DWORD = 1072; +pub const ERROR_SERVICE_EXISTS: DWORD = 1073; +pub const ERROR_ALREADY_RUNNING_LKG: DWORD = 1074; +pub const ERROR_SERVICE_DEPENDENCY_DELETED: DWORD = 1075; +pub const ERROR_BOOT_ALREADY_ACCEPTED: DWORD = 1076; +pub const ERROR_SERVICE_NEVER_STARTED: DWORD = 1077; +pub const ERROR_DUPLICATE_SERVICE_NAME: DWORD = 1078; +pub const ERROR_DIFFERENT_SERVICE_ACCOUNT: DWORD = 1079; +pub const ERROR_CANNOT_DETECT_DRIVER_FAILURE: DWORD = 1080; +pub const ERROR_CANNOT_DETECT_PROCESS_ABORT: DWORD = 1081; +pub const ERROR_NO_RECOVERY_PROGRAM: DWORD = 1082; +pub const ERROR_SERVICE_NOT_IN_EXE: DWORD = 1083; +pub const ERROR_NOT_SAFEBOOT_SERVICE: DWORD = 1084; +pub const ERROR_END_OF_MEDIA: DWORD = 1100; +pub const ERROR_FILEMARK_DETECTED: DWORD = 1101; +pub const ERROR_BEGINNING_OF_MEDIA: DWORD = 1102; +pub const ERROR_SETMARK_DETECTED: DWORD = 1103; +pub const ERROR_NO_DATA_DETECTED: DWORD = 1104; +pub const ERROR_PARTITION_FAILURE: DWORD = 1105; +pub const ERROR_INVALID_BLOCK_LENGTH: DWORD = 1106; +pub const ERROR_DEVICE_NOT_PARTITIONED: DWORD = 1107; +pub const ERROR_UNABLE_TO_LOCK_MEDIA: DWORD = 1108; +pub const ERROR_UNABLE_TO_UNLOAD_MEDIA: DWORD = 1109; +pub const ERROR_MEDIA_CHANGED: DWORD = 1110; +pub const ERROR_BUS_RESET: DWORD = 1111; +pub const ERROR_NO_MEDIA_IN_DRIVE: DWORD = 1112; +pub const ERROR_NO_UNICODE_TRANSLATION: DWORD = 1113; +pub const ERROR_DLL_INIT_FAILED: DWORD = 1114; +pub const ERROR_SHUTDOWN_IN_PROGRESS: DWORD = 1115; +pub const ERROR_NO_SHUTDOWN_IN_PROGRESS: DWORD = 1116; +pub const ERROR_IO_DEVICE: DWORD = 1117; +pub const ERROR_SERIAL_NO_DEVICE: DWORD = 1118; +pub const ERROR_IRQ_BUSY: DWORD = 1119; +pub const ERROR_MORE_WRITES: DWORD = 1120; +pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; +pub const ERROR_FLOPPY_ID_MARK_NOT_FOUND: DWORD = 1122; +pub const ERROR_FLOPPY_WRONG_CYLINDER: DWORD = 1123; +pub const ERROR_FLOPPY_UNKNOWN_ERROR: DWORD = 1124; +pub const ERROR_FLOPPY_BAD_REGISTERS: DWORD = 1125; +pub const ERROR_DISK_RECALIBRATE_FAILED: DWORD = 1126; +pub const ERROR_DISK_OPERATION_FAILED: DWORD = 1127; +pub const ERROR_DISK_RESET_FAILED: DWORD = 1128; +pub const ERROR_EOM_OVERFLOW: DWORD = 1129; +pub const ERROR_NOT_ENOUGH_SERVER_MEMORY: DWORD = 1130; +pub const ERROR_POSSIBLE_DEADLOCK: DWORD = 1131; +pub const ERROR_MAPPED_ALIGNMENT: DWORD = 1132; +pub const ERROR_SET_POWER_STATE_VETOED: DWORD = 1140; +pub const ERROR_SET_POWER_STATE_FAILED: DWORD = 1141; +pub const ERROR_TOO_MANY_LINKS: DWORD = 1142; +pub const ERROR_OLD_WIN_VERSION: DWORD = 1150; +pub const ERROR_APP_WRONG_OS: DWORD = 1151; +pub const ERROR_SINGLE_INSTANCE_APP: DWORD = 1152; +pub const ERROR_RMODE_APP: DWORD = 1153; +pub const ERROR_INVALID_DLL: DWORD = 1154; +pub const ERROR_NO_ASSOCIATION: DWORD = 1155; +pub const ERROR_DDE_FAIL: DWORD = 1156; +pub const ERROR_DLL_NOT_FOUND: DWORD = 1157; +pub const ERROR_NO_MORE_USER_HANDLES: DWORD = 1158; +pub const ERROR_MESSAGE_SYNC_ONLY: DWORD = 1159; +pub const ERROR_SOURCE_ELEMENT_EMPTY: DWORD = 1160; +pub const ERROR_DESTINATION_ELEMENT_FULL: DWORD = 1161; +pub const ERROR_ILLEGAL_ELEMENT_ADDRESS: DWORD = 1162; +pub const ERROR_MAGAZINE_NOT_PRESENT: DWORD = 1163; +pub const ERROR_DEVICE_REINITIALIZATION_NEEDED: DWORD = 1164; +pub const ERROR_DEVICE_REQUIRES_CLEANING: DWORD = 1165; +pub const ERROR_DEVICE_DOOR_OPEN: DWORD = 1166; +pub const ERROR_DEVICE_NOT_CONNECTED: DWORD = 1167; +pub const ERROR_NOT_FOUND: DWORD = 1168; +pub const ERROR_NO_MATCH: DWORD = 1169; +pub const ERROR_SET_NOT_FOUND: DWORD = 1170; +pub const ERROR_POINT_NOT_FOUND: DWORD = 1171; +pub const ERROR_NO_TRACKING_SERVICE: DWORD = 1172; +pub const ERROR_NO_VOLUME_ID: DWORD = 1173; +pub const ERROR_UNABLE_TO_REMOVE_REPLACED: DWORD = 1175; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT: DWORD = 1176; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT_2: DWORD = 1177; +pub const ERROR_JOURNAL_DELETE_IN_PROGRESS: DWORD = 1178; +pub const ERROR_JOURNAL_NOT_ACTIVE: DWORD = 1179; +pub const ERROR_POTENTIAL_FILE_FOUND: DWORD = 1180; +pub const ERROR_JOURNAL_ENTRY_DELETED: DWORD = 1181; +pub const ERROR_BAD_DEVICE: DWORD = 1200; +pub const ERROR_CONNECTION_UNAVAIL: DWORD = 1201; +pub const ERROR_DEVICE_ALREADY_REMEMBERED: DWORD = 1202; +pub const ERROR_NO_NET_OR_BAD_PATH: DWORD = 1203; +pub const ERROR_BAD_PROVIDER: DWORD = 1204; +pub const ERROR_CANNOT_OPEN_PROFILE: DWORD = 1205; +pub const ERROR_BAD_PROFILE: DWORD = 1206; +pub const ERROR_NOT_CONTAINER: DWORD = 1207; +pub const ERROR_EXTENDED_ERROR: DWORD = 1208; +pub const ERROR_INVALID_GROUPNAME: DWORD = 1209; +pub const ERROR_INVALID_COMPUTERNAME: DWORD = 1210; +pub const ERROR_INVALID_EVENTNAME: DWORD = 1211; +pub const ERROR_INVALID_DOMAINNAME: DWORD = 1212; +pub const ERROR_INVALID_SERVICENAME: DWORD = 1213; +pub const ERROR_INVALID_NETNAME: DWORD = 1214; +pub const ERROR_INVALID_SHARENAME: DWORD = 1215; +pub const ERROR_INVALID_PASSWORDNAME: DWORD = 1216; +pub const ERROR_INVALID_MESSAGENAME: DWORD = 1217; +pub const ERROR_INVALID_MESSAGEDEST: DWORD = 1218; +pub const ERROR_SESSION_CREDENTIAL_CONFLICT: DWORD = 1219; +pub const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: DWORD = 1220; +pub const ERROR_DUP_DOMAINNAME: DWORD = 1221; +pub const ERROR_NO_NETWORK: DWORD = 1222; +pub const ERROR_CANCELLED: DWORD = 1223; +pub const ERROR_USER_MAPPED_FILE: DWORD = 1224; +pub const ERROR_CONNECTION_REFUSED: DWORD = 1225; +pub const ERROR_GRACEFUL_DISCONNECT: DWORD = 1226; +pub const ERROR_ADDRESS_ALREADY_ASSOCIATED: DWORD = 1227; +pub const ERROR_ADDRESS_NOT_ASSOCIATED: DWORD = 1228; +pub const ERROR_CONNECTION_INVALID: DWORD = 1229; +pub const ERROR_CONNECTION_ACTIVE: DWORD = 1230; +pub const ERROR_NETWORK_UNREACHABLE: DWORD = 1231; +pub const ERROR_HOST_UNREACHABLE: DWORD = 1232; +pub const ERROR_PROTOCOL_UNREACHABLE: DWORD = 1233; +pub const ERROR_PORT_UNREACHABLE: DWORD = 1234; +pub const ERROR_REQUEST_ABORTED: DWORD = 1235; +pub const ERROR_CONNECTION_ABORTED: DWORD = 1236; +pub const ERROR_RETRY: DWORD = 1237; +pub const ERROR_CONNECTION_COUNT_LIMIT: DWORD = 1238; +pub const ERROR_LOGIN_TIME_RESTRICTION: DWORD = 1239; +pub const ERROR_LOGIN_WKSTA_RESTRICTION: DWORD = 1240; +pub const ERROR_INCORRECT_ADDRESS: DWORD = 1241; +pub const ERROR_ALREADY_REGISTERED: DWORD = 1242; +pub const ERROR_SERVICE_NOT_FOUND: DWORD = 1243; +pub const ERROR_NOT_AUTHENTICATED: DWORD = 1244; +pub const ERROR_NOT_LOGGED_ON: DWORD = 1245; +pub const ERROR_CONTINUE: DWORD = 1246; +pub const ERROR_ALREADY_INITIALIZED: DWORD = 1247; +pub const ERROR_NO_MORE_DEVICES: DWORD = 1248; +pub const ERROR_NO_SUCH_SITE: DWORD = 1249; +pub const ERROR_DOMAIN_CONTROLLER_EXISTS: DWORD = 1250; +pub const ERROR_ONLY_IF_CONNECTED: DWORD = 1251; +pub const ERROR_OVERRIDE_NOCHANGES: DWORD = 1252; +pub const ERROR_BAD_USER_PROFILE: DWORD = 1253; +pub const ERROR_NOT_SUPPORTED_ON_SBS: DWORD = 1254; +pub const ERROR_SERVER_SHUTDOWN_IN_PROGRESS: DWORD = 1255; +pub const ERROR_HOST_DOWN: DWORD = 1256; +pub const ERROR_NON_ACCOUNT_SID: DWORD = 1257; +pub const ERROR_NON_DOMAIN_SID: DWORD = 1258; +pub const ERROR_APPHELP_BLOCK: DWORD = 1259; +pub const ERROR_ACCESS_DISABLED_BY_POLICY: DWORD = 1260; +pub const ERROR_REG_NAT_CONSUMPTION: DWORD = 1261; +pub const ERROR_CSCSHARE_OFFLINE: DWORD = 1262; +pub const ERROR_PKINIT_FAILURE: DWORD = 1263; +pub const ERROR_SMARTCARD_SUBSYSTEM_FAILURE: DWORD = 1264; +pub const ERROR_DOWNGRADE_DETECTED: DWORD = 1265; +pub const ERROR_MACHINE_LOCKED: DWORD = 1271; +pub const ERROR_CALLBACK_SUPPLIED_INVALID_DATA: DWORD = 1273; +pub const ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED: DWORD = 1274; +pub const ERROR_DRIVER_BLOCKED: DWORD = 1275; +pub const ERROR_INVALID_IMPORT_OF_NON_DLL: DWORD = 1276; +pub const ERROR_ACCESS_DISABLED_WEBBLADE: DWORD = 1277; +pub const ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER: DWORD = 1278; +pub const ERROR_RECOVERY_FAILURE: DWORD = 1279; +pub const ERROR_ALREADY_FIBER: DWORD = 1280; +pub const ERROR_ALREADY_THREAD: DWORD = 1281; +pub const ERROR_STACK_BUFFER_OVERRUN: DWORD = 1282; +pub const ERROR_PARAMETER_QUOTA_EXCEEDED: DWORD = 1283; +pub const ERROR_DEBUGGER_INACTIVE: DWORD = 1284; +pub const ERROR_DELAY_LOAD_FAILED: DWORD = 1285; +pub const ERROR_VDM_DISALLOWED: DWORD = 1286; +pub const ERROR_UNIDENTIFIED_ERROR: DWORD = 1287; +pub const ERROR_NOT_ALL_ASSIGNED: DWORD = 1300; +pub const ERROR_SOME_NOT_MAPPED: DWORD = 1301; +pub const ERROR_NO_QUOTAS_FOR_ACCOUNT: DWORD = 1302; +pub const ERROR_LOCAL_USER_SESSION_KEY: DWORD = 1303; +pub const ERROR_NULL_LM_PASSWORD: DWORD = 1304; +pub const ERROR_UNKNOWN_REVISION: DWORD = 1305; +pub const ERROR_REVISION_MISMATCH: DWORD = 1306; +pub const ERROR_INVALID_OWNER: DWORD = 1307; +pub const ERROR_INVALID_PRIMARY_GROUP: DWORD = 1308; +pub const ERROR_NO_IMPERSONATION_TOKEN: DWORD = 1309; +pub const ERROR_CANT_DISABLE_MANDATORY: DWORD = 1310; +pub const ERROR_NO_LOGON_SERVERS: DWORD = 1311; +pub const ERROR_NO_SUCH_LOGON_SESSION: DWORD = 1312; +pub const ERROR_NO_SUCH_PRIVILEGE: DWORD = 1313; +pub const ERROR_PRIVILEGE_NOT_HELD: DWORD = 1314; +pub const ERROR_INVALID_ACCOUNT_NAME: DWORD = 1315; +pub const ERROR_USER_EXISTS: DWORD = 1316; +pub const ERROR_NO_SUCH_USER: DWORD = 1317; +pub const ERROR_GROUP_EXISTS: DWORD = 1318; +pub const ERROR_NO_SUCH_GROUP: DWORD = 1319; +pub const ERROR_MEMBER_IN_GROUP: DWORD = 1320; +pub const ERROR_MEMBER_NOT_IN_GROUP: DWORD = 1321; +pub const ERROR_LAST_ADMIN: DWORD = 1322; +pub const ERROR_WRONG_PASSWORD: DWORD = 1323; +pub const ERROR_ILL_FORMED_PASSWORD: DWORD = 1324; +pub const ERROR_PASSWORD_RESTRICTION: DWORD = 1325; +pub const ERROR_LOGON_FAILURE: DWORD = 1326; +pub const ERROR_ACCOUNT_RESTRICTION: DWORD = 1327; +pub const ERROR_INVALID_LOGON_HOURS: DWORD = 1328; +pub const ERROR_INVALID_WORKSTATION: DWORD = 1329; +pub const ERROR_PASSWORD_EXPIRED: DWORD = 1330; +pub const ERROR_ACCOUNT_DISABLED: DWORD = 1331; +pub const ERROR_NONE_MAPPED: DWORD = 1332; +pub const ERROR_TOO_MANY_LUIDS_REQUESTED: DWORD = 1333; +pub const ERROR_LUIDS_EXHAUSTED: DWORD = 1334; +pub const ERROR_INVALID_SUB_AUTHORITY: DWORD = 1335; +pub const ERROR_INVALID_ACL: DWORD = 1336; +pub const ERROR_INVALID_SID: DWORD = 1337; +pub const ERROR_INVALID_SECURITY_DESCR: DWORD = 1338; +pub const ERROR_BAD_INHERITANCE_ACL: DWORD = 1340; +pub const ERROR_SERVER_DISABLED: DWORD = 1341; +pub const ERROR_SERVER_NOT_DISABLED: DWORD = 1342; +pub const ERROR_INVALID_ID_AUTHORITY: DWORD = 1343; +pub const ERROR_ALLOTTED_SPACE_EXCEEDED: DWORD = 1344; +pub const ERROR_INVALID_GROUP_ATTRIBUTES: DWORD = 1345; +pub const ERROR_BAD_IMPERSONATION_LEVEL: DWORD = 1346; +pub const ERROR_CANT_OPEN_ANONYMOUS: DWORD = 1347; +pub const ERROR_BAD_VALIDATION_CLASS: DWORD = 1348; +pub const ERROR_BAD_TOKEN_TYPE: DWORD = 1349; +pub const ERROR_NO_SECURITY_ON_OBJECT: DWORD = 1350; +pub const ERROR_CANT_ACCESS_DOMAIN_INFO: DWORD = 1351; +pub const ERROR_INVALID_SERVER_STATE: DWORD = 1352; +pub const ERROR_INVALID_DOMAIN_STATE: DWORD = 1353; +pub const ERROR_INVALID_DOMAIN_ROLE: DWORD = 1354; +pub const ERROR_NO_SUCH_DOMAIN: DWORD = 1355; +pub const ERROR_DOMAIN_EXISTS: DWORD = 1356; +pub const ERROR_DOMAIN_LIMIT_EXCEEDED: DWORD = 1357; +pub const ERROR_INTERNAL_DB_CORRUPTION: DWORD = 1358; +pub const ERROR_INTERNAL_ERROR: DWORD = 1359; +pub const ERROR_GENERIC_NOT_MAPPED: DWORD = 1360; +pub const ERROR_BAD_DESCRIPTOR_FORMAT: DWORD = 1361; +pub const ERROR_NOT_LOGON_PROCESS: DWORD = 1362; +pub const ERROR_LOGON_SESSION_EXISTS: DWORD = 1363; +pub const ERROR_NO_SUCH_PACKAGE: DWORD = 1364; +pub const ERROR_BAD_LOGON_SESSION_STATE: DWORD = 1365; +pub const ERROR_LOGON_SESSION_COLLISION: DWORD = 1366; +pub const ERROR_INVALID_LOGON_TYPE: DWORD = 1367; +pub const ERROR_CANNOT_IMPERSONATE: DWORD = 1368; +pub const ERROR_RXACT_INVALID_STATE: DWORD = 1369; +pub const ERROR_RXACT_COMMIT_FAILURE: DWORD = 1370; +pub const ERROR_SPECIAL_ACCOUNT: DWORD = 1371; +pub const ERROR_SPECIAL_GROUP: DWORD = 1372; +pub const ERROR_SPECIAL_USER: DWORD = 1373; +pub const ERROR_MEMBERS_PRIMARY_GROUP: DWORD = 1374; +pub const ERROR_TOKEN_ALREADY_IN_USE: DWORD = 1375; +pub const ERROR_NO_SUCH_ALIAS: DWORD = 1376; +pub const ERROR_MEMBER_NOT_IN_ALIAS: DWORD = 1377; +pub const ERROR_MEMBER_IN_ALIAS: DWORD = 1378; +pub const ERROR_ALIAS_EXISTS: DWORD = 1379; +pub const ERROR_LOGON_NOT_GRANTED: DWORD = 1380; +pub const ERROR_TOO_MANY_SECRETS: DWORD = 1381; +pub const ERROR_SECRET_TOO_LONG: DWORD = 1382; +pub const ERROR_INTERNAL_DB_ERROR: DWORD = 1383; +pub const ERROR_TOO_MANY_CONTEXT_IDS: DWORD = 1384; +pub const ERROR_LOGON_TYPE_NOT_GRANTED: DWORD = 1385; +pub const ERROR_NT_CROSS_ENCRYPTION_REQUIRED: DWORD = 1386; +pub const ERROR_NO_SUCH_MEMBER: DWORD = 1387; +pub const ERROR_INVALID_MEMBER: DWORD = 1388; +pub const ERROR_TOO_MANY_SIDS: DWORD = 1389; +pub const ERROR_LM_CROSS_ENCRYPTION_REQUIRED: DWORD = 1390; +pub const ERROR_NO_INHERITANCE: DWORD = 1391; +pub const ERROR_FILE_CORRUPT: DWORD = 1392; +pub const ERROR_DISK_CORRUPT: DWORD = 1393; +pub const ERROR_NO_USER_SESSION_KEY: DWORD = 1394; +pub const ERROR_LICENSE_QUOTA_EXCEEDED: DWORD = 1395; +pub const ERROR_WRONG_TARGET_NAME: DWORD = 1396; +pub const ERROR_MUTUAL_AUTH_FAILED: DWORD = 1397; +pub const ERROR_TIME_SKEW: DWORD = 1398; +pub const ERROR_CURRENT_DOMAIN_NOT_ALLOWED: DWORD = 1399; +pub const ERROR_INVALID_WINDOW_HANDLE: DWORD = 1400; +pub const ERROR_INVALID_MENU_HANDLE: DWORD = 1401; +pub const ERROR_INVALID_CURSOR_HANDLE: DWORD = 1402; +pub const ERROR_INVALID_ACCEL_HANDLE: DWORD = 1403; +pub const ERROR_INVALID_HOOK_HANDLE: DWORD = 1404; +pub const ERROR_INVALID_DWP_HANDLE: DWORD = 1405; +pub const ERROR_TLW_WITH_WSCHILD: DWORD = 1406; +pub const ERROR_CANNOT_FIND_WND_CLASS: DWORD = 1407; +pub const ERROR_WINDOW_OF_OTHER_THREAD: DWORD = 1408; +pub const ERROR_HOTKEY_ALREADY_REGISTERED: DWORD = 1409; +pub const ERROR_CLASS_ALREADY_EXISTS: DWORD = 1410; +pub const ERROR_CLASS_DOES_NOT_EXIST: DWORD = 1411; +pub const ERROR_CLASS_HAS_WINDOWS: DWORD = 1412; +pub const ERROR_INVALID_INDEX: DWORD = 1413; +pub const ERROR_INVALID_ICON_HANDLE: DWORD = 1414; +pub const ERROR_PRIVATE_DIALOG_INDEX: DWORD = 1415; +pub const ERROR_LISTBOX_ID_NOT_FOUND: DWORD = 1416; +pub const ERROR_NO_WILDCARD_CHARACTERS: DWORD = 1417; +pub const ERROR_CLIPBOARD_NOT_OPEN: DWORD = 1418; +pub const ERROR_HOTKEY_NOT_REGISTERED: DWORD = 1419; +pub const ERROR_WINDOW_NOT_DIALOG: DWORD = 1420; +pub const ERROR_CONTROL_ID_NOT_FOUND: DWORD = 1421; +pub const ERROR_INVALID_COMBOBOX_MESSAGE: DWORD = 1422; +pub const ERROR_WINDOW_NOT_COMBOBOX: DWORD = 1423; +pub const ERROR_INVALID_EDIT_HEIGHT: DWORD = 1424; +pub const ERROR_DC_NOT_FOUND: DWORD = 1425; +pub const ERROR_INVALID_HOOK_FILTER: DWORD = 1426; +pub const ERROR_INVALID_FILTER_PROC: DWORD = 1427; +pub const ERROR_HOOK_NEEDS_HMOD: DWORD = 1428; +pub const ERROR_GLOBAL_ONLY_HOOK: DWORD = 1429; +pub const ERROR_JOURNAL_HOOK_SET: DWORD = 1430; +pub const ERROR_HOOK_NOT_INSTALLED: DWORD = 1431; +pub const ERROR_INVALID_LB_MESSAGE: DWORD = 1432; +pub const ERROR_SETCOUNT_ON_BAD_LB: DWORD = 1433; +pub const ERROR_LB_WITHOUT_TABSTOPS: DWORD = 1434; +pub const ERROR_DESTROY_OBJECT_OF_OTHER_THREAD: DWORD = 1435; +pub const ERROR_CHILD_WINDOW_MENU: DWORD = 1436; +pub const ERROR_NO_SYSTEM_MENU: DWORD = 1437; +pub const ERROR_INVALID_MSGBOX_STYLE: DWORD = 1438; +pub const ERROR_INVALID_SPI_VALUE: DWORD = 1439; +pub const ERROR_SCREEN_ALREADY_LOCKED: DWORD = 1440; +pub const ERROR_HWNDS_HAVE_DIFF_PARENT: DWORD = 1441; +pub const ERROR_NOT_CHILD_WINDOW: DWORD = 1442; +pub const ERROR_INVALID_GW_COMMAND: DWORD = 1443; +pub const ERROR_INVALID_THREAD_ID: DWORD = 1444; +pub const ERROR_NON_MDICHILD_WINDOW: DWORD = 1445; +pub const ERROR_POPUP_ALREADY_ACTIVE: DWORD = 1446; +pub const ERROR_NO_SCROLLBARS: DWORD = 1447; +pub const ERROR_INVALID_SCROLLBAR_RANGE: DWORD = 1448; +pub const ERROR_INVALID_SHOWWIN_COMMAND: DWORD = 1449; +pub const ERROR_NO_SYSTEM_RESOURCES: DWORD = 1450; +pub const ERROR_NONPAGED_SYSTEM_RESOURCES: DWORD = 1451; +pub const ERROR_PAGED_SYSTEM_RESOURCES: DWORD = 1452; +pub const ERROR_WORKING_SET_QUOTA: DWORD = 1453; +pub const ERROR_PAGEFILE_QUOTA: DWORD = 1454; +pub const ERROR_COMMITMENT_LIMIT: DWORD = 1455; +pub const ERROR_MENU_ITEM_NOT_FOUND: DWORD = 1456; +pub const ERROR_INVALID_KEYBOARD_HANDLE: DWORD = 1457; +pub const ERROR_HOOK_TYPE_NOT_ALLOWED: DWORD = 1458; +pub const ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: DWORD = 1459; +pub const ERROR_TIMEOUT: DWORD = 1460; +pub const ERROR_INVALID_MONITOR_HANDLE: DWORD = 1461; +pub const ERROR_INCORRECT_SIZE: DWORD = 1462; +pub const ERROR_SYMLINK_CLASS_DISABLED: DWORD = 1463; +pub const ERROR_SYMLINK_NOT_SUPPORTED: DWORD = 1464; +pub const ERROR_XML_PARSE_ERROR: DWORD = 1465; +pub const ERROR_XMLDSIG_ERROR: DWORD = 1466; +pub const ERROR_RESTART_APPLICATION: DWORD = 1467; +pub const ERROR_WRONG_COMPARTMENT: DWORD = 1468; +pub const ERROR_AUTHIP_FAILURE: DWORD = 1469; +pub const ERROR_NO_NVRAM_RESOURCES: DWORD = 1470; +pub const ERROR_NOT_GUI_PROCESS: DWORD = 1471; +pub const ERROR_EVENTLOG_FILE_CORRUPT: DWORD = 1500; +pub const ERROR_EVENTLOG_CANT_START: DWORD = 1501; +pub const ERROR_LOG_FILE_FULL: DWORD = 1502; +pub const ERROR_EVENTLOG_FILE_CHANGED: DWORD = 1503; +pub const ERROR_INSTALL_SERVICE_FAILURE: DWORD = 1601; +pub const ERROR_INSTALL_USEREXIT: DWORD = 1602; +pub const ERROR_INSTALL_FAILURE: DWORD = 1603; +pub const ERROR_INSTALL_SUSPEND: DWORD = 1604; +pub const ERROR_UNKNOWN_PRODUCT: DWORD = 1605; +pub const ERROR_UNKNOWN_FEATURE: DWORD = 1606; +pub const ERROR_UNKNOWN_COMPONENT: DWORD = 1607; +pub const ERROR_UNKNOWN_PROPERTY: DWORD = 1608; +pub const ERROR_INVALID_HANDLE_STATE: DWORD = 1609; +pub const ERROR_BAD_CONFIGURATION: DWORD = 1610; +pub const ERROR_INDEX_ABSENT: DWORD = 1611; +pub const ERROR_INSTALL_SOURCE_ABSENT: DWORD = 1612; +pub const ERROR_INSTALL_PACKAGE_VERSION: DWORD = 1613; +pub const ERROR_PRODUCT_UNINSTALLED: DWORD = 1614; +pub const ERROR_BAD_QUERY_SYNTAX: DWORD = 1615; +pub const ERROR_INVALID_FIELD: DWORD = 1616; +pub const ERROR_DEVICE_REMOVED: DWORD = 1617; +pub const ERROR_INSTALL_ALREADY_RUNNING: DWORD = 1618; +pub const ERROR_INSTALL_PACKAGE_OPEN_FAILED: DWORD = 1619; +pub const ERROR_INSTALL_PACKAGE_INVALID: DWORD = 1620; +pub const ERROR_INSTALL_UI_FAILURE: DWORD = 1621; +pub const ERROR_INSTALL_LOG_FAILURE: DWORD = 1622; +pub const ERROR_INSTALL_LANGUAGE_UNSUPPORTED: DWORD = 1623; +pub const ERROR_INSTALL_TRANSFORM_FAILURE: DWORD = 1624; +pub const ERROR_INSTALL_PACKAGE_REJECTED: DWORD = 1625; +pub const ERROR_FUNCTION_NOT_CALLED: DWORD = 1626; +pub const ERROR_FUNCTION_FAILED: DWORD = 1627; +pub const ERROR_INVALID_TABLE: DWORD = 1628; +pub const ERROR_DATATYPE_MISMATCH: DWORD = 1629; +pub const ERROR_UNSUPPORTED_TYPE: DWORD = 1630; +pub const ERROR_CREATE_FAILED: DWORD = 1631; +pub const ERROR_INSTALL_TEMP_UNWRITABLE: DWORD = 1632; +pub const ERROR_INSTALL_PLATFORM_UNSUPPORTED: DWORD = 1633; +pub const ERROR_INSTALL_NOTUSED: DWORD = 1634; +pub const ERROR_PATCH_PACKAGE_OPEN_FAILED: DWORD = 1635; +pub const ERROR_PATCH_PACKAGE_INVALID: DWORD = 1636; +pub const ERROR_PATCH_PACKAGE_UNSUPPORTED: DWORD = 1637; +pub const ERROR_PRODUCT_VERSION: DWORD = 1638; +pub const ERROR_INVALID_COMMAND_LINE: DWORD = 1639; +pub const ERROR_INSTALL_REMOTE_DISALLOWED: DWORD = 1640; +pub const ERROR_SUCCESS_REBOOT_INITIATED: DWORD = 1641; +pub const ERROR_PATCH_TARGET_NOT_FOUND: DWORD = 1642; +pub const ERROR_PATCH_PACKAGE_REJECTED: DWORD = 1643; +pub const ERROR_INSTALL_TRANSFORM_REJECTED: DWORD = 1644; +pub const ERROR_INSTALL_REMOTE_PROHIBITED: DWORD = 1645; +pub const ERROR_INVALID_USER_BUFFER: DWORD = 1784; +pub const ERROR_UNRECOGNIZED_MEDIA: DWORD = 1785; +pub const ERROR_NO_TRUST_LSA_SECRET: DWORD = 1786; +pub const ERROR_NO_TRUST_SAM_ACCOUNT: DWORD = 1787; +pub const ERROR_TRUSTED_DOMAIN_FAILURE: DWORD = 1788; +pub const ERROR_TRUSTED_RELATIONSHIP_FAILURE: DWORD = 1789; +pub const ERROR_TRUST_FAILURE: DWORD = 1790; +pub const ERROR_NETLOGON_NOT_STARTED: DWORD = 1792; +pub const ERROR_ACCOUNT_EXPIRED: DWORD = 1793; +pub const ERROR_REDIRECTOR_HAS_OPEN_HANDLES: DWORD = 1794; +pub const ERROR_PRINTER_DRIVER_ALREADY_INSTALLED: DWORD = 1795; +pub const ERROR_UNKNOWN_PORT: DWORD = 1796; +pub const ERROR_UNKNOWN_PRINTER_DRIVER: DWORD = 1797; +pub const ERROR_UNKNOWN_PRINTPROCESSOR: DWORD = 1798; +pub const ERROR_INVALID_SEPARATOR_FILE: DWORD = 1799; +pub const ERROR_INVALID_PRIORITY: DWORD = 1800; +pub const ERROR_INVALID_PRINTER_NAME: DWORD = 1801; +pub const ERROR_PRINTER_ALREADY_EXISTS: DWORD = 1802; +pub const ERROR_INVALID_PRINTER_COMMAND: DWORD = 1803; +pub const ERROR_INVALID_DATATYPE: DWORD = 1804; +pub const ERROR_INVALID_ENVIRONMENT: DWORD = 1805; +pub const ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: DWORD = 1807; +pub const ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT: DWORD = 1808; +pub const ERROR_NOLOGON_SERVER_TRUST_ACCOUNT: DWORD = 1809; +pub const ERROR_DOMAIN_TRUST_INCONSISTENT: DWORD = 1810; +pub const ERROR_SERVER_HAS_OPEN_HANDLES: DWORD = 1811; +pub const ERROR_RESOURCE_DATA_NOT_FOUND: DWORD = 1812; +pub const ERROR_RESOURCE_TYPE_NOT_FOUND: DWORD = 1813; +pub const ERROR_RESOURCE_NAME_NOT_FOUND: DWORD = 1814; +pub const ERROR_RESOURCE_LANG_NOT_FOUND: DWORD = 1815; +pub const ERROR_NOT_ENOUGH_QUOTA: DWORD = 1816; +pub const ERROR_INVALID_TIME: DWORD = 1901; +pub const ERROR_INVALID_FORM_NAME: DWORD = 1902; +pub const ERROR_INVALID_FORM_SIZE: DWORD = 1903; +pub const ERROR_ALREADY_WAITING: DWORD = 1904; +pub const ERROR_PRINTER_DELETED: DWORD = 1905; +pub const ERROR_INVALID_PRINTER_STATE: DWORD = 1906; +pub const ERROR_PASSWORD_MUST_CHANGE: DWORD = 1907; +pub const ERROR_DOMAIN_CONTROLLER_NOT_FOUND: DWORD = 1908; +pub const ERROR_ACCOUNT_LOCKED_OUT: DWORD = 1909; +pub const ERROR_NO_SITENAME: DWORD = 1919; +pub const ERROR_CANT_ACCESS_FILE: DWORD = 1920; +pub const ERROR_CANT_RESOLVE_FILENAME: DWORD = 1921; +pub const ERROR_KM_DRIVER_BLOCKED: DWORD = 1930; +pub const ERROR_CONTEXT_EXPIRED: DWORD = 1931; +pub const ERROR_PER_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1932; +pub const ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1933; +pub const ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED: DWORD = 1934; +pub const ERROR_AUTHENTICATION_FIREWALL_FAILED: DWORD = 1935; +pub const ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED: DWORD = 1936; +pub const ERROR_INVALID_PIXEL_FORMAT: DWORD = 2000; +pub const ERROR_BAD_DRIVER: DWORD = 2001; +pub const ERROR_INVALID_WINDOW_STYLE: DWORD = 2002; +pub const ERROR_METAFILE_NOT_SUPPORTED: DWORD = 2003; +pub const ERROR_TRANSFORM_NOT_SUPPORTED: DWORD = 2004; +pub const ERROR_CLIPPING_NOT_SUPPORTED: DWORD = 2005; +pub const ERROR_INVALID_CMM: DWORD = 2010; +pub const ERROR_INVALID_PROFILE: DWORD = 2011; +pub const ERROR_TAG_NOT_FOUND: DWORD = 2012; +pub const ERROR_TAG_NOT_PRESENT: DWORD = 2013; +pub const ERROR_DUPLICATE_TAG: DWORD = 2014; +pub const ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE: DWORD = 2015; +pub const ERROR_PROFILE_NOT_FOUND: DWORD = 2016; +pub const ERROR_INVALID_COLORSPACE: DWORD = 2017; +pub const ERROR_ICM_NOT_ENABLED: DWORD = 2018; +pub const ERROR_DELETING_ICM_XFORM: DWORD = 2019; +pub const ERROR_INVALID_TRANSFORM: DWORD = 2020; +pub const ERROR_COLORSPACE_MISMATCH: DWORD = 2021; +pub const ERROR_INVALID_COLORINDEX: DWORD = 2022; +pub const ERROR_CONNECTED_OTHER_PASSWORD: DWORD = 2108; +pub const ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT: DWORD = 2109; +pub const ERROR_BAD_USERNAME: DWORD = 2202; +pub const ERROR_NOT_CONNECTED: DWORD = 2250; +pub const ERROR_OPEN_FILES: DWORD = 2401; +pub const ERROR_ACTIVE_CONNECTIONS: DWORD = 2402; +pub const ERROR_DEVICE_IN_USE: DWORD = 2404; +pub const ERROR_UNKNOWN_PRINT_MONITOR: DWORD = 3000; +pub const ERROR_PRINTER_DRIVER_IN_USE: DWORD = 3001; +pub const ERROR_SPOOL_FILE_NOT_FOUND: DWORD = 3002; +pub const ERROR_SPL_NO_STARTDOC: DWORD = 3003; +pub const ERROR_SPL_NO_ADDJOB: DWORD = 3004; +pub const ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED: DWORD = 3005; +pub const ERROR_PRINT_MONITOR_ALREADY_INSTALLED: DWORD = 3006; +pub const ERROR_INVALID_PRINT_MONITOR: DWORD = 3007; +pub const ERROR_PRINT_MONITOR_IN_USE: DWORD = 3008; +pub const ERROR_PRINTER_HAS_JOBS_QUEUED: DWORD = 3009; +pub const ERROR_SUCCESS_REBOOT_REQUIRED: DWORD = 3010; +pub const ERROR_SUCCESS_RESTART_REQUIRED: DWORD = 3011; +pub const ERROR_PRINTER_NOT_FOUND: DWORD = 3012; +pub const ERROR_PRINTER_DRIVER_WARNED: DWORD = 3013; +pub const ERROR_PRINTER_DRIVER_BLOCKED: DWORD = 3014; +pub const ERROR_WINS_INTERNAL: DWORD = 4000; +pub const ERROR_CAN_NOT_DEL_LOCAL_WINS: DWORD = 4001; +pub const ERROR_STATIC_INIT: DWORD = 4002; +pub const ERROR_INC_BACKUP: DWORD = 4003; +pub const ERROR_FULL_BACKUP: DWORD = 4004; +pub const ERROR_REC_NON_EXISTENT: DWORD = 4005; +pub const ERROR_RPL_NOT_ALLOWED: DWORD = 4006; +pub const ERROR_DHCP_ADDRESS_CONFLICT: DWORD = 4100; +pub const ERROR_WMI_GUID_NOT_FOUND: DWORD = 4200; +pub const ERROR_WMI_INSTANCE_NOT_FOUND: DWORD = 4201; +pub const ERROR_WMI_ITEMID_NOT_FOUND: DWORD = 4202; +pub const ERROR_WMI_TRY_AGAIN: DWORD = 4203; +pub const ERROR_WMI_DP_NOT_FOUND: DWORD = 4204; +pub const ERROR_WMI_UNRESOLVED_INSTANCE_REF: DWORD = 4205; +pub const ERROR_WMI_ALREADY_ENABLED: DWORD = 4206; +pub const ERROR_WMI_GUID_DISCONNECTED: DWORD = 4207; +pub const ERROR_WMI_SERVER_UNAVAILABLE: DWORD = 4208; +pub const ERROR_WMI_DP_FAILED: DWORD = 4209; +pub const ERROR_WMI_INVALID_MOF: DWORD = 4210; +pub const ERROR_WMI_INVALID_REGINFO: DWORD = 4211; +pub const ERROR_WMI_ALREADY_DISABLED: DWORD = 4212; +pub const ERROR_WMI_READ_ONLY: DWORD = 4213; +pub const ERROR_WMI_SET_FAILURE: DWORD = 4214; +pub const ERROR_INVALID_MEDIA: DWORD = 4300; +pub const ERROR_INVALID_LIBRARY: DWORD = 4301; +pub const ERROR_INVALID_MEDIA_POOL: DWORD = 4302; +pub const ERROR_DRIVE_MEDIA_MISMATCH: DWORD = 4303; +pub const ERROR_MEDIA_OFFLINE: DWORD = 4304; +pub const ERROR_LIBRARY_OFFLINE: DWORD = 4305; +pub const ERROR_EMPTY: DWORD = 4306; +pub const ERROR_NOT_EMPTY: DWORD = 4307; +pub const ERROR_MEDIA_UNAVAILABLE: DWORD = 4308; +pub const ERROR_RESOURCE_DISABLED: DWORD = 4309; +pub const ERROR_INVALID_CLEANER: DWORD = 4310; +pub const ERROR_UNABLE_TO_CLEAN: DWORD = 4311; +pub const ERROR_OBJECT_NOT_FOUND: DWORD = 4312; +pub const ERROR_DATABASE_FAILURE: DWORD = 4313; +pub const ERROR_DATABASE_FULL: DWORD = 4314; +pub const ERROR_MEDIA_INCOMPATIBLE: DWORD = 4315; +pub const ERROR_RESOURCE_NOT_PRESENT: DWORD = 4316; +pub const ERROR_INVALID_OPERATION: DWORD = 4317; +pub const ERROR_MEDIA_NOT_AVAILABLE: DWORD = 4318; +pub const ERROR_DEVICE_NOT_AVAILABLE: DWORD = 4319; +pub const ERROR_REQUEST_REFUSED: DWORD = 4320; +pub const ERROR_INVALID_DRIVE_OBJECT: DWORD = 4321; +pub const ERROR_LIBRARY_FULL: DWORD = 4322; +pub const ERROR_MEDIUM_NOT_ACCESSIBLE: DWORD = 4323; +pub const ERROR_UNABLE_TO_LOAD_MEDIUM: DWORD = 4324; +pub const ERROR_UNABLE_TO_INVENTORY_DRIVE: DWORD = 4325; +pub const ERROR_UNABLE_TO_INVENTORY_SLOT: DWORD = 4326; +pub const ERROR_UNABLE_TO_INVENTORY_TRANSPORT: DWORD = 4327; +pub const ERROR_TRANSPORT_FULL: DWORD = 4328; +pub const ERROR_CONTROLLING_IEPORT: DWORD = 4329; +pub const ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA: DWORD = 4330; +pub const ERROR_CLEANER_SLOT_SET: DWORD = 4331; +pub const ERROR_CLEANER_SLOT_NOT_SET: DWORD = 4332; +pub const ERROR_CLEANER_CARTRIDGE_SPENT: DWORD = 4333; +pub const ERROR_UNEXPECTED_OMID: DWORD = 4334; +pub const ERROR_CANT_DELETE_LAST_ITEM: DWORD = 4335; +pub const ERROR_MESSAGE_EXCEEDS_MAX_SIZE: DWORD = 4336; +pub const ERROR_VOLUME_CONTAINS_SYS_FILES: DWORD = 4337; +pub const ERROR_INDIGENOUS_TYPE: DWORD = 4338; +pub const ERROR_NO_SUPPORTING_DRIVES: DWORD = 4339; +pub const ERROR_CLEANER_CARTRIDGE_INSTALLED: DWORD = 4340; +pub const ERROR_IEPORT_FULL: DWORD = 4341; +pub const ERROR_FILE_OFFLINE: DWORD = 4350; +pub const ERROR_REMOTE_STORAGE_NOT_ACTIVE: DWORD = 4351; +pub const ERROR_REMOTE_STORAGE_MEDIA_ERROR: DWORD = 4352; +pub const ERROR_NOT_A_REPARSE_POINT: DWORD = 4390; +pub const ERROR_REPARSE_ATTRIBUTE_CONFLICT: DWORD = 4391; +pub const ERROR_INVALID_REPARSE_DATA: DWORD = 4392; +pub const ERROR_REPARSE_TAG_INVALID: DWORD = 4393; +pub const ERROR_REPARSE_TAG_MISMATCH: DWORD = 4394; +pub const ERROR_VOLUME_NOT_SIS_ENABLED: DWORD = 4500; +pub const ERROR_DEPENDENT_RESOURCE_EXISTS: DWORD = 5001; +pub const ERROR_DEPENDENCY_NOT_FOUND: DWORD = 5002; +pub const ERROR_DEPENDENCY_ALREADY_EXISTS: DWORD = 5003; +pub const ERROR_RESOURCE_NOT_ONLINE: DWORD = 5004; +pub const ERROR_HOST_NODE_NOT_AVAILABLE: DWORD = 5005; +pub const ERROR_RESOURCE_NOT_AVAILABLE: DWORD = 5006; +pub const ERROR_RESOURCE_NOT_FOUND: DWORD = 5007; +pub const ERROR_SHUTDOWN_CLUSTER: DWORD = 5008; +pub const ERROR_CANT_EVICT_ACTIVE_NODE: DWORD = 5009; +pub const ERROR_OBJECT_ALREADY_EXISTS: DWORD = 5010; +pub const ERROR_OBJECT_IN_LIST: DWORD = 5011; +pub const ERROR_GROUP_NOT_AVAILABLE: DWORD = 5012; +pub const ERROR_GROUP_NOT_FOUND: DWORD = 5013; +pub const ERROR_GROUP_NOT_ONLINE: DWORD = 5014; +pub const ERROR_HOST_NODE_NOT_RESOURCE_OWNER: DWORD = 5015; +pub const ERROR_HOST_NODE_NOT_GROUP_OWNER: DWORD = 5016; +pub const ERROR_RESMON_CREATE_FAILED: DWORD = 5017; +pub const ERROR_RESMON_ONLINE_FAILED: DWORD = 5018; +pub const ERROR_RESOURCE_ONLINE: DWORD = 5019; +pub const ERROR_QUORUM_RESOURCE: DWORD = 5020; +pub const ERROR_NOT_QUORUM_CAPABLE: DWORD = 5021; +pub const ERROR_CLUSTER_SHUTTING_DOWN: DWORD = 5022; +pub const ERROR_INVALID_STATE: DWORD = 5023; +pub const ERROR_RESOURCE_PROPERTIES_STORED: DWORD = 5024; +pub const ERROR_NOT_QUORUM_CLASS: DWORD = 5025; +pub const ERROR_CORE_RESOURCE: DWORD = 5026; +pub const ERROR_QUORUM_RESOURCE_ONLINE_FAILED: DWORD = 5027; +pub const ERROR_QUORUMLOG_OPEN_FAILED: DWORD = 5028; +pub const ERROR_CLUSTERLOG_CORRUPT: DWORD = 5029; +pub const ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE: DWORD = 5030; +pub const ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE: DWORD = 5031; +pub const ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND: DWORD = 5032; +pub const ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE: DWORD = 5033; +pub const ERROR_QUORUM_OWNER_ALIVE: DWORD = 5034; +pub const ERROR_NETWORK_NOT_AVAILABLE: DWORD = 5035; +pub const ERROR_NODE_NOT_AVAILABLE: DWORD = 5036; +pub const ERROR_ALL_NODES_NOT_AVAILABLE: DWORD = 5037; +pub const ERROR_RESOURCE_FAILED: DWORD = 5038; +pub const ERROR_CLUSTER_INVALID_NODE: DWORD = 5039; +pub const ERROR_CLUSTER_NODE_EXISTS: DWORD = 5040; +pub const ERROR_CLUSTER_JOIN_IN_PROGRESS: DWORD = 5041; +pub const ERROR_CLUSTER_NODE_NOT_FOUND: DWORD = 5042; +pub const ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND: DWORD = 5043; +pub const ERROR_CLUSTER_NETWORK_EXISTS: DWORD = 5044; +pub const ERROR_CLUSTER_NETWORK_NOT_FOUND: DWORD = 5045; +pub const ERROR_CLUSTER_NETINTERFACE_EXISTS: DWORD = 5046; +pub const ERROR_CLUSTER_NETINTERFACE_NOT_FOUND: DWORD = 5047; +pub const ERROR_CLUSTER_INVALID_REQUEST: DWORD = 5048; +pub const ERROR_CLUSTER_INVALID_NETWORK_PROVIDER: DWORD = 5049; +pub const ERROR_CLUSTER_NODE_DOWN: DWORD = 5050; +pub const ERROR_CLUSTER_NODE_UNREACHABLE: DWORD = 5051; +pub const ERROR_CLUSTER_NODE_NOT_MEMBER: DWORD = 5052; +pub const ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS: DWORD = 5053; +pub const ERROR_CLUSTER_INVALID_NETWORK: DWORD = 5054; +pub const ERROR_CLUSTER_NODE_UP: DWORD = 5056; +pub const ERROR_CLUSTER_IPADDR_IN_USE: DWORD = 5057; +pub const ERROR_CLUSTER_NODE_NOT_PAUSED: DWORD = 5058; +pub const ERROR_CLUSTER_NO_SECURITY_CONTEXT: DWORD = 5059; +pub const ERROR_CLUSTER_NETWORK_NOT_INTERNAL: DWORD = 5060; +pub const ERROR_CLUSTER_NODE_ALREADY_UP: DWORD = 5061; +pub const ERROR_CLUSTER_NODE_ALREADY_DOWN: DWORD = 5062; +pub const ERROR_CLUSTER_NETWORK_ALREADY_ONLINE: DWORD = 5063; +pub const ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE: DWORD = 5064; +pub const ERROR_CLUSTER_NODE_ALREADY_MEMBER: DWORD = 5065; +pub const ERROR_CLUSTER_LAST_INTERNAL_NETWORK: DWORD = 5066; +pub const ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS: DWORD = 5067; +pub const ERROR_INVALID_OPERATION_ON_QUORUM: DWORD = 5068; +pub const ERROR_DEPENDENCY_NOT_ALLOWED: DWORD = 5069; +pub const ERROR_CLUSTER_NODE_PAUSED: DWORD = 5070; +pub const ERROR_NODE_CANT_HOST_RESOURCE: DWORD = 5071; +pub const ERROR_CLUSTER_NODE_NOT_READY: DWORD = 5072; +pub const ERROR_CLUSTER_NODE_SHUTTING_DOWN: DWORD = 5073; +pub const ERROR_CLUSTER_JOIN_ABORTED: DWORD = 5074; +pub const ERROR_CLUSTER_INCOMPATIBLE_VERSIONS: DWORD = 5075; +pub const ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED: DWORD = 5076; +pub const ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED: DWORD = 5077; +pub const ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND: DWORD = 5078; +pub const ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED: DWORD = 5079; +pub const ERROR_CLUSTER_RESNAME_NOT_FOUND: DWORD = 5080; +pub const ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED: DWORD = 5081; +pub const ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST: DWORD = 5082; +pub const ERROR_CLUSTER_DATABASE_SEQMISMATCH: DWORD = 5083; +pub const ERROR_RESMON_INVALID_STATE: DWORD = 5084; +pub const ERROR_CLUSTER_GUM_NOT_LOCKER: DWORD = 5085; +pub const ERROR_QUORUM_DISK_NOT_FOUND: DWORD = 5086; +pub const ERROR_DATABASE_BACKUP_CORRUPT: DWORD = 5087; +pub const ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT: DWORD = 5088; +pub const ERROR_RESOURCE_PROPERTY_UNCHANGEABLE: DWORD = 5089; +pub const ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE: DWORD = 5890; +pub const ERROR_CLUSTER_QUORUMLOG_NOT_FOUND: DWORD = 5891; +pub const ERROR_CLUSTER_MEMBERSHIP_HALT: DWORD = 5892; +pub const ERROR_CLUSTER_INSTANCE_ID_MISMATCH: DWORD = 5893; +pub const ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP: DWORD = 5894; +pub const ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH: DWORD = 5895; +pub const ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP: DWORD = 5896; +pub const ERROR_CLUSTER_PARAMETER_MISMATCH: DWORD = 5897; +pub const ERROR_NODE_CANNOT_BE_CLUSTERED: DWORD = 5898; +pub const ERROR_CLUSTER_WRONG_OS_VERSION: DWORD = 5899; +pub const ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME: DWORD = 5900; +pub const ERROR_CLUSCFG_ALREADY_COMMITTED: DWORD = 5901; +pub const ERROR_CLUSCFG_ROLLBACK_FAILED: DWORD = 5902; +pub const ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT: DWORD = 5903; +pub const ERROR_CLUSTER_OLD_VERSION: DWORD = 5904; +pub const ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME: DWORD = 5905; +pub const ERROR_ENCRYPTION_FAILED: DWORD = 6000; +pub const ERROR_DECRYPTION_FAILED: DWORD = 6001; +pub const ERROR_FILE_ENCRYPTED: DWORD = 6002; +pub const ERROR_NO_RECOVERY_POLICY: DWORD = 6003; +pub const ERROR_NO_EFS: DWORD = 6004; +pub const ERROR_WRONG_EFS: DWORD = 6005; +pub const ERROR_NO_USER_KEYS: DWORD = 6006; +pub const ERROR_FILE_NOT_ENCRYPTED: DWORD = 6007; +pub const ERROR_NOT_EXPORT_FORMAT: DWORD = 6008; +pub const ERROR_FILE_READ_ONLY: DWORD = 6009; +pub const ERROR_DIR_EFS_DISALLOWED: DWORD = 6010; +pub const ERROR_EFS_SERVER_NOT_TRUSTED: DWORD = 6011; +pub const ERROR_BAD_RECOVERY_POLICY: DWORD = 6012; +pub const ERROR_EFS_ALG_BLOB_TOO_BIG: DWORD = 6013; +pub const ERROR_VOLUME_NOT_SUPPORT_EFS: DWORD = 6014; +pub const ERROR_EFS_DISABLED: DWORD = 6015; +pub const ERROR_EFS_VERSION_NOT_SUPPORT: DWORD = 6016; +pub const ERROR_NO_BROWSER_SERVERS_FOUND: DWORD = 6118; +pub const ERROR_CTX_WINSTATION_NAME_INVALID: DWORD = 7001; +pub const ERROR_CTX_INVALID_PD: DWORD = 7002; +pub const ERROR_CTX_PD_NOT_FOUND: DWORD = 7003; +pub const ERROR_CTX_WD_NOT_FOUND: DWORD = 7004; +pub const ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY: DWORD = 7005; +pub const ERROR_CTX_SERVICE_NAME_COLLISION: DWORD = 7006; +pub const ERROR_CTX_CLOSE_PENDING: DWORD = 7007; +pub const ERROR_CTX_NO_OUTBUF: DWORD = 7008; +pub const ERROR_CTX_MODEM_INF_NOT_FOUND: DWORD = 7009; +pub const ERROR_CTX_INVALID_MODEMNAME: DWORD = 7010; +pub const ERROR_CTX_MODEM_RESPONSE_ERROR: DWORD = 7011; +pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; +pub const ERROR_CTX_MODEM_RESPONSE_NO_CARRIER: DWORD = 7013; +pub const ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE: DWORD = 7014; +pub const ERROR_CTX_MODEM_RESPONSE_BUSY: DWORD = 7015; +pub const ERROR_CTX_MODEM_RESPONSE_VOICE: DWORD = 7016; +pub const ERROR_CTX_TD_ERROR: DWORD = 7017; +pub const ERROR_CTX_WINSTATION_NOT_FOUND: DWORD = 7022; +pub const ERROR_CTX_WINSTATION_ALREADY_EXISTS: DWORD = 7023; +pub const ERROR_CTX_WINSTATION_BUSY: DWORD = 7024; +pub const ERROR_CTX_BAD_VIDEO_MODE: DWORD = 7025; +pub const ERROR_CTX_GRAPHICS_INVALID: DWORD = 7035; +pub const ERROR_CTX_LOGON_DISABLED: DWORD = 7037; +pub const ERROR_CTX_NOT_CONSOLE: DWORD = 7038; +pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; +pub const ERROR_CTX_CONSOLE_DISCONNECT: DWORD = 7041; +pub const ERROR_CTX_CONSOLE_CONNECT: DWORD = 7042; +pub const ERROR_CTX_SHADOW_DENIED: DWORD = 7044; +pub const ERROR_CTX_WINSTATION_ACCESS_DENIED: DWORD = 7045; +pub const ERROR_CTX_INVALID_WD: DWORD = 7049; +pub const ERROR_CTX_SHADOW_INVALID: DWORD = 7050; +pub const ERROR_CTX_SHADOW_DISABLED: DWORD = 7051; +pub const ERROR_CTX_CLIENT_LICENSE_IN_USE: DWORD = 7052; +pub const ERROR_CTX_CLIENT_LICENSE_NOT_SET: DWORD = 7053; +pub const ERROR_CTX_LICENSE_NOT_AVAILABLE: DWORD = 7054; +pub const ERROR_CTX_LICENSE_CLIENT_INVALID: DWORD = 7055; +pub const ERROR_CTX_LICENSE_EXPIRED: DWORD = 7056; +pub const ERROR_CTX_SHADOW_NOT_RUNNING: DWORD = 7057; +pub const ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE: DWORD = 7058; +pub const ERROR_ACTIVATION_COUNT_EXCEEDED: DWORD = 7059; +pub const ERROR_DS_NOT_INSTALLED: DWORD = 8200; +pub const ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY: DWORD = 8201; +pub const ERROR_DS_NO_ATTRIBUTE_OR_VALUE: DWORD = 8202; +pub const ERROR_DS_INVALID_ATTRIBUTE_SYNTAX: DWORD = 8203; +pub const ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED: DWORD = 8204; +pub const ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS: DWORD = 8205; +pub const ERROR_DS_BUSY: DWORD = 8206; +pub const ERROR_DS_UNAVAILABLE: DWORD = 8207; +pub const ERROR_DS_NO_RIDS_ALLOCATED: DWORD = 8208; +pub const ERROR_DS_NO_MORE_RIDS: DWORD = 8209; +pub const ERROR_DS_INCORRECT_ROLE_OWNER: DWORD = 8210; +pub const ERROR_DS_RIDMGR_INIT_ERROR: DWORD = 8211; +pub const ERROR_DS_OBJ_CLASS_VIOLATION: DWORD = 8212; +pub const ERROR_DS_CANT_ON_NON_LEAF: DWORD = 8213; +pub const ERROR_DS_CANT_ON_RDN: DWORD = 8214; +pub const ERROR_DS_CANT_MOD_OBJ_CLASS: DWORD = 8215; +pub const ERROR_DS_CROSS_DOM_MOVE_ERROR: DWORD = 8216; +pub const ERROR_DS_GC_NOT_AVAILABLE: DWORD = 8217; +pub const ERROR_SHARED_POLICY: DWORD = 8218; +pub const ERROR_POLICY_OBJECT_NOT_FOUND: DWORD = 8219; +pub const ERROR_POLICY_ONLY_IN_DS: DWORD = 8220; +pub const ERROR_PROMOTION_ACTIVE: DWORD = 8221; +pub const ERROR_NO_PROMOTION_ACTIVE: DWORD = 8222; +pub const ERROR_DS_OPERATIONS_ERROR: DWORD = 8224; +pub const ERROR_DS_PROTOCOL_ERROR: DWORD = 8225; +pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; +pub const ERROR_DS_SIZELIMIT_EXCEEDED: DWORD = 8227; +pub const ERROR_DS_ADMIN_LIMIT_EXCEEDED: DWORD = 8228; +pub const ERROR_DS_COMPARE_FALSE: DWORD = 8229; +pub const ERROR_DS_COMPARE_TRUE: DWORD = 8230; +pub const ERROR_DS_AUTH_METHOD_NOT_SUPPORTED: DWORD = 8231; +pub const ERROR_DS_STRONG_AUTH_REQUIRED: DWORD = 8232; +pub const ERROR_DS_INAPPROPRIATE_AUTH: DWORD = 8233; +pub const ERROR_DS_AUTH_UNKNOWN: DWORD = 8234; +pub const ERROR_DS_REFERRAL: DWORD = 8235; +pub const ERROR_DS_UNAVAILABLE_CRIT_EXTENSION: DWORD = 8236; +pub const ERROR_DS_CONFIDENTIALITY_REQUIRED: DWORD = 8237; +pub const ERROR_DS_INAPPROPRIATE_MATCHING: DWORD = 8238; +pub const ERROR_DS_CONSTRAINT_VIOLATION: DWORD = 8239; +pub const ERROR_DS_NO_SUCH_OBJECT: DWORD = 8240; +pub const ERROR_DS_ALIAS_PROBLEM: DWORD = 8241; +pub const ERROR_DS_INVALID_DN_SYNTAX: DWORD = 8242; +pub const ERROR_DS_IS_LEAF: DWORD = 8243; +pub const ERROR_DS_ALIAS_DEREF_PROBLEM: DWORD = 8244; +pub const ERROR_DS_UNWILLING_TO_PERFORM: DWORD = 8245; +pub const ERROR_DS_LOOP_DETECT: DWORD = 8246; +pub const ERROR_DS_NAMING_VIOLATION: DWORD = 8247; +pub const ERROR_DS_OBJECT_RESULTS_TOO_LARGE: DWORD = 8248; +pub const ERROR_DS_AFFECTS_MULTIPLE_DSAS: DWORD = 8249; +pub const ERROR_DS_SERVER_DOWN: DWORD = 8250; +pub const ERROR_DS_LOCAL_ERROR: DWORD = 8251; +pub const ERROR_DS_ENCODING_ERROR: DWORD = 8252; +pub const ERROR_DS_DECODING_ERROR: DWORD = 8253; +pub const ERROR_DS_FILTER_UNKNOWN: DWORD = 8254; +pub const ERROR_DS_PARAM_ERROR: DWORD = 8255; +pub const ERROR_DS_NOT_SUPPORTED: DWORD = 8256; +pub const ERROR_DS_NO_RESULTS_RETURNED: DWORD = 8257; +pub const ERROR_DS_CONTROL_NOT_FOUND: DWORD = 8258; +pub const ERROR_DS_CLIENT_LOOP: DWORD = 8259; +pub const ERROR_DS_REFERRAL_LIMIT_EXCEEDED: DWORD = 8260; +pub const ERROR_DS_SORT_CONTROL_MISSING: DWORD = 8261; +pub const ERROR_DS_OFFSET_RANGE_ERROR: DWORD = 8262; +pub const ERROR_DS_ROOT_MUST_BE_NC: DWORD = 8301; +pub const ERROR_DS_ADD_REPLICA_INHIBITED: DWORD = 8302; +pub const ERROR_DS_ATT_NOT_DEF_IN_SCHEMA: DWORD = 8303; +pub const ERROR_DS_MAX_OBJ_SIZE_EXCEEDED: DWORD = 8304; +pub const ERROR_DS_OBJ_STRING_NAME_EXISTS: DWORD = 8305; +pub const ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA: DWORD = 8306; +pub const ERROR_DS_RDN_DOESNT_MATCH_SCHEMA: DWORD = 8307; +pub const ERROR_DS_NO_REQUESTED_ATTS_FOUND: DWORD = 8308; +pub const ERROR_DS_USER_BUFFER_TO_SMALL: DWORD = 8309; +pub const ERROR_DS_ATT_IS_NOT_ON_OBJ: DWORD = 8310; +pub const ERROR_DS_ILLEGAL_MOD_OPERATION: DWORD = 8311; +pub const ERROR_DS_OBJ_TOO_LARGE: DWORD = 8312; +pub const ERROR_DS_BAD_INSTANCE_TYPE: DWORD = 8313; +pub const ERROR_DS_MASTERDSA_REQUIRED: DWORD = 8314; +pub const ERROR_DS_OBJECT_CLASS_REQUIRED: DWORD = 8315; +pub const ERROR_DS_MISSING_REQUIRED_ATT: DWORD = 8316; +pub const ERROR_DS_ATT_NOT_DEF_FOR_CLASS: DWORD = 8317; +pub const ERROR_DS_ATT_ALREADY_EXISTS: DWORD = 8318; +pub const ERROR_DS_CANT_ADD_ATT_VALUES: DWORD = 8320; +pub const ERROR_DS_SINGLE_VALUE_CONSTRAINT: DWORD = 8321; +pub const ERROR_DS_RANGE_CONSTRAINT: DWORD = 8322; +pub const ERROR_DS_ATT_VAL_ALREADY_EXISTS: DWORD = 8323; +pub const ERROR_DS_CANT_REM_MISSING_ATT: DWORD = 8324; +pub const ERROR_DS_CANT_REM_MISSING_ATT_VAL: DWORD = 8325; +pub const ERROR_DS_ROOT_CANT_BE_SUBREF: DWORD = 8326; +pub const ERROR_DS_NO_CHAINING: DWORD = 8327; +pub const ERROR_DS_NO_CHAINED_EVAL: DWORD = 8328; +pub const ERROR_DS_NO_PARENT_OBJECT: DWORD = 8329; +pub const ERROR_DS_PARENT_IS_AN_ALIAS: DWORD = 8330; +pub const ERROR_DS_CANT_MIX_MASTER_AND_REPS: DWORD = 8331; +pub const ERROR_DS_CHILDREN_EXIST: DWORD = 8332; +pub const ERROR_DS_OBJ_NOT_FOUND: DWORD = 8333; +pub const ERROR_DS_ALIASED_OBJ_MISSING: DWORD = 8334; +pub const ERROR_DS_BAD_NAME_SYNTAX: DWORD = 8335; +pub const ERROR_DS_ALIAS_POINTS_TO_ALIAS: DWORD = 8336; +pub const ERROR_DS_CANT_DEREF_ALIAS: DWORD = 8337; +pub const ERROR_DS_OUT_OF_SCOPE: DWORD = 8338; +pub const ERROR_DS_OBJECT_BEING_REMOVED: DWORD = 8339; +pub const ERROR_DS_CANT_DELETE_DSA_OBJ: DWORD = 8340; +pub const ERROR_DS_GENERIC_ERROR: DWORD = 8341; +pub const ERROR_DS_DSA_MUST_BE_INT_MASTER: DWORD = 8342; +pub const ERROR_DS_CLASS_NOT_DSA: DWORD = 8343; +pub const ERROR_DS_INSUFF_ACCESS_RIGHTS: DWORD = 8344; +pub const ERROR_DS_ILLEGAL_SUPERIOR: DWORD = 8345; +pub const ERROR_DS_ATTRIBUTE_OWNED_BY_SAM: DWORD = 8346; +pub const ERROR_DS_NAME_TOO_MANY_PARTS: DWORD = 8347; +pub const ERROR_DS_NAME_TOO_LONG: DWORD = 8348; +pub const ERROR_DS_NAME_VALUE_TOO_LONG: DWORD = 8349; +pub const ERROR_DS_NAME_UNPARSEABLE: DWORD = 8350; +pub const ERROR_DS_NAME_TYPE_UNKNOWN: DWORD = 8351; +pub const ERROR_DS_NOT_AN_OBJECT: DWORD = 8352; +pub const ERROR_DS_SEC_DESC_TOO_SHORT: DWORD = 8353; +pub const ERROR_DS_SEC_DESC_INVALID: DWORD = 8354; +pub const ERROR_DS_NO_DELETED_NAME: DWORD = 8355; +pub const ERROR_DS_SUBREF_MUST_HAVE_PARENT: DWORD = 8356; +pub const ERROR_DS_NCNAME_MUST_BE_NC: DWORD = 8357; +pub const ERROR_DS_CANT_ADD_SYSTEM_ONLY: DWORD = 8358; +pub const ERROR_DS_CLASS_MUST_BE_CONCRETE: DWORD = 8359; +pub const ERROR_DS_INVALID_DMD: DWORD = 8360; +pub const ERROR_DS_OBJ_GUID_EXISTS: DWORD = 8361; +pub const ERROR_DS_NOT_ON_BACKLINK: DWORD = 8362; +pub const ERROR_DS_NO_CROSSREF_FOR_NC: DWORD = 8363; +pub const ERROR_DS_SHUTTING_DOWN: DWORD = 8364; +pub const ERROR_DS_UNKNOWN_OPERATION: DWORD = 8365; +pub const ERROR_DS_INVALID_ROLE_OWNER: DWORD = 8366; +pub const ERROR_DS_COULDNT_CONTACT_FSMO: DWORD = 8367; +pub const ERROR_DS_CROSS_NC_DN_RENAME: DWORD = 8368; +pub const ERROR_DS_CANT_MOD_SYSTEM_ONLY: DWORD = 8369; +pub const ERROR_DS_REPLICATOR_ONLY: DWORD = 8370; +pub const ERROR_DS_OBJ_CLASS_NOT_DEFINED: DWORD = 8371; +pub const ERROR_DS_OBJ_CLASS_NOT_SUBCLASS: DWORD = 8372; +pub const ERROR_DS_NAME_REFERENCE_INVALID: DWORD = 8373; +pub const ERROR_DS_CROSS_REF_EXISTS: DWORD = 8374; +pub const ERROR_DS_CANT_DEL_MASTER_CROSSREF: DWORD = 8375; +pub const ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD: DWORD = 8376; +pub const ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX: DWORD = 8377; +pub const ERROR_DS_DUP_RDN: DWORD = 8378; +pub const ERROR_DS_DUP_OID: DWORD = 8379; +pub const ERROR_DS_DUP_MAPI_ID: DWORD = 8380; +pub const ERROR_DS_DUP_SCHEMA_ID_GUID: DWORD = 8381; +pub const ERROR_DS_DUP_LDAP_DISPLAY_NAME: DWORD = 8382; +pub const ERROR_DS_SEMANTIC_ATT_TEST: DWORD = 8383; +pub const ERROR_DS_SYNTAX_MISMATCH: DWORD = 8384; +pub const ERROR_DS_EXISTS_IN_MUST_HAVE: DWORD = 8385; +pub const ERROR_DS_EXISTS_IN_MAY_HAVE: DWORD = 8386; +pub const ERROR_DS_NONEXISTENT_MAY_HAVE: DWORD = 8387; +pub const ERROR_DS_NONEXISTENT_MUST_HAVE: DWORD = 8388; +pub const ERROR_DS_AUX_CLS_TEST_FAIL: DWORD = 8389; +pub const ERROR_DS_NONEXISTENT_POSS_SUP: DWORD = 8390; +pub const ERROR_DS_SUB_CLS_TEST_FAIL: DWORD = 8391; +pub const ERROR_DS_BAD_RDN_ATT_ID_SYNTAX: DWORD = 8392; +pub const ERROR_DS_EXISTS_IN_AUX_CLS: DWORD = 8393; +pub const ERROR_DS_EXISTS_IN_SUB_CLS: DWORD = 8394; +pub const ERROR_DS_EXISTS_IN_POSS_SUP: DWORD = 8395; +pub const ERROR_DS_RECALCSCHEMA_FAILED: DWORD = 8396; +pub const ERROR_DS_TREE_DELETE_NOT_FINISHED: DWORD = 8397; +pub const ERROR_DS_CANT_DELETE: DWORD = 8398; +pub const ERROR_DS_ATT_SCHEMA_REQ_ID: DWORD = 8399; +pub const ERROR_DS_BAD_ATT_SCHEMA_SYNTAX: DWORD = 8400; +pub const ERROR_DS_CANT_CACHE_ATT: DWORD = 8401; +pub const ERROR_DS_CANT_CACHE_CLASS: DWORD = 8402; +pub const ERROR_DS_CANT_REMOVE_ATT_CACHE: DWORD = 8403; +pub const ERROR_DS_CANT_REMOVE_CLASS_CACHE: DWORD = 8404; +pub const ERROR_DS_CANT_RETRIEVE_DN: DWORD = 8405; +pub const ERROR_DS_MISSING_SUPREF: DWORD = 8406; +pub const ERROR_DS_CANT_RETRIEVE_INSTANCE: DWORD = 8407; +pub const ERROR_DS_CODE_INCONSISTENCY: DWORD = 8408; +pub const ERROR_DS_DATABASE_ERROR: DWORD = 8409; +pub const ERROR_DS_GOVERNSID_MISSING: DWORD = 8410; +pub const ERROR_DS_MISSING_EXPECTED_ATT: DWORD = 8411; +pub const ERROR_DS_NCNAME_MISSING_CR_REF: DWORD = 8412; +pub const ERROR_DS_SECURITY_CHECKING_ERROR: DWORD = 8413; +pub const ERROR_DS_SCHEMA_NOT_LOADED: DWORD = 8414; +pub const ERROR_DS_SCHEMA_ALLOC_FAILED: DWORD = 8415; +pub const ERROR_DS_ATT_SCHEMA_REQ_SYNTAX: DWORD = 8416; +pub const ERROR_DS_GCVERIFY_ERROR: DWORD = 8417; +pub const ERROR_DS_DRA_SCHEMA_MISMATCH: DWORD = 8418; +pub const ERROR_DS_CANT_FIND_DSA_OBJ: DWORD = 8419; +pub const ERROR_DS_CANT_FIND_EXPECTED_NC: DWORD = 8420; +pub const ERROR_DS_CANT_FIND_NC_IN_CACHE: DWORD = 8421; +pub const ERROR_DS_CANT_RETRIEVE_CHILD: DWORD = 8422; +pub const ERROR_DS_SECURITY_ILLEGAL_MODIFY: DWORD = 8423; +pub const ERROR_DS_CANT_REPLACE_HIDDEN_REC: DWORD = 8424; +pub const ERROR_DS_BAD_HIERARCHY_FILE: DWORD = 8425; +pub const ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED: DWORD = 8426; +pub const ERROR_DS_CONFIG_PARAM_MISSING: DWORD = 8427; +pub const ERROR_DS_COUNTING_AB_INDICES_FAILED: DWORD = 8428; +pub const ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED: DWORD = 8429; +pub const ERROR_DS_INTERNAL_FAILURE: DWORD = 8430; +pub const ERROR_DS_UNKNOWN_ERROR: DWORD = 8431; +pub const ERROR_DS_ROOT_REQUIRES_CLASS_TOP: DWORD = 8432; +pub const ERROR_DS_REFUSING_FSMO_ROLES: DWORD = 8433; +pub const ERROR_DS_MISSING_FSMO_SETTINGS: DWORD = 8434; +pub const ERROR_DS_UNABLE_TO_SURRENDER_ROLES: DWORD = 8435; +pub const ERROR_DS_DRA_GENERIC: DWORD = 8436; +pub const ERROR_DS_DRA_INVALID_PARAMETER: DWORD = 8437; +pub const ERROR_DS_DRA_BUSY: DWORD = 8438; +pub const ERROR_DS_DRA_BAD_DN: DWORD = 8439; +pub const ERROR_DS_DRA_BAD_NC: DWORD = 8440; +pub const ERROR_DS_DRA_DN_EXISTS: DWORD = 8441; +pub const ERROR_DS_DRA_INTERNAL_ERROR: DWORD = 8442; +pub const ERROR_DS_DRA_INCONSISTENT_DIT: DWORD = 8443; +pub const ERROR_DS_DRA_CONNECTION_FAILED: DWORD = 8444; +pub const ERROR_DS_DRA_BAD_INSTANCE_TYPE: DWORD = 8445; +pub const ERROR_DS_DRA_OUT_OF_MEM: DWORD = 8446; +pub const ERROR_DS_DRA_MAIL_PROBLEM: DWORD = 8447; +pub const ERROR_DS_DRA_REF_ALREADY_EXISTS: DWORD = 8448; +pub const ERROR_DS_DRA_REF_NOT_FOUND: DWORD = 8449; +pub const ERROR_DS_DRA_OBJ_IS_REP_SOURCE: DWORD = 8450; +pub const ERROR_DS_DRA_DB_ERROR: DWORD = 8451; +pub const ERROR_DS_DRA_NO_REPLICA: DWORD = 8452; +pub const ERROR_DS_DRA_ACCESS_DENIED: DWORD = 8453; +pub const ERROR_DS_DRA_NOT_SUPPORTED: DWORD = 8454; +pub const ERROR_DS_DRA_RPC_CANCELLED: DWORD = 8455; +pub const ERROR_DS_DRA_SOURCE_DISABLED: DWORD = 8456; +pub const ERROR_DS_DRA_SINK_DISABLED: DWORD = 8457; +pub const ERROR_DS_DRA_NAME_COLLISION: DWORD = 8458; +pub const ERROR_DS_DRA_SOURCE_REINSTALLED: DWORD = 8459; +pub const ERROR_DS_DRA_MISSING_PARENT: DWORD = 8460; +pub const ERROR_DS_DRA_PREEMPTED: DWORD = 8461; +pub const ERROR_DS_DRA_ABANDON_SYNC: DWORD = 8462; +pub const ERROR_DS_DRA_SHUTDOWN: DWORD = 8463; +pub const ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET: DWORD = 8464; +pub const ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA: DWORD = 8465; +pub const ERROR_DS_DRA_EXTN_CONNECTION_FAILED: DWORD = 8466; +pub const ERROR_DS_INSTALL_SCHEMA_MISMATCH: DWORD = 8467; +pub const ERROR_DS_DUP_LINK_ID: DWORD = 8468; +pub const ERROR_DS_NAME_ERROR_RESOLVING: DWORD = 8469; +pub const ERROR_DS_NAME_ERROR_NOT_FOUND: DWORD = 8470; +pub const ERROR_DS_NAME_ERROR_NOT_UNIQUE: DWORD = 8471; +pub const ERROR_DS_NAME_ERROR_NO_MAPPING: DWORD = 8472; +pub const ERROR_DS_NAME_ERROR_DOMAIN_ONLY: DWORD = 8473; +pub const ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING: DWORD = 8474; +pub const ERROR_DS_CONSTRUCTED_ATT_MOD: DWORD = 8475; +pub const ERROR_DS_WRONG_OM_OBJ_CLASS: DWORD = 8476; +pub const ERROR_DS_DRA_REPL_PENDING: DWORD = 8477; +pub const ERROR_DS_DS_REQUIRED: DWORD = 8478; +pub const ERROR_DS_INVALID_LDAP_DISPLAY_NAME: DWORD = 8479; +pub const ERROR_DS_NON_BASE_SEARCH: DWORD = 8480; +pub const ERROR_DS_CANT_RETRIEVE_ATTS: DWORD = 8481; +pub const ERROR_DS_BACKLINK_WITHOUT_LINK: DWORD = 8482; +pub const ERROR_DS_EPOCH_MISMATCH: DWORD = 8483; +pub const ERROR_DS_SRC_NAME_MISMATCH: DWORD = 8484; +pub const ERROR_DS_SRC_AND_DST_NC_IDENTICAL: DWORD = 8485; +pub const ERROR_DS_DST_NC_MISMATCH: DWORD = 8486; +pub const ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC: DWORD = 8487; +pub const ERROR_DS_SRC_GUID_MISMATCH: DWORD = 8488; +pub const ERROR_DS_CANT_MOVE_DELETED_OBJECT: DWORD = 8489; +pub const ERROR_DS_PDC_OPERATION_IN_PROGRESS: DWORD = 8490; +pub const ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD: DWORD = 8491; +pub const ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION: DWORD = 8492; +pub const ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS: DWORD = 8493; +pub const ERROR_DS_NC_MUST_HAVE_NC_PARENT: DWORD = 8494; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE: DWORD = 8495; +pub const ERROR_DS_DST_DOMAIN_NOT_NATIVE: DWORD = 8496; +pub const ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER: DWORD = 8497; +pub const ERROR_DS_CANT_MOVE_ACCOUNT_GROUP: DWORD = 8498; +pub const ERROR_DS_CANT_MOVE_RESOURCE_GROUP: DWORD = 8499; +pub const ERROR_DS_INVALID_SEARCH_FLAG: DWORD = 8500; +pub const ERROR_DS_NO_TREE_DELETE_ABOVE_NC: DWORD = 8501; +pub const ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE: DWORD = 8502; +pub const ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE: DWORD = 8503; +pub const ERROR_DS_SAM_INIT_FAILURE: DWORD = 8504; +pub const ERROR_DS_SENSITIVE_GROUP_VIOLATION: DWORD = 8505; +pub const ERROR_DS_CANT_MOD_PRIMARYGROUPID: DWORD = 8506; +pub const ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD: DWORD = 8507; +pub const ERROR_DS_NONSAFE_SCHEMA_CHANGE: DWORD = 8508; +pub const ERROR_DS_SCHEMA_UPDATE_DISALLOWED: DWORD = 8509; +pub const ERROR_DS_CANT_CREATE_UNDER_SCHEMA: DWORD = 8510; +pub const ERROR_DS_INSTALL_NO_SRC_SCH_VERSION: DWORD = 8511; +pub const ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE: DWORD = 8512; +pub const ERROR_DS_INVALID_GROUP_TYPE: DWORD = 8513; +pub const ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: DWORD = 8514; +pub const ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: DWORD = 8515; +pub const ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8516; +pub const ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8517; +pub const ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8518; +pub const ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: DWORD = 8519; +pub const ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: DWORD = 8520; +pub const ERROR_DS_HAVE_PRIMARY_MEMBERS: DWORD = 8521; +pub const ERROR_DS_STRING_SD_CONVERSION_FAILED: DWORD = 8522; +pub const ERROR_DS_NAMING_MASTER_GC: DWORD = 8523; +pub const ERROR_DS_DNS_LOOKUP_FAILURE: DWORD = 8524; +pub const ERROR_DS_COULDNT_UPDATE_SPNS: DWORD = 8525; +pub const ERROR_DS_CANT_RETRIEVE_SD: DWORD = 8526; +pub const ERROR_DS_KEY_NOT_UNIQUE: DWORD = 8527; +pub const ERROR_DS_WRONG_LINKED_ATT_SYNTAX: DWORD = 8528; +pub const ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD: DWORD = 8529; +pub const ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY: DWORD = 8530; +pub const ERROR_DS_CANT_START: DWORD = 8531; +pub const ERROR_DS_INIT_FAILURE: DWORD = 8532; +pub const ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION: DWORD = 8533; +pub const ERROR_DS_SOURCE_DOMAIN_IN_FOREST: DWORD = 8534; +pub const ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST: DWORD = 8535; +pub const ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED: DWORD = 8536; +pub const ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN: DWORD = 8537; +pub const ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER: DWORD = 8538; +pub const ERROR_DS_SRC_SID_EXISTS_IN_FOREST: DWORD = 8539; +pub const ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH: DWORD = 8540; +pub const ERROR_SAM_INIT_FAILURE: DWORD = 8541; +pub const ERROR_DS_DRA_SCHEMA_INFO_SHIP: DWORD = 8542; +pub const ERROR_DS_DRA_SCHEMA_CONFLICT: DWORD = 8543; +pub const ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT: DWORD = 8544; +pub const ERROR_DS_DRA_OBJ_NC_MISMATCH: DWORD = 8545; +pub const ERROR_DS_NC_STILL_HAS_DSAS: DWORD = 8546; +pub const ERROR_DS_GC_REQUIRED: DWORD = 8547; +pub const ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: DWORD = 8548; +pub const ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS: DWORD = 8549; +pub const ERROR_DS_CANT_ADD_TO_GC: DWORD = 8550; +pub const ERROR_DS_NO_CHECKPOINT_WITH_PDC: DWORD = 8551; +pub const ERROR_DS_SOURCE_AUDITING_NOT_ENABLED: DWORD = 8552; +pub const ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC: DWORD = 8553; +pub const ERROR_DS_INVALID_NAME_FOR_SPN: DWORD = 8554; +pub const ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS: DWORD = 8555; +pub const ERROR_DS_UNICODEPWD_NOT_IN_QUOTES: DWORD = 8556; +pub const ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: DWORD = 8557; +pub const ERROR_DS_MUST_BE_RUN_ON_DST_DC: DWORD = 8558; +pub const ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER: DWORD = 8559; +pub const ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ: DWORD = 8560; +pub const ERROR_DS_INIT_FAILURE_CONSOLE: DWORD = 8561; +pub const ERROR_DS_SAM_INIT_FAILURE_CONSOLE: DWORD = 8562; +pub const ERROR_DS_FOREST_VERSION_TOO_HIGH: DWORD = 8563; +pub const ERROR_DS_DOMAIN_VERSION_TOO_HIGH: DWORD = 8564; +pub const ERROR_DS_FOREST_VERSION_TOO_LOW: DWORD = 8565; +pub const ERROR_DS_DOMAIN_VERSION_TOO_LOW: DWORD = 8566; +pub const ERROR_DS_INCOMPATIBLE_VERSION: DWORD = 8567; +pub const ERROR_DS_LOW_DSA_VERSION: DWORD = 8568; +pub const ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN: DWORD = 8569; +pub const ERROR_DS_NOT_SUPPORTED_SORT_ORDER: DWORD = 8570; +pub const ERROR_DS_NAME_NOT_UNIQUE: DWORD = 8571; +pub const ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4: DWORD = 8572; +pub const ERROR_DS_OUT_OF_VERSION_STORE: DWORD = 8573; +pub const ERROR_DS_INCOMPATIBLE_CONTROLS_USED: DWORD = 8574; +pub const ERROR_DS_NO_REF_DOMAIN: DWORD = 8575; +pub const ERROR_DS_RESERVED_LINK_ID: DWORD = 8576; +pub const ERROR_DS_LINK_ID_NOT_AVAILABLE: DWORD = 8577; +pub const ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8578; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE: DWORD = 8579; +pub const ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC: DWORD = 8580; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG: DWORD = 8581; +pub const ERROR_DS_MODIFYDN_WRONG_GRANDPARENT: DWORD = 8582; +pub const ERROR_DS_NAME_ERROR_TRUST_REFERRAL: DWORD = 8583; +pub const ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER: DWORD = 8584; +pub const ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD: DWORD = 8585; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2: DWORD = 8586; +pub const ERROR_DS_THREAD_LIMIT_EXCEEDED: DWORD = 8587; +pub const ERROR_DS_NOT_CLOSEST: DWORD = 8588; +pub const ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF: DWORD = 8589; +pub const ERROR_DS_SINGLE_USER_MODE_FAILED: DWORD = 8590; +pub const ERROR_DS_NTDSCRIPT_SYNTAX_ERROR: DWORD = 8591; +pub const ERROR_DS_NTDSCRIPT_PROCESS_ERROR: DWORD = 8592; +pub const ERROR_DS_DIFFERENT_REPL_EPOCHS: DWORD = 8593; +pub const ERROR_DS_DRS_EXTENSIONS_CHANGED: DWORD = 8594; +pub const ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR: DWORD = 8595; +pub const ERROR_DS_NO_MSDS_INTID: DWORD = 8596; +pub const ERROR_DS_DUP_MSDS_INTID: DWORD = 8597; +pub const ERROR_DS_EXISTS_IN_RDNATTID: DWORD = 8598; +pub const ERROR_DS_AUTHORIZATION_FAILED: DWORD = 8599; +pub const ERROR_DS_INVALID_SCRIPT: DWORD = 8600; +pub const ERROR_DS_REMOTE_CROSSREF_OP_FAILED: DWORD = 8601; +pub const ERROR_DS_CROSS_REF_BUSY: DWORD = 8602; +pub const ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN: DWORD = 8603; +pub const ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC: DWORD = 8604; +pub const ERROR_DS_DUPLICATE_ID_FOUND: DWORD = 8605; +pub const ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT: DWORD = 8606; +pub const ERROR_DS_GROUP_CONVERSION_ERROR: DWORD = 8607; +pub const ERROR_DS_CANT_MOVE_APP_BASIC_GROUP: DWORD = 8608; +pub const ERROR_DS_CANT_MOVE_APP_QUERY_GROUP: DWORD = 8609; +pub const ERROR_DS_ROLE_NOT_VERIFIED: DWORD = 8610; +pub const ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL: DWORD = 8611; +pub const ERROR_DS_DOMAIN_RENAME_IN_PROGRESS: DWORD = 8612; +pub const ERROR_DS_EXISTING_AD_CHILD_NC: DWORD = 8613; +pub const ERROR_DS_REPL_LIFETIME_EXCEEDED: DWORD = 8614; +pub const ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER: DWORD = 8615; +pub const ERROR_DS_LDAP_SEND_QUEUE_FULL: DWORD = 8616; +pub const ERROR_DS_DRA_OUT_SCHEDULE_WINDOW: DWORD = 8617; +pub const ERROR_SXS_SECTION_NOT_FOUND: DWORD = 14000; +pub const ERROR_SXS_CANT_GEN_ACTCTX: DWORD = 14001; +pub const ERROR_SXS_INVALID_ACTCTXDATA_FORMAT: DWORD = 14002; +pub const ERROR_SXS_ASSEMBLY_NOT_FOUND: DWORD = 14003; +pub const ERROR_SXS_MANIFEST_FORMAT_ERROR: DWORD = 14004; +pub const ERROR_SXS_MANIFEST_PARSE_ERROR: DWORD = 14005; +pub const ERROR_SXS_ACTIVATION_CONTEXT_DISABLED: DWORD = 14006; +pub const ERROR_SXS_KEY_NOT_FOUND: DWORD = 14007; +pub const ERROR_SXS_VERSION_CONFLICT: DWORD = 14008; +pub const ERROR_SXS_WRONG_SECTION_TYPE: DWORD = 14009; +pub const ERROR_SXS_THREAD_QUERIES_DISABLED: DWORD = 14010; +pub const ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET: DWORD = 14011; +pub const ERROR_SXS_UNKNOWN_ENCODING_GROUP: DWORD = 14012; +pub const ERROR_SXS_UNKNOWN_ENCODING: DWORD = 14013; +pub const ERROR_SXS_INVALID_XML_NAMESPACE_URI: DWORD = 14014; +pub const ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14015; +pub const ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14016; +pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14017; +pub const ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14018; +pub const ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14019; +pub const ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT: DWORD = 14020; +pub const ERROR_SXS_DUPLICATE_DLL_NAME: DWORD = 14021; +pub const ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME: DWORD = 14022; +pub const ERROR_SXS_DUPLICATE_CLSID: DWORD = 14023; +pub const ERROR_SXS_DUPLICATE_IID: DWORD = 14024; +pub const ERROR_SXS_DUPLICATE_TLBID: DWORD = 14025; +pub const ERROR_SXS_DUPLICATE_PROGID: DWORD = 14026; +pub const ERROR_SXS_DUPLICATE_ASSEMBLY_NAME: DWORD = 14027; +pub const ERROR_SXS_FILE_HASH_MISMATCH: DWORD = 14028; +pub const ERROR_SXS_POLICY_PARSE_ERROR: DWORD = 14029; +pub const ERROR_SXS_XML_E_MISSINGQUOTE: DWORD = 14030; +pub const ERROR_SXS_XML_E_COMMENTSYNTAX: DWORD = 14031; +pub const ERROR_SXS_XML_E_BADSTARTNAMECHAR: DWORD = 14032; +pub const ERROR_SXS_XML_E_BADNAMECHAR: DWORD = 14033; +pub const ERROR_SXS_XML_E_BADCHARINSTRING: DWORD = 14034; +pub const ERROR_SXS_XML_E_XMLDECLSYNTAX: DWORD = 14035; +pub const ERROR_SXS_XML_E_BADCHARDATA: DWORD = 14036; +pub const ERROR_SXS_XML_E_MISSINGWHITESPACE: DWORD = 14037; +pub const ERROR_SXS_XML_E_EXPECTINGTAGEND: DWORD = 14038; +pub const ERROR_SXS_XML_E_MISSINGSEMICOLON: DWORD = 14039; +pub const ERROR_SXS_XML_E_UNBALANCEDPAREN: DWORD = 14040; +pub const ERROR_SXS_XML_E_INTERNALERROR: DWORD = 14041; +pub const ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE: DWORD = 14042; +pub const ERROR_SXS_XML_E_INCOMPLETE_ENCODING: DWORD = 14043; +pub const ERROR_SXS_XML_E_MISSING_PAREN: DWORD = 14044; +pub const ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE: DWORD = 14045; +pub const ERROR_SXS_XML_E_MULTIPLE_COLONS: DWORD = 14046; +pub const ERROR_SXS_XML_E_INVALID_DECIMAL: DWORD = 14047; +pub const ERROR_SXS_XML_E_INVALID_HEXIDECIMAL: DWORD = 14048; +pub const ERROR_SXS_XML_E_INVALID_UNICODE: DWORD = 14049; +pub const ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK: DWORD = 14050; +pub const ERROR_SXS_XML_E_UNEXPECTEDENDTAG: DWORD = 14051; +pub const ERROR_SXS_XML_E_UNCLOSEDTAG: DWORD = 14052; +pub const ERROR_SXS_XML_E_DUPLICATEATTRIBUTE: DWORD = 14053; +pub const ERROR_SXS_XML_E_MULTIPLEROOTS: DWORD = 14054; +pub const ERROR_SXS_XML_E_INVALIDATROOTLEVEL: DWORD = 14055; +pub const ERROR_SXS_XML_E_BADXMLDECL: DWORD = 14056; +pub const ERROR_SXS_XML_E_MISSINGROOT: DWORD = 14057; +pub const ERROR_SXS_XML_E_UNEXPECTEDEOF: DWORD = 14058; +pub const ERROR_SXS_XML_E_BADPEREFINSUBSET: DWORD = 14059; +pub const ERROR_SXS_XML_E_UNCLOSEDSTARTTAG: DWORD = 14060; +pub const ERROR_SXS_XML_E_UNCLOSEDENDTAG: DWORD = 14061; +pub const ERROR_SXS_XML_E_UNCLOSEDSTRING: DWORD = 14062; +pub const ERROR_SXS_XML_E_UNCLOSEDCOMMENT: DWORD = 14063; +pub const ERROR_SXS_XML_E_UNCLOSEDDECL: DWORD = 14064; +pub const ERROR_SXS_XML_E_UNCLOSEDCDATA: DWORD = 14065; +pub const ERROR_SXS_XML_E_RESERVEDNAMESPACE: DWORD = 14066; +pub const ERROR_SXS_XML_E_INVALIDENCODING: DWORD = 14067; +pub const ERROR_SXS_XML_E_INVALIDSWITCH: DWORD = 14068; +pub const ERROR_SXS_XML_E_BADXMLCASE: DWORD = 14069; +pub const ERROR_SXS_XML_E_INVALID_STANDALONE: DWORD = 14070; +pub const ERROR_SXS_XML_E_UNEXPECTED_STANDALONE: DWORD = 14071; +pub const ERROR_SXS_XML_E_INVALID_VERSION: DWORD = 14072; +pub const ERROR_SXS_XML_E_MISSINGEQUALS: DWORD = 14073; +pub const ERROR_SXS_PROTECTION_RECOVERY_FAILED: DWORD = 14074; +pub const ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT: DWORD = 14075; +pub const ERROR_SXS_PROTECTION_CATALOG_NOT_VALID: DWORD = 14076; +pub const ERROR_SXS_UNTRANSLATABLE_HRESULT: DWORD = 14077; +pub const ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING: DWORD = 14078; +pub const ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14079; +pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME: DWORD = 14080; +pub const ERROR_SXS_ASSEMBLY_MISSING: DWORD = 14081; +pub const ERROR_SXS_CORRUPT_ACTIVATION_STACK: DWORD = 14082; +pub const ERROR_SXS_CORRUPTION: DWORD = 14083; +pub const ERROR_SXS_EARLY_DEACTIVATION: DWORD = 14084; +pub const ERROR_SXS_INVALID_DEACTIVATION: DWORD = 14085; +pub const ERROR_SXS_MULTIPLE_DEACTIVATION: DWORD = 14086; +pub const ERROR_SXS_PROCESS_TERMINATION_REQUESTED: DWORD = 14087; +pub const ERROR_SXS_RELEASE_ACTIVATION_CONTEXT: DWORD = 14088; +pub const ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY: DWORD = 14089; +pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE: DWORD = 14090; +pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME: DWORD = 14091; +pub const ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE: DWORD = 14092; +pub const ERROR_SXS_IDENTITY_PARSE_ERROR: DWORD = 14093; +pub const ERROR_MALFORMED_SUBSTITUTION_STRING: DWORD = 14094; +pub const ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN: DWORD = 14095; +pub const ERROR_UNMAPPED_SUBSTITUTION_STRING: DWORD = 14096; +pub const ERROR_SXS_ASSEMBLY_NOT_LOCKED: DWORD = 14097; +pub const ERROR_SXS_COMPONENT_STORE_CORRUPT: DWORD = 14098; +pub const ERROR_ADVANCED_INSTALLER_FAILED: DWORD = 14099; +pub const ERROR_XML_ENCODING_MISMATCH: DWORD = 14100; +pub const ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT: DWORD = 14101; +pub const ERROR_SXS_IDENTITIES_DIFFERENT: DWORD = 14102; +pub const ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT: DWORD = 14103; +pub const ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY: DWORD = 14104; +pub const ERROR_SXS_MANIFEST_TOO_BIG: DWORD = 14105; +pub const ERROR_SXS_SETTING_NOT_REGISTERED: DWORD = 14106; +pub const ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE: DWORD = 14107; +pub const ERROR_SMI_PRIMITIVE_INSTALLER_FAILED: DWORD = 14108; +pub const ERROR_GENERIC_COMMAND_FAILED: DWORD = 14109; +pub const ERROR_SXS_FILE_HASH_MISSING: DWORD = 14110; +pub const ERROR_IPSEC_QM_POLICY_EXISTS: DWORD = 13000; +pub const ERROR_IPSEC_QM_POLICY_NOT_FOUND: DWORD = 13001; +pub const ERROR_IPSEC_QM_POLICY_IN_USE: DWORD = 13002; +pub const ERROR_IPSEC_MM_POLICY_EXISTS: DWORD = 13003; +pub const ERROR_IPSEC_MM_POLICY_NOT_FOUND: DWORD = 13004; +pub const ERROR_IPSEC_MM_POLICY_IN_USE: DWORD = 13005; +pub const ERROR_IPSEC_MM_FILTER_EXISTS: DWORD = 13006; +pub const ERROR_IPSEC_MM_FILTER_NOT_FOUND: DWORD = 13007; +pub const ERROR_IPSEC_TRANSPORT_FILTER_EXISTS: DWORD = 13008; +pub const ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND: DWORD = 13009; +pub const ERROR_IPSEC_MM_AUTH_EXISTS: DWORD = 13010; +pub const ERROR_IPSEC_MM_AUTH_NOT_FOUND: DWORD = 13011; +pub const ERROR_IPSEC_MM_AUTH_IN_USE: DWORD = 13012; +pub const ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND: DWORD = 13013; +pub const ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND: DWORD = 13014; +pub const ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND: DWORD = 13015; +pub const ERROR_IPSEC_TUNNEL_FILTER_EXISTS: DWORD = 13016; +pub const ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND: DWORD = 13017; +pub const ERROR_IPSEC_MM_FILTER_PENDING_DELETION: DWORD = 13018; +pub const ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION: DWORD = 13019; +pub const ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION: DWORD = 13020; +pub const ERROR_IPSEC_MM_POLICY_PENDING_DELETION: DWORD = 13021; +pub const ERROR_IPSEC_MM_AUTH_PENDING_DELETION: DWORD = 13022; +pub const ERROR_IPSEC_QM_POLICY_PENDING_DELETION: DWORD = 13023; +pub const ERROR_IPSEC_IKE_NEG_STATUS_BEGIN: DWORD = 13800; +pub const ERROR_IPSEC_IKE_AUTH_FAIL: DWORD = 13801; +pub const ERROR_IPSEC_IKE_ATTRIB_FAIL: DWORD = 13802; +pub const ERROR_IPSEC_IKE_NEGOTIATION_PENDING: DWORD = 13803; +pub const ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR: DWORD = 13804; +pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; +pub const ERROR_IPSEC_IKE_NO_CERT: DWORD = 13806; +pub const ERROR_IPSEC_IKE_SA_DELETED: DWORD = 13807; +pub const ERROR_IPSEC_IKE_SA_REAPED: DWORD = 13808; +pub const ERROR_IPSEC_IKE_MM_ACQUIRE_DROP: DWORD = 13809; +pub const ERROR_IPSEC_IKE_QM_ACQUIRE_DROP: DWORD = 13810; +pub const ERROR_IPSEC_IKE_QUEUE_DROP_MM: DWORD = 13811; +pub const ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM: DWORD = 13812; +pub const ERROR_IPSEC_IKE_DROP_NO_RESPONSE: DWORD = 13813; +pub const ERROR_IPSEC_IKE_MM_DELAY_DROP: DWORD = 13814; +pub const ERROR_IPSEC_IKE_QM_DELAY_DROP: DWORD = 13815; +pub const ERROR_IPSEC_IKE_ERROR: DWORD = 13816; +pub const ERROR_IPSEC_IKE_CRL_FAILED: DWORD = 13817; +pub const ERROR_IPSEC_IKE_INVALID_KEY_USAGE: DWORD = 13818; +pub const ERROR_IPSEC_IKE_INVALID_CERT_TYPE: DWORD = 13819; +pub const ERROR_IPSEC_IKE_NO_PRIVATE_KEY: DWORD = 13820; +pub const ERROR_IPSEC_IKE_DH_FAIL: DWORD = 13822; +pub const ERROR_IPSEC_IKE_INVALID_HEADER: DWORD = 13824; +pub const ERROR_IPSEC_IKE_NO_POLICY: DWORD = 13825; +pub const ERROR_IPSEC_IKE_INVALID_SIGNATURE: DWORD = 13826; +pub const ERROR_IPSEC_IKE_KERBEROS_ERROR: DWORD = 13827; +pub const ERROR_IPSEC_IKE_NO_PUBLIC_KEY: DWORD = 13828; +pub const ERROR_IPSEC_IKE_PROCESS_ERR: DWORD = 13829; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_SA: DWORD = 13830; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_PROP: DWORD = 13831; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_TRANS: DWORD = 13832; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_KE: DWORD = 13833; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_ID: DWORD = 13834; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT: DWORD = 13835; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ: DWORD = 13836; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_HASH: DWORD = 13837; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_SIG: DWORD = 13838; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NONCE: DWORD = 13839; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY: DWORD = 13840; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_DELETE: DWORD = 13841; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR: DWORD = 13842; +pub const ERROR_IPSEC_IKE_INVALID_PAYLOAD: DWORD = 13843; +pub const ERROR_IPSEC_IKE_LOAD_SOFT_SA: DWORD = 13844; +pub const ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN: DWORD = 13845; +pub const ERROR_IPSEC_IKE_INVALID_COOKIE: DWORD = 13846; +pub const ERROR_IPSEC_IKE_NO_PEER_CERT: DWORD = 13847; +pub const ERROR_IPSEC_IKE_PEER_CRL_FAILED: DWORD = 13848; +pub const ERROR_IPSEC_IKE_POLICY_CHANGE: DWORD = 13849; +pub const ERROR_IPSEC_IKE_NO_MM_POLICY: DWORD = 13850; +pub const ERROR_IPSEC_IKE_NOTCBPRIV: DWORD = 13851; +pub const ERROR_IPSEC_IKE_SECLOADFAIL: DWORD = 13852; +pub const ERROR_IPSEC_IKE_FAILSSPINIT: DWORD = 13853; +pub const ERROR_IPSEC_IKE_FAILQUERYSSP: DWORD = 13854; +pub const ERROR_IPSEC_IKE_SRVACQFAIL: DWORD = 13855; +pub const ERROR_IPSEC_IKE_SRVQUERYCRED: DWORD = 13856; +pub const ERROR_IPSEC_IKE_GETSPIFAIL: DWORD = 13857; +pub const ERROR_IPSEC_IKE_INVALID_FILTER: DWORD = 13858; +pub const ERROR_IPSEC_IKE_OUT_OF_MEMORY: DWORD = 13859; +pub const ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED: DWORD = 13860; +pub const ERROR_IPSEC_IKE_INVALID_POLICY: DWORD = 13861; +pub const ERROR_IPSEC_IKE_UNKNOWN_DOI: DWORD = 13862; +pub const ERROR_IPSEC_IKE_INVALID_SITUATION: DWORD = 13863; +pub const ERROR_IPSEC_IKE_DH_FAILURE: DWORD = 13864; +pub const ERROR_IPSEC_IKE_INVALID_GROUP: DWORD = 13865; +pub const ERROR_IPSEC_IKE_ENCRYPT: DWORD = 13866; +pub const ERROR_IPSEC_IKE_DECRYPT: DWORD = 13867; +pub const ERROR_IPSEC_IKE_POLICY_MATCH: DWORD = 13868; +pub const ERROR_IPSEC_IKE_UNSUPPORTED_ID: DWORD = 13869; +pub const ERROR_IPSEC_IKE_INVALID_HASH: DWORD = 13870; +pub const ERROR_IPSEC_IKE_INVALID_HASH_ALG: DWORD = 13871; +pub const ERROR_IPSEC_IKE_INVALID_HASH_SIZE: DWORD = 13872; +pub const ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG: DWORD = 13873; +pub const ERROR_IPSEC_IKE_INVALID_AUTH_ALG: DWORD = 13874; +pub const ERROR_IPSEC_IKE_INVALID_SIG: DWORD = 13875; +pub const ERROR_IPSEC_IKE_LOAD_FAILED: DWORD = 13876; +pub const ERROR_IPSEC_IKE_RPC_DELETE: DWORD = 13877; +pub const ERROR_IPSEC_IKE_BENIGN_REINIT: DWORD = 13878; +pub const ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY: DWORD = 13879; +pub const ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN: DWORD = 13881; +pub const ERROR_IPSEC_IKE_MM_LIMIT: DWORD = 13882; +pub const ERROR_IPSEC_IKE_NEGOTIATION_DISABLED: DWORD = 13883; +/*pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13884)*/ +pub const ERROR_IPSEC_IKE_QM_LIMIT: DWORD = 13884; +pub const ERROR_IPSEC_IKE_MM_EXPIRED: DWORD = 13885; +pub const ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID: DWORD = 13886; +pub const ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH: DWORD = 13887; +pub const ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID: DWORD = 13888; +pub const ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD: DWORD = 13889; +pub const ERROR_IPSEC_IKE_DOS_COOKIE_SENT: DWORD = 13890; +pub const ERROR_IPSEC_IKE_SHUTTING_DOWN: DWORD = 13891; +pub const ERROR_IPSEC_IKE_CGA_AUTH_FAILED: DWORD = 13892; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NATOA: DWORD = 13893; +pub const ERROR_IPSEC_IKE_INVALID_MM_FOR_QM: DWORD = 13894; +pub const ERROR_IPSEC_IKE_QM_EXPIRED: DWORD = 13895; +pub const ERROR_IPSEC_IKE_TOO_MANY_FILTERS: DWORD = 13896; +pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13897; +pub const ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL: DWORD = 13898; +pub const ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE: DWORD = 13899; +pub const ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING: DWORD = 13900; +pub const ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING: DWORD = 13901; +pub const ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS: DWORD = 13902; +pub const ERROR_IPSEC_IKE_RATELIMIT_DROP: DWORD = 13903; +pub const ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE: DWORD = 13904; +pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE: DWORD = 13905; +pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE: DWORD = 13906; +pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY: DWORD = 13907; +pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE: DWORD = 13908; +pub const ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END: DWORD = 13909; +pub const ERROR_IPSEC_BAD_SPI: DWORD = 13910; +pub const ERROR_IPSEC_SA_LIFETIME_EXPIRED: DWORD = 13911; +pub const ERROR_IPSEC_WRONG_SA: DWORD = 13912; +pub const ERROR_IPSEC_REPLAY_CHECK_FAILED: DWORD = 13913; +pub const ERROR_IPSEC_INVALID_PACKET: DWORD = 13914; +pub const ERROR_IPSEC_INTEGRITY_CHECK_FAILED: DWORD = 13915; +pub const ERROR_IPSEC_CLEAR_TEXT_DROP: DWORD = 13916; +pub const ERROR_IPSEC_AUTH_FIREWALL_DROP: DWORD = 13917; +pub const ERROR_IPSEC_THROTTLE_DROP: DWORD = 13918; +pub const ERROR_IPSEC_DOSP_BLOCK: DWORD = 13925; +pub const ERROR_IPSEC_DOSP_RECEIVED_MULTICAST: DWORD = 13926; +pub const ERROR_IPSEC_DOSP_INVALID_PACKET: DWORD = 13927; +pub const ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED: DWORD = 13928; +pub const ERROR_IPSEC_DOSP_MAX_ENTRIES: DWORD = 13929; +pub const ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED: DWORD = 13930; +pub const ERROR_IPSEC_DOSP_NOT_INSTALLED: DWORD = 13931; +pub const ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES: DWORD = 13932; +pub const ERROR_EVT_INVALID_CHANNEL_PATH: DWORD = 15000; +pub const ERROR_EVT_INVALID_QUERY: DWORD = 15001; +pub const ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND: DWORD = 15002; +pub const ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND: DWORD = 15003; +pub const ERROR_EVT_INVALID_PUBLISHER_NAME: DWORD = 15004; +pub const ERROR_EVT_INVALID_EVENT_DATA: DWORD = 15005; +pub const ERROR_EVT_CHANNEL_NOT_FOUND: DWORD = 15007; +pub const ERROR_EVT_MALFORMED_XML_TEXT: DWORD = 15008; +pub const ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL: DWORD = 15009; +pub const ERROR_EVT_CONFIGURATION_ERROR: DWORD = 15010; +pub const ERROR_EVT_QUERY_RESULT_STALE: DWORD = 15011; +pub const ERROR_EVT_QUERY_RESULT_INVALID_POSITION: DWORD = 15012; +pub const ERROR_EVT_NON_VALIDATING_MSXML: DWORD = 15013; +pub const ERROR_EVT_FILTER_ALREADYSCOPED: DWORD = 15014; +pub const ERROR_EVT_FILTER_NOTELTSET: DWORD = 15015; +pub const ERROR_EVT_FILTER_INVARG: DWORD = 15016; +pub const ERROR_EVT_FILTER_INVTEST: DWORD = 15017; +pub const ERROR_EVT_FILTER_INVTYPE: DWORD = 15018; +pub const ERROR_EVT_FILTER_PARSEERR: DWORD = 15019; +pub const ERROR_EVT_FILTER_UNSUPPORTEDOP: DWORD = 15020; +pub const ERROR_EVT_FILTER_UNEXPECTEDTOKEN: DWORD = 15021; +pub const ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL: DWORD = 15022; +pub const ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE: DWORD = 15023; +pub const ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE: DWORD = 15024; +pub const ERROR_EVT_CHANNEL_CANNOT_ACTIVATE: DWORD = 15025; +pub const ERROR_EVT_FILTER_TOO_COMPLEX: DWORD = 15026; +pub const ERROR_EVT_MESSAGE_NOT_FOUND: DWORD = 15027; +pub const ERROR_EVT_MESSAGE_ID_NOT_FOUND: DWORD = 15028; +pub const ERROR_EVT_UNRESOLVED_VALUE_INSERT: DWORD = 15029; +pub const ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: DWORD = 15030; +pub const ERROR_EVT_MAX_INSERTS_REACHED: DWORD = 15031; +pub const ERROR_EVT_EVENT_DEFINITION_NOT_FOUND: DWORD = 15032; +pub const ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND: DWORD = 15033; +pub const ERROR_EVT_VERSION_TOO_OLD: DWORD = 15034; +pub const ERROR_EVT_VERSION_TOO_NEW: DWORD = 15035; +pub const ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY: DWORD = 15036; +pub const ERROR_EVT_PUBLISHER_DISABLED: DWORD = 15037; +pub const ERROR_EVT_FILTER_OUT_OF_RANGE: DWORD = 15038; +pub const ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE: DWORD = 15080; +pub const ERROR_EC_LOG_DISABLED: DWORD = 15081; +pub const ERROR_EC_CIRCULAR_FORWARDING: DWORD = 15082; +pub const ERROR_EC_CREDSTORE_FULL: DWORD = 15083; +pub const ERROR_EC_CRED_NOT_FOUND: DWORD = 15084; +pub const ERROR_EC_NO_ACTIVE_CHANNEL: DWORD = 15085; +pub const ERROR_MUI_FILE_NOT_FOUND: DWORD = 15100; +pub const ERROR_MUI_INVALID_FILE: DWORD = 15101; +pub const ERROR_MUI_INVALID_RC_CONFIG: DWORD = 15102; +pub const ERROR_MUI_INVALID_LOCALE_NAME: DWORD = 15103; +pub const ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME: DWORD = 15104; +pub const ERROR_MUI_FILE_NOT_LOADED: DWORD = 15105; +pub const ERROR_RESOURCE_ENUM_USER_STOP: DWORD = 15106; +pub const ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED: DWORD = 15107; +pub const ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME: DWORD = 15108; +pub const ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE: DWORD = 15110; +pub const ERROR_MRM_INVALID_PRICONFIG: DWORD = 15111; +pub const ERROR_MRM_INVALID_FILE_TYPE: DWORD = 15112; +pub const ERROR_MRM_UNKNOWN_QUALIFIER: DWORD = 15113; +pub const ERROR_MRM_INVALID_QUALIFIER_VALUE: DWORD = 15114; +pub const ERROR_MRM_NO_CANDIDATE: DWORD = 15115; +pub const ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE: DWORD = 15116; +pub const ERROR_MRM_RESOURCE_TYPE_MISMATCH: DWORD = 15117; +pub const ERROR_MRM_DUPLICATE_MAP_NAME: DWORD = 15118; +pub const ERROR_MRM_DUPLICATE_ENTRY: DWORD = 15119; +pub const ERROR_MRM_INVALID_RESOURCE_IDENTIFIER: DWORD = 15120; +pub const ERROR_MRM_FILEPATH_TOO_LONG: DWORD = 15121; +pub const ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE: DWORD = 15122; +pub const ERROR_MRM_INVALID_PRI_FILE: DWORD = 15126; +pub const ERROR_MRM_NAMED_RESOURCE_NOT_FOUND: DWORD = 15127; +pub const ERROR_MRM_MAP_NOT_FOUND: DWORD = 15135; +pub const ERROR_MRM_UNSUPPORTED_PROFILE_TYPE: DWORD = 15136; +pub const ERROR_MRM_INVALID_QUALIFIER_OPERATOR: DWORD = 15137; +pub const ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE: DWORD = 15138; +pub const ERROR_MRM_AUTOMERGE_ENABLED: DWORD = 15139; +pub const ERROR_MRM_TOO_MANY_RESOURCES: DWORD = 15140; +pub const ERROR_MCA_INVALID_CAPABILITIES_STRING: DWORD = 15200; +pub const ERROR_MCA_INVALID_VCP_VERSION: DWORD = 15201; +pub const ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION: DWORD = 15202; +pub const ERROR_MCA_MCCS_VERSION_MISMATCH: DWORD = 15203; +pub const ERROR_MCA_UNSUPPORTED_MCCS_VERSION: DWORD = 15204; +pub const ERROR_MCA_INTERNAL_ERROR: DWORD = 15205; +pub const ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED: DWORD = 15206; +pub const ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE: DWORD = 15207; +pub const ERROR_AMBIGUOUS_SYSTEM_DEVICE: DWORD = 15250; +pub const ERROR_SYSTEM_DEVICE_NOT_FOUND: DWORD = 15299; +pub const ERROR_HASH_NOT_SUPPORTED: DWORD = 15300; +pub const ERROR_HASH_NOT_PRESENT: DWORD = 15301; +pub const ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED: DWORD = 15321; +pub const ERROR_GPIO_CLIENT_INFORMATION_INVALID: DWORD = 15322; +pub const ERROR_GPIO_VERSION_NOT_SUPPORTED: DWORD = 15323; +pub const ERROR_GPIO_INVALID_REGISTRATION_PACKET: DWORD = 15324; +pub const ERROR_GPIO_OPERATION_DENIED: DWORD = 15325; +pub const ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE: DWORD = 15326; +pub const ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED: DWORD = 15327; +pub const ERROR_CANNOT_SWITCH_RUNLEVEL: DWORD = 15400; +pub const ERROR_INVALID_RUNLEVEL_SETTING: DWORD = 15401; +pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; +pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; +pub const ERROR_RUNLEVEL_SWITCH_IN_PROGRESS: DWORD = 15404; +pub const ERROR_SERVICES_FAILED_AUTOSTART: DWORD = 15405; +pub const ERROR_COM_TASK_STOP_PENDING: DWORD = 15501; +pub const ERROR_INSTALL_OPEN_PACKAGE_FAILED: DWORD = 15600; +pub const ERROR_INSTALL_PACKAGE_NOT_FOUND: DWORD = 15601; +pub const ERROR_INSTALL_INVALID_PACKAGE: DWORD = 15602; +pub const ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED: DWORD = 15603; +pub const ERROR_INSTALL_OUT_OF_DISK_SPACE: DWORD = 15604; +pub const ERROR_INSTALL_NETWORK_FAILURE: DWORD = 15605; +pub const ERROR_INSTALL_REGISTRATION_FAILURE: DWORD = 15606; +pub const ERROR_INSTALL_DEREGISTRATION_FAILURE: DWORD = 15607; +pub const ERROR_INSTALL_CANCEL: DWORD = 15608; +pub const ERROR_INSTALL_FAILED: DWORD = 15609; +pub const ERROR_REMOVE_FAILED: DWORD = 15610; +pub const ERROR_PACKAGE_ALREADY_EXISTS: DWORD = 15611; +pub const ERROR_NEEDS_REMEDIATION: DWORD = 15612; +pub const ERROR_INSTALL_PREREQUISITE_FAILED: DWORD = 15613; +pub const ERROR_PACKAGE_REPOSITORY_CORRUPTED: DWORD = 15614; +pub const ERROR_INSTALL_POLICY_FAILURE: DWORD = 15615; +pub const ERROR_PACKAGE_UPDATING: DWORD = 15616; +pub const ERROR_DEPLOYMENT_BLOCKED_BY_POLICY: DWORD = 15617; +pub const ERROR_PACKAGES_IN_USE: DWORD = 15618; +pub const ERROR_RECOVERY_FILE_CORRUPT: DWORD = 15619; +pub const ERROR_INVALID_STAGED_SIGNATURE: DWORD = 15620; +pub const ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED: DWORD = 15621; +pub const ERROR_INSTALL_PACKAGE_DOWNGRADE: DWORD = 15622; +pub const ERROR_SYSTEM_NEEDS_REMEDIATION: DWORD = 15623; +pub const ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN: DWORD = 15624; +pub const ERROR_RESILIENCY_FILE_CORRUPT: DWORD = 15625; +pub const ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING: DWORD = 15626; +pub const ERROR_STATE_LOAD_STORE_FAILED: DWORD = 15800; +pub const ERROR_STATE_GET_VERSION_FAILED: DWORD = 15801; +pub const ERROR_STATE_SET_VERSION_FAILED: DWORD = 15802; +pub const ERROR_STATE_STRUCTURED_RESET_FAILED: DWORD = 15803; +pub const ERROR_STATE_OPEN_CONTAINER_FAILED: DWORD = 15804; +pub const ERROR_STATE_CREATE_CONTAINER_FAILED: DWORD = 15805; +pub const ERROR_STATE_DELETE_CONTAINER_FAILED: DWORD = 15806; +pub const ERROR_STATE_READ_SETTING_FAILED: DWORD = 15807; +pub const ERROR_STATE_WRITE_SETTING_FAILED: DWORD = 15808; +pub const ERROR_STATE_DELETE_SETTING_FAILED: DWORD = 15809; +pub const ERROR_STATE_QUERY_SETTING_FAILED: DWORD = 15810; +pub const ERROR_STATE_READ_COMPOSITE_SETTING_FAILED: DWORD = 15811; +pub const ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED: DWORD = 15812; +pub const ERROR_STATE_ENUMERATE_CONTAINER_FAILED: DWORD = 15813; +pub const ERROR_STATE_ENUMERATE_SETTINGS_FAILED: DWORD = 15814; +pub const ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15815; +pub const ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15816; +pub const ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15817; +pub const ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15818; +pub const ERROR_API_UNAVAILABLE: DWORD = 15841; +pub const ERROR_AUDITING_DISABLED: DWORD = 0xC0090001; +pub const ERROR_ALL_SIDS_FILTERED: DWORD = 0xC0090002; + +pub const WSABASEERR: c_int = 10000; +pub const WSAEINTR: c_int = WSABASEERR + 4; +pub const WSAEBADF: c_int = WSABASEERR + 9; +pub const WSAEACCES: c_int = WSABASEERR + 13; +pub const WSAEFAULT: c_int = WSABASEERR + 14; +pub const WSAEINVAL: c_int = WSABASEERR + 22; +pub const WSAEMFILE: c_int = WSABASEERR + 24; +pub const WSAEWOULDBLOCK: c_int = WSABASEERR + 35; +pub const WSAEINPROGRESS: c_int = WSABASEERR + 36; +pub const WSAEALREADY: c_int = WSABASEERR + 37; +pub const WSAENOTSOCK: c_int = WSABASEERR + 38; +pub const WSAEDESTADDRREQ: c_int = WSABASEERR + 39; +pub const WSAEMSGSIZE: c_int = WSABASEERR + 40; +pub const WSAEPROTOTYPE: c_int = WSABASEERR + 41; +pub const WSAENOPROTOOPT: c_int = WSABASEERR + 42; +pub const WSAEPROTONOSUPPORT: c_int = WSABASEERR + 43; +pub const WSAESOCKTNOSUPPORT: c_int = WSABASEERR + 44; +pub const WSAEOPNOTSUPP: c_int = WSABASEERR + 45; +pub const WSAEPFNOSUPPORT: c_int = WSABASEERR + 46; +pub const WSAEAFNOSUPPORT: c_int = WSABASEERR + 47; +pub const WSAEADDRINUSE: c_int = WSABASEERR + 48; +pub const WSAEADDRNOTAVAIL: c_int = WSABASEERR + 49; +pub const WSAENETDOWN: c_int = WSABASEERR + 50; +pub const WSAENETUNREACH: c_int = WSABASEERR + 51; +pub const WSAENETRESET: c_int = WSABASEERR + 52; +pub const WSAECONNABORTED: c_int = WSABASEERR + 53; +pub const WSAECONNRESET: c_int = WSABASEERR + 54; +pub const WSAENOBUFS: c_int = WSABASEERR + 55; +pub const WSAEISCONN: c_int = WSABASEERR + 56; +pub const WSAENOTCONN: c_int = WSABASEERR + 57; +pub const WSAESHUTDOWN: c_int = WSABASEERR + 58; +pub const WSAETOOMANYREFS: c_int = WSABASEERR + 59; +pub const WSAETIMEDOUT: c_int = WSABASEERR + 60; +pub const WSAECONNREFUSED: c_int = WSABASEERR + 61; +pub const WSAELOOP: c_int = WSABASEERR + 62; +pub const WSAENAMETOOLONG: c_int = WSABASEERR + 63; +pub const WSAEHOSTDOWN: c_int = WSABASEERR + 64; +pub const WSAEHOSTUNREACH: c_int = WSABASEERR + 65; +pub const WSAENOTEMPTY: c_int = WSABASEERR + 66; +pub const WSAEPROCLIM: c_int = WSABASEERR + 67; +pub const WSAEUSERS: c_int = WSABASEERR + 68; +pub const WSAEDQUOT: c_int = WSABASEERR + 69; +pub const WSAESTALE: c_int = WSABASEERR + 70; +pub const WSAEREMOTE: c_int = WSABASEERR + 71; +pub const WSASYSNOTREADY: c_int = WSABASEERR + 91; +pub const WSAVERNOTSUPPORTED: c_int = WSABASEERR + 92; +pub const WSANOTINITIALISED: c_int = WSABASEERR + 93; +pub const WSAEDISCON: c_int = WSABASEERR + 101; +pub const WSAENOMORE: c_int = WSABASEERR + 102; +pub const WSAECANCELLED: c_int = WSABASEERR + 103; +pub const WSAEINVALIDPROCTABLE: c_int = WSABASEERR + 104; +pub const WSAEINVALIDPROVIDER: c_int = WSABASEERR + 105; +pub const WSAEPROVIDERFAILEDINIT: c_int = WSABASEERR + 106; +pub const WSASYSCALLFAILURE: c_int = WSABASEERR + 107; +pub const WSASERVICE_NOT_FOUND: c_int = WSABASEERR + 108; +pub const WSATYPE_NOT_FOUND: c_int = WSABASEERR + 109; +pub const WSA_E_NO_MORE: c_int = WSABASEERR + 110; +pub const WSA_E_CANCELLED: c_int = WSABASEERR + 111; +pub const WSAEREFUSED: c_int = WSABASEERR + 112; +pub const WSAHOST_NOT_FOUND: c_int = WSABASEERR + 1001; +pub const WSATRY_AGAIN: c_int = WSABASEERR + 1002; +pub const WSANO_RECOVERY: c_int = WSABASEERR + 1003; +pub const WSANO_DATA: c_int = WSABASEERR + 1004; +pub const WSA_QOS_RECEIVERS: c_int = WSABASEERR + 1005; +pub const WSA_QOS_SENDERS: c_int = WSABASEERR + 1006; +pub const WSA_QOS_NO_SENDERS: c_int = WSABASEERR + 1007; +pub const WSA_QOS_NO_RECEIVERS: c_int = WSABASEERR + 1008; +pub const WSA_QOS_REQUEST_CONFIRMED: c_int = WSABASEERR + 1009; +pub const WSA_QOS_ADMISSION_FAILURE: c_int = WSABASEERR + 1010; +pub const WSA_QOS_POLICY_FAILURE: c_int = WSABASEERR + 1011; +pub const WSA_QOS_BAD_STYLE: c_int = WSABASEERR + 1012; +pub const WSA_QOS_BAD_OBJECT: c_int = WSABASEERR + 1013; +pub const WSA_QOS_TRAFFIC_CTRL_ERROR: c_int = WSABASEERR + 1014; +pub const WSA_QOS_GENERIC_ERROR: c_int = WSABASEERR + 1015; +pub const WSA_QOS_ESERVICETYPE: c_int = WSABASEERR + 1016; +pub const WSA_QOS_EFLOWSPEC: c_int = WSABASEERR + 1017; +pub const WSA_QOS_EPROVSPECBUF: c_int = WSABASEERR + 1018; +pub const WSA_QOS_EFILTERSTYLE: c_int = WSABASEERR + 1019; +pub const WSA_QOS_EFILTERTYPE: c_int = WSABASEERR + 1020; +pub const WSA_QOS_EFILTERCOUNT: c_int = WSABASEERR + 1021; +pub const WSA_QOS_EOBJLENGTH: c_int = WSABASEERR + 1022; +pub const WSA_QOS_EFLOWCOUNT: c_int = WSABASEERR + 1023; +pub const WSA_QOS_EUNKNOWNPSOBJ: c_int = WSABASEERR + 1024; +pub const WSA_QOS_EUNKOWNPSOBJ: c_int = WSA_QOS_EUNKNOWNPSOBJ; +pub const WSA_QOS_EPOLICYOBJ: c_int = WSABASEERR + 1025; +pub const WSA_QOS_EFLOWDESC: c_int = WSABASEERR + 1026; +pub const WSA_QOS_EPSFLOWSPEC: c_int = WSABASEERR + 1027; +pub const WSA_QOS_EPSFILTERSPEC: c_int = WSABASEERR + 1028; +pub const WSA_QOS_ESDMODEOBJ: c_int = WSABASEERR + 1029; +pub const WSA_QOS_ESHAPERATEOBJ: c_int = WSABASEERR + 1030; +pub const WSA_QOS_RESERVED_PETYPE: c_int = WSABASEERR + 1031; diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 2b6143de960..c677adae688 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -514,7 +514,7 @@ impl File { } _ => { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"Unsupported reparse point type", )); } @@ -961,9 +961,8 @@ pub fn try_exists(path: &Path) -> io::Result<bool> { // `ERROR_SHARING_VIOLATION` means that the file has been locked by // another process. This is often temporary so we simply report it // as the file existing. - io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => { - Ok(true) - } + _ if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => Ok(true), + // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the // file exists. However, these types of errors are usually more // permanent so we report them here. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index f23e874f249..28fec817f86 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -61,16 +61,18 @@ pub unsafe fn cleanup() { } pub fn decode_error_kind(errno: i32) -> ErrorKind { + use ErrorKind::*; + match errno as c::DWORD { - c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied, - c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists, - c::ERROR_FILE_EXISTS => return ErrorKind::AlreadyExists, - c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe, - c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, - c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, - c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, - c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput, - c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return ErrorKind::OutOfMemory, + c::ERROR_ACCESS_DENIED => return PermissionDenied, + c::ERROR_ALREADY_EXISTS => return AlreadyExists, + c::ERROR_FILE_EXISTS => return AlreadyExists, + c::ERROR_BROKEN_PIPE => return BrokenPipe, + c::ERROR_FILE_NOT_FOUND => return NotFound, + c::ERROR_PATH_NOT_FOUND => return NotFound, + c::ERROR_NO_DATA => return BrokenPipe, + c::ERROR_INVALID_PARAMETER => return InvalidInput, + c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT @@ -86,24 +88,42 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { | c::DNS_ERROR_RECORD_TIMED_OUT | c::ERROR_IPSEC_IKE_TIMED_OUT | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT - | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_CALL_NOT_IMPLEMENTED => return ErrorKind::Unsupported, + | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut, + c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported, + c::ERROR_HOST_UNREACHABLE => return HostUnreachable, + c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable, + c::ERROR_DIRECTORY => return NotADirectory, + c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory, + c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty, + c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, + c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, + c::ERROR_SEEK_ON_DEVICE => return NotSeekable, + c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded, + c::ERROR_FILE_TOO_LARGE => return FileTooLarge, + c::ERROR_BUSY => return ResourceBusy, + c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, + c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, + c::ERROR_TOO_MANY_LINKS => return TooManyLinks, + c::ERROR_FILENAME_EXCED_RANGE => return FilenameTooLong, _ => {} } match errno { - c::WSAEACCES => ErrorKind::PermissionDenied, - c::WSAEADDRINUSE => ErrorKind::AddrInUse, - c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - c::WSAECONNABORTED => ErrorKind::ConnectionAborted, - c::WSAECONNREFUSED => ErrorKind::ConnectionRefused, - c::WSAECONNRESET => ErrorKind::ConnectionReset, - c::WSAEINVAL => ErrorKind::InvalidInput, - c::WSAENOTCONN => ErrorKind::NotConnected, - c::WSAEWOULDBLOCK => ErrorKind::WouldBlock, - c::WSAETIMEDOUT => ErrorKind::TimedOut, + c::WSAEACCES => PermissionDenied, + c::WSAEADDRINUSE => AddrInUse, + c::WSAEADDRNOTAVAIL => AddrNotAvailable, + c::WSAECONNABORTED => ConnectionAborted, + c::WSAECONNREFUSED => ConnectionRefused, + c::WSAECONNRESET => ConnectionReset, + c::WSAEINVAL => InvalidInput, + c::WSAENOTCONN => NotConnected, + c::WSAEWOULDBLOCK => WouldBlock, + c::WSAETIMEDOUT => TimedOut, + c::WSAEHOSTUNREACH => HostUnreachable, + c::WSAENETDOWN => NetworkDown, + c::WSAENETUNREACH => NetworkUnreachable, - _ => ErrorKind::Other, + _ => Uncategorized, } } diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index b3caf232064..b082e21ab3b 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -4,6 +4,7 @@ mod tests; use crate::borrow::Borrow; +use crate::cmp; use crate::collections::BTreeMap; use crate::convert::{TryFrom, TryInto}; use crate::env; @@ -34,32 +35,95 @@ use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS}; // Command //////////////////////////////////////////////////////////////////////////////// -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Clone, Debug, Eq)] #[doc(hidden)] -pub struct EnvKey(OsString); +pub struct EnvKey { + os_string: OsString, + // This stores a UTF-16 encoded string to workaround the mismatch between + // Rust's OsString (WTF-8) and the Windows API string type (UTF-16). + // Normally converting on every API call is acceptable but here + // `c::CompareStringOrdinal` will be called for every use of `==`. + utf16: Vec<u16>, +} + +// Comparing Windows environment variable keys[1] are behaviourally the +// composition of two operations[2]: +// +// 1. Case-fold both strings. This is done using a language-independent +// uppercase mapping that's unique to Windows (albeit based on data from an +// older Unicode spec). It only operates on individual UTF-16 code units so +// surrogates are left unchanged. This uppercase mapping can potentially change +// between Windows versions. +// +// 2. Perform an ordinal comparison of the strings. A comparison using ordinal +// is just a comparison based on the numerical value of each UTF-16 code unit[3]. +// +// Because the case-folding mapping is unique to Windows and not guaranteed to +// be stable, we ask the OS to compare the strings for us. This is done by +// calling `CompareStringOrdinal`[4] with `bIgnoreCase` set to `TRUE`. +// +// [1] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#choosing-a-stringcomparison-member-for-your-method-call +// [2] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#stringtoupper-and-stringtolower +// [3] https://docs.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=net-5.0#System_StringComparison_Ordinal +// [4] https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal +impl Ord for EnvKey { + fn cmp(&self, other: &Self) -> cmp::Ordering { + unsafe { + let result = c::CompareStringOrdinal( + self.utf16.as_ptr(), + self.utf16.len() as _, + other.utf16.as_ptr(), + other.utf16.len() as _, + c::TRUE, + ); + match result { + c::CSTR_LESS_THAN => cmp::Ordering::Less, + c::CSTR_EQUAL => cmp::Ordering::Equal, + c::CSTR_GREATER_THAN => cmp::Ordering::Greater, + // `CompareStringOrdinal` should never fail so long as the parameters are correct. + _ => panic!("comparing environment keys failed: {}", Error::last_os_error()), + } + } + } +} +impl PartialOrd for EnvKey { + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { + Some(self.cmp(other)) + } +} +impl PartialEq for EnvKey { + fn eq(&self, other: &Self) -> bool { + if self.utf16.len() != other.utf16.len() { + false + } else { + self.cmp(other) == cmp::Ordering::Equal + } + } +} +// Environment variable keys should preserve their original case even though +// they are compared using a caseless string mapping. impl From<OsString> for EnvKey { - fn from(mut k: OsString) -> Self { - k.make_ascii_uppercase(); - EnvKey(k) + fn from(k: OsString) -> Self { + EnvKey { utf16: k.encode_wide().collect(), os_string: k } } } impl From<EnvKey> for OsString { fn from(k: EnvKey) -> Self { - k.0 + k.os_string } } impl Borrow<OsStr> for EnvKey { fn borrow(&self) -> &OsStr { - &self.0 + &self.os_string } } impl AsRef<OsStr> for EnvKey { fn as_ref(&self) -> &OsStr { - &self.0 + &self.os_string } } @@ -537,7 +601,8 @@ fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>) -> io::Result<(*mut } for (k, v) in env { - blk.extend(ensure_no_nuls(k.0)?.encode_wide()); + ensure_no_nuls(k.os_string)?; + blk.extend(k.utf16); blk.push('=' as u16); blk.extend(ensure_no_nuls(v)?.encode_wide()); blk.push(0); diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 8830ae049c6..ff3f9131cc8 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -1,5 +1,7 @@ use super::make_command_line; +use crate::env; use crate::ffi::{OsStr, OsString}; +use crate::process::Command; #[test] fn test_make_command_line() { @@ -41,3 +43,62 @@ fn test_make_command_line() { "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\"" ); } + +// On Windows, environment args are case preserving but comparisons are case-insensitive. +// See: #85242 +#[test] +fn windows_env_unicode_case() { + let test_cases = [ + ("ä", "Ä"), + ("ß", "SS"), + ("Ä", "Ö"), + ("Ä", "Ö"), + ("I", "İ"), + ("I", "i"), + ("I", "ı"), + ("i", "I"), + ("i", "İ"), + ("i", "ı"), + ("İ", "I"), + ("İ", "i"), + ("İ", "ı"), + ("ı", "I"), + ("ı", "i"), + ("ı", "İ"), + ("ä", "Ä"), + ("ß", "SS"), + ("Ä", "Ö"), + ("Ä", "Ö"), + ("I", "İ"), + ("I", "i"), + ("I", "ı"), + ("i", "I"), + ("i", "İ"), + ("i", "ı"), + ("İ", "I"), + ("İ", "i"), + ("İ", "ı"), + ("ı", "I"), + ("ı", "i"), + ("ı", "İ"), + ]; + // Test that `cmd.env` matches `env::set_var` when setting two strings that + // may (or may not) be case-folded when compared. + for (a, b) in test_cases.iter() { + let mut cmd = Command::new("cmd"); + cmd.env(a, "1"); + cmd.env(b, "2"); + env::set_var(a, "1"); + env::set_var(b, "2"); + + for (key, value) in cmd.get_envs() { + assert_eq!( + env::var(key).ok(), + value.map(|s| s.to_string_lossy().into_owned()), + "command environment mismatch: {} {}", + a, + b + ); + } + } +} diff --git a/library/std/src/sys_common/bytestring.rs b/library/std/src/sys_common/bytestring.rs deleted file mode 100644 index 97fba60c271..00000000000 --- a/library/std/src/sys_common/bytestring.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![allow(dead_code)] - -#[cfg(test)] -mod tests; - -use crate::fmt::{Formatter, Result, Write}; -use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; - -pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result { - // Writes out a valid unicode string with the correct escape sequences - fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result { - for c in s.chars().flat_map(|c| c.escape_debug()) { - f.write_char(c)? - } - Ok(()) - } - - f.write_str("\"")?; - for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(slice).chunks() { - write_str_escaped(f, valid)?; - for b in broken { - write!(f, "\\x{:02X}", b)?; - } - } - f.write_str("\"") -} diff --git a/library/std/src/sys_common/bytestring/tests.rs b/library/std/src/sys_common/bytestring/tests.rs deleted file mode 100644 index 1685f087d18..00000000000 --- a/library/std/src/sys_common/bytestring/tests.rs +++ /dev/null @@ -1,19 +0,0 @@ -use super::*; -use crate::fmt::{Debug, Formatter, Result}; - -#[test] -fn smoke() { - struct Helper<'a>(&'a [u8]); - - impl Debug for Helper<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - debug_fmt_bytestring(self.0, f) - } - } - - let input = b"\xF0hello,\tworld"; - let expected = r#""\xF0hello,\tworld""#; - let output = format!("{:?}", Helper(input)); - - assert!(output == expected); -} diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 1a9caa22c92..db83bad60d8 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -21,7 +21,6 @@ mod tests; pub mod backtrace; -pub mod bytestring; pub mod condvar; pub mod fs; pub mod io; diff --git a/library/std/src/sys_common/os_str_bytes.rs b/library/std/src/sys_common/os_str_bytes.rs index 470f401a6d2..569600470db 100644 --- a/library/std/src/sys_common/os_str_bytes.rs +++ b/library/std/src/sys_common/os_str_bytes.rs @@ -2,16 +2,18 @@ //! systems: just a `Vec<u8>`/`[u8]`. use crate::borrow::Cow; - use crate::fmt; +use crate::fmt::Write; use crate::mem; use crate::rc::Rc; use crate::str; use crate::sync::Arc; -use crate::sys_common::bytestring::debug_fmt_bytestring; use crate::sys_common::{AsInner, IntoInner}; -use core::str::lossy::Utf8Lossy; +use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; + +#[cfg(test)] +mod tests; #[derive(Hash)] #[repr(transparent)] @@ -26,7 +28,19 @@ pub struct Slice { impl fmt::Debug for Slice { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_fmt_bytestring(&self.inner, formatter) + // Writes out a valid unicode string with the correct escape sequences + + formatter.write_str("\"")?; + for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(&self.inner).chunks() { + for c in valid.chars().flat_map(|c| c.escape_debug()) { + formatter.write_char(c)? + } + + for b in broken { + write!(formatter, "\\x{:02X}", b)?; + } + } + formatter.write_str("\"") } } diff --git a/library/std/src/sys_common/os_str_bytes/tests.rs b/library/std/src/sys_common/os_str_bytes/tests.rs new file mode 100644 index 00000000000..37967378155 --- /dev/null +++ b/library/std/src/sys_common/os_str_bytes/tests.rs @@ -0,0 +1,10 @@ +use super::*; + +#[test] +fn slice_debug_output() { + let input = Slice::from_u8_slice(b"\xF0hello,\tworld"); + let expected = r#""\xF0hello,\tworld""#; + let output = format!("{:?}", input); + + assert_eq!(output, expected); +} diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 5a4a540b04e..794f7277004 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -61,9 +61,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -75,9 +73,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -97,9 +93,7 @@ pub fn do_not_run_ignored_tests() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -120,9 +114,7 @@ pub fn ignored_tests_result_in_ignored() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -147,9 +139,7 @@ fn test_should_panic() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -174,9 +164,7 @@ fn test_should_panic_good_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -206,9 +194,7 @@ fn test_should_panic_bad_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -242,9 +228,7 @@ fn test_should_panic_non_string_message_type() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -270,9 +254,7 @@ fn test_should_panic_but_succeeds() { ignore: false, should_panic, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -306,9 +288,7 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -343,9 +323,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type, }, @@ -384,9 +362,7 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type, } @@ -499,9 +475,7 @@ pub fn exclude_should_panic_option() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -525,9 +499,7 @@ pub fn exact_filter_match() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -621,9 +593,7 @@ pub fn sort_tests() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -702,9 +672,7 @@ pub fn test_bench_no_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -726,9 +694,7 @@ pub fn test_bench_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -744,9 +710,7 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -756,9 +720,7 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 63907c71ea7..3512a57e8e4 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -124,9 +124,7 @@ pub struct TestDesc { pub ignore: bool, pub should_panic: options::ShouldPanic, pub allow_fail: bool, - #[cfg(not(bootstrap))] pub compile_fail: bool, - #[cfg(not(bootstrap))] pub no_run: bool, pub test_type: TestType, } @@ -147,7 +145,6 @@ impl TestDesc { /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test. /// Descriptions include "should panic", "compile fail" and "compile". - #[cfg(not(bootstrap))] pub fn test_mode(&self) -> Option<&'static str> { if self.ignore { return None; @@ -169,11 +166,6 @@ impl TestDesc { } None } - - #[cfg(bootstrap)] - pub fn test_mode(&self) -> Option<&'static str> { - None - } } #[derive(Debug)] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 7fd6b7d1609..f9904cb610d 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -138,7 +138,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): shutil.rmtree(os.path.join(dst, fname)) -def run(args, verbose=False, exception=False, **kwargs): +def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: print("running: " + ' '.join(args)) @@ -151,7 +151,14 @@ def run(args, verbose=False, exception=False, **kwargs): err = "failed to run: " + ' '.join(args) if verbose or exception: raise RuntimeError(err) - sys.exit(err) + # For most failures, we definitely do want to print this error, or the user will have no + # idea what went wrong. But when we've successfully built bootstrap and it failed, it will + # have already printed an error above, so there's no need to print the exact command we're + # running. + if is_bootstrap: + sys.exit(1) + else: + sys.exit(err) def require(cmd, exit=True): @@ -1170,7 +1177,7 @@ def bootstrap(help_triggered): env["BOOTSTRAP_CONFIG"] = toml_path if build.rustc_commit is not None: env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1' - run(args, env=env, verbose=build.verbose) + run(args, env=env, verbose=build.verbose, is_bootstrap=True) def main(): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e2f605257bd..56ecc6e68a9 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -450,6 +450,7 @@ impl<'a> Builder<'a> { test::RustdocTheme, test::RustdocUi, test::RustdocJson, + test::HtmlCheck, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, // Run run-make last, since these won't pass without make on Windows @@ -464,6 +465,7 @@ impl<'a> Builder<'a> { doc::Std, doc::Rustc, doc::Rustdoc, + doc::Rustfmt, doc::ErrorIndex, doc::Nomicon, doc::Reference, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 112a6ea9398..1fae4bee732 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1366,7 +1366,7 @@ pub fn stream_cargo( // Make sure Cargo actually succeeded after we read all of its stdout. let status = t!(child.wait()); - if !status.success() { + if builder.is_verbose() && !status.success() { eprintln!( "command did not execute successfully: {:?}\n\ expected success, got: {}", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 19895baf08f..92853378e58 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -400,12 +400,12 @@ impl Step for Rustc { // Copy over lld if it's there if builder.config.lld_enabled { - let exe = exe("rust-lld", compiler.host); - builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe)); + let rust_lld = exe("rust-lld", compiler.host); + builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); // for `-Z gcc-ld=lld` let gcc_lld_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&gcc_lld_dir)); - builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe)); + builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host))); } // Copy over llvm-dwp if it's there diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index d2fabf9967f..8603361362c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -501,8 +501,8 @@ impl Step for Std { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { - stage: u32, - target: TargetSelection, + pub stage: u32, + pub target: TargetSelection, } impl Step for Rustc { @@ -593,84 +593,97 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Rustdoc { - stage: u32, - target: TargetSelection, -} - -impl Step for Rustdoc { - type Output = (); - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.krate("rustdoc-tool") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Rustdoc { stage: run.builder.top_stage, target: run.target }); - } - - /// Generates compiler documentation. - /// - /// This will generate all documentation for compiler and dependencies. - /// Compiler documentation is distributed separately, so we make sure - /// we do not merge it with the other documentation from std, test and - /// proc_macros. This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} rustdoc ({})", stage, target)); - - // This is the intended out directory for compiler documentation. - let out = builder.compiler_doc_out(target); - t!(fs::create_dir_all(&out)); +macro_rules! tool_doc { + ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(, binary=$bin:expr)?) => { + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct $tool { + stage: u32, + target: TargetSelection, + } - let compiler = builder.compiler(stage, builder.config.build); + impl Step for $tool { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; - if !builder.config.compiler_docs { - builder.info("\tskipping - compiler/librustdoc docs disabled"); - return; - } + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.krate($should_run) + } - // Build rustc docs so that we generate relative links. - builder.ensure(Rustc { stage, target }); + fn make_run(run: RunConfig<'_>) { + run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target }); + } - // Build rustdoc. - builder.ensure(tool::Rustdoc { compiler }); + /// Generates compiler documentation. + /// + /// This will generate all documentation for compiler and dependencies. + /// Compiler documentation is distributed separately, so we make sure + /// we do not merge it with the other documentation from std, test and + /// proc_macros. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let target = self.target; + builder.info(&format!("Documenting stage{} {} ({})", stage, stringify!($tool).to_lowercase(), target)); - // Symlink compiler docs to the output directory of rustdoc documentation. - let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); - t!(fs::create_dir_all(&out_dir)); - t!(symlink_dir_force(&builder.config, &out, &out_dir)); + // This is the intended out directory for compiler documentation. + let out = builder.compiler_doc_out(target); + t!(fs::create_dir_all(&out)); - // Build cargo command. - let mut cargo = prepare_tool_cargo( - builder, - compiler, - Mode::ToolRustc, - target, - "doc", - "src/tools/rustdoc", - SourceType::InTree, - &[], - ); + let compiler = builder.compiler(stage, builder.config.build); - cargo.arg("-Zskip-rustdoc-fingerprint"); - // Only include compiler crates, no dependencies of those, such as `libc`. - cargo.arg("--no-deps"); - cargo.arg("-p").arg("rustdoc"); - cargo.arg("-p").arg("rustdoc-json-types"); + if !builder.config.compiler_docs { + builder.info("\tskipping - compiler/tool docs disabled"); + return; + } - cargo.rustdocflag("--document-private-items"); - cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("-Zunstable-options"); - builder.run(&mut cargo.into()); + // Build rustc docs so that we generate relative links. + builder.ensure(Rustc { stage, target }); + + // Symlink compiler docs to the output directory of rustdoc documentation. + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); + t!(fs::create_dir_all(&out_dir)); + t!(symlink_dir_force(&builder.config, &out, &out_dir)); + + // Build cargo command. + let mut cargo = prepare_tool_cargo( + builder, + compiler, + Mode::ToolRustc, + target, + "doc", + $path, + SourceType::InTree, + &[], + ); + + cargo.arg("-Zskip-rustdoc-fingerprint"); + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + $( + cargo.arg("-p").arg($krate); + )+ + + $(if !$bin { + cargo.rustdocflag("--document-private-items"); + })? + cargo.rustdocflag("--enable-index-page"); + cargo.rustdocflag("--show-type-layout"); + cargo.rustdocflag("-Zunstable-options"); + builder.run(&mut cargo.into()); + } + } } } +tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]); +tool_doc!( + Rustfmt, + "rustfmt-nightly", + "src/tools/rustfmt", + ["rustfmt-nightly", "rustfmt-config_proc_macro"], + binary = true +); + #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { pub target: TargetSelection, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 92ac3b364f6..64b3ee7c359 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -9,7 +9,7 @@ use std::fmt; use std::fs; use std::iter; use std::path::{Path, PathBuf}; -use std::process::Command; +use std::process::{Command, Stdio}; use build_helper::{self, output, t}; @@ -161,6 +161,49 @@ You can skip linkcheck with --exclude src/tools/linkchecker" } } +fn check_if_tidy_is_installed() -> bool { + Command::new("tidy") + .arg("--version") + .stdout(Stdio::null()) + .status() + .map_or(false, |status| status.success()) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct HtmlCheck { + target: TargetSelection, +} + +impl Step for HtmlCheck { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + let run = run.path("src/tools/html-checker"); + run.lazy_default_condition(Box::new(check_if_tidy_is_installed)) + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(HtmlCheck { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + if !check_if_tidy_is_installed() { + eprintln!("not running HTML-check tool because `tidy` is missing"); + eprintln!( + "Note that `tidy` is not the in-tree `src/tools/tidy` but needs to be installed" + ); + panic!("Cannot run html-check tests"); + } + // Ensure that a few different kinds of documentation are available. + builder.default_doc(&[]); + builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage }); + + try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargotest { stage: u32, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9d75ad0918a..aa7fe658df3 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -376,6 +376,7 @@ bootstrap_tool!( ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; LintDocs, "src/tools/lint-docs", "lint-docs"; JsonDocCk, "src/tools/jsondocck", "jsondocck"; + HtmlChecker, "src/tools/html-checker", "html-checker"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 66afe84be4a..8066ea3a944 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -28,6 +28,7 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ +COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ @@ -37,6 +38,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py test --stage 2 src/tools/tidy && \ python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ + /scripts/validate-error-codes.sh && \ # Runs checks to ensure that there are no ES5 issues in our JS code. es-check es5 ../src/librustdoc/html/static/*.js && \ eslint ../src/librustdoc/html/static/*.js diff --git a/src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh b/src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh new file mode 100755 index 00000000000..e9aa948eb87 --- /dev/null +++ b/src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Checks that no error code explanation is removed. + +set -eo pipefail + +if [[ -z "$BASE_COMMIT" ]]; then + echo "not checking error code explanations removal" + exit 0 +fi + +echo "Check if an error code explanation was removed..." + +if (git diff "$BASE_COMMIT" --name-status | grep '^D' \ + | grep --quiet "compiler/rustc_error_codes/src/error_codes/"); then + echo "Error code explanations should never be removed!" + echo "Take a look at E0001 to see how to handle it." + exit 1 +fi + +echo "No error code explanation was removed!" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile index 7f1a5820e22..ee3cd092f4c 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile @@ -17,7 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1-mesa-dev \ llvm-dev \ libfreetype6-dev \ - libexpat1-dev + libexpat1-dev \ + tidy COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 35d274da673..6dcf0bdcba4 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ libssl-dev \ sudo \ - xz-utils + xz-utils \ + tidy # Install dependencies for chromium browser RUN apt-get install -y \ @@ -71,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.0 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.4.1 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 3a47076722c..489c3d76601 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -219,6 +219,14 @@ else command="/checkout/src/ci/run.sh" fi +if [ "$CI" != "" ]; then + # Get some needed information for $BASE_COMMIT + git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF" + BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)" +else + BASE_COMMIT="" +fi + docker \ run \ --workdir /checkout/obj \ @@ -237,6 +245,7 @@ docker \ --env TOOLSTATE_PUBLISH \ --env RUST_CI_OVERRIDE_RELEASE_CHANNEL \ --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ + --env BASE_COMMIT="$BASE_COMMIT" \ --init \ --rm \ rust-ci \ diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index c3c717266db..d2962179eea 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -15,14 +15,16 @@ function pgo_perf_benchmark { local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF local name=$1 + local edition=$2 curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs - RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \ --crate-type=lib /tmp/$name.rs } -pgo_perf_benchmark externs -pgo_perf_benchmark ctfe-stress-4 +pgo_perf_benchmark externs 2018 +pgo_perf_benchmark ctfe-stress-4 2018 +pgo_perf_benchmark inflate 2015 cp -pri ../src/tools/cargo /tmp/cargo diff --git a/src/doc/unstable-book/src/library-features/try-trait.md b/src/doc/unstable-book/src/library-features/try-trait.md deleted file mode 100644 index 022640067bd..00000000000 --- a/src/doc/unstable-book/src/library-features/try-trait.md +++ /dev/null @@ -1,50 +0,0 @@ -# `try_trait` - -The tracking issue for this feature is: [#42327] - -[#42327]: https://github.com/rust-lang/rust/issues/42327 - ------------------------- - -This introduces a new trait `Try` for extending the `?` operator to types -other than `Result` (a part of [RFC 1859]). The trait provides the canonical -way to _view_ a type in terms of a success/failure dichotomy. This will -allow `?` to supplant the `try_opt!` macro on `Option` and the `try_ready!` -macro on `Poll`, among other things. - -[RFC 1859]: https://github.com/rust-lang/rfcs/pull/1859 - -Here's an example implementation of the trait: - -```rust,ignore (cannot-reimpl-Try) -/// A distinct type to represent the `None` value of an `Option`. -/// -/// This enables using the `?` operator on `Option`; it's rarely useful alone. -#[derive(Debug)] -#[unstable(feature = "try_trait", issue = "42327")] -pub struct None { _priv: () } - -#[unstable(feature = "try_trait", issue = "42327")] -impl<T> ops::Try for Option<T> { - type Ok = T; - type Error = None; - - fn into_result(self) -> Result<T, None> { - self.ok_or(None { _priv: () }) - } - - fn from_ok(v: T) -> Self { - Some(v) - } - - fn from_error(_: None) -> Self { - None - } -} -``` - -Note the `Error` associated type here is a new marker. The `?` operator -allows interconversion between different `Try` implementers only when -the error type can be converted `Into` the error type of the enclosing -function (or catch block). Having a distinct error type (as opposed to -just `()`, or similar) restricts this to where it's semantically meaningful. diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 89280149a03..cf887ffb0c0 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -15,7 +15,7 @@ </Synthetic> </Expand> </Type> - <Type Name="slice<*>"> + <Type Name="slice$<*>"> <DisplayString>{{ len={length} }}</DisplayString> <Expand> <Item Name="[len]" ExcludeView="simple">length</Item> @@ -25,23 +25,23 @@ </ArrayItems> </Expand> </Type> - <Type Name="tuple<>"> + <Type Name="tuple$<>"> <DisplayString>()</DisplayString> </Type> - <Type Name="tuple<*>"> + <Type Name="tuple$<*>"> <DisplayString>({__0})</DisplayString> <Expand> <Item Name="[0]">__0</Item> </Expand> </Type> - <Type Name="tuple<*,*>"> + <Type Name="tuple$<*,*>"> <DisplayString>({__0}, {__1})</DisplayString> <Expand> <Item Name="[0]">__0</Item> <Item Name="[1]">__1</Item> </Expand> </Type> - <Type Name="tuple<*,*,*>"> + <Type Name="tuple$<*,*,*>"> <DisplayString>({__0}, {__1}, {__2})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -49,7 +49,7 @@ <Item Name="[2]">__2</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*>"> + <Type Name="tuple$<*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -58,7 +58,7 @@ <Item Name="[3]">__3</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -68,7 +68,7 @@ <Item Name="[4]">__4</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -79,7 +79,7 @@ <Item Name="[5]">__5</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -91,7 +91,7 @@ <Item Name="[6]">__6</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -104,7 +104,7 @@ <Item Name="[7]">__7</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -118,7 +118,7 @@ <Item Name="[8]">__8</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9})</DisplayString> <Expand> <Item Name="[0]">__0</Item> @@ -133,7 +133,7 @@ <Item Name="[9]">__9</Item> </Expand> </Type> - <Type Name="tuple<*,*,*,*,*,*,*,*,*,*,*>"> + <Type Name="tuple$<*,*,*,*,*,*,*,*,*,*,*>"> <DisplayString>({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...)</DisplayString> <Expand> <Item Name="[0]">__0</Item> diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 2c05f9d7c12..3ccd2e9c30e 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -41,7 +41,7 @@ <If Condition="(base.table.table.ctrl.pointer[i] & 0x80) == 0"> <!-- Bucket is populated --> <Exec>n--</Exec> - <Item Name="{((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item> + <Item Name="{((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__0}">((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1</Item> </If> <Exec>i++</Exec> </Loop> diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 9e98d0b7bbe..fb46b81102c 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -32,7 +32,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { cx.cache.owned_box_did = cx.tcx.lang_items().owned_box(); let mut externs = Vec::new(); - for &cnum in cx.tcx.crates().iter() { + for &cnum in cx.tcx.crates(()).iter() { externs.push((cnum, cnum.clean(cx))); // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c3d9c4ea7f2..66f4f481292 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,12 +1,12 @@ -use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; use rustc_driver::abort_on_err; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; +use rustc_hir::def::Namespace::TypeNS; use rustc_hir::def::Res; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::HirId; use rustc_hir::{ intravisit::{self, NestedVisitorMap, Visitor}, @@ -23,7 +23,7 @@ use rustc_session::DiagnosticOutput; use rustc_session::Session; use rustc_span::source_map; use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::RefCell; use std::mem; @@ -300,17 +300,41 @@ crate fn create_config( } crate fn create_resolver<'a>( + externs: config::Externs, queries: &Queries<'a>, sess: &Session, ) -> Rc<RefCell<interface::BoxedResolver>> { - let parts = abort_on_err(queries.expansion(), sess).peek(); - let (krate, resolver, _) = &*parts; - let resolver = resolver.borrow().clone(); - - let mut loader = crate::passes::collect_intra_doc_links::IntraLinkCrateLoader::new(resolver); - ast::visit::walk_crate(&mut loader, krate); + let extern_names: Vec<String> = externs + .iter() + .filter(|(_, entry)| entry.add_prelude) + .map(|(name, _)| name) + .cloned() + .collect(); + + let (_, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek(); + + // Before we actually clone it, let's force all the extern'd crates to + // actually be loaded, just in case they're only referred to inside + // intra-doc links + resolver.borrow_mut().access(|resolver| { + sess.time("load_extern_crates", || { + for extern_name in &extern_names { + debug!("loading extern crate {}", extern_name); + if let Err(()) = resolver + .resolve_str_path_error( + DUMMY_SP, + extern_name, + TypeNS, + LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), + ) { + warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name) + } + } + }); + }); - loader.resolver + // Now we're good to clone the resolver because everything should be loaded + resolver.clone() } crate fn run_global_ctxt( diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 1750f05b4dc..1281f76fd0f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -112,7 +112,6 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { let res = interface::run_compiler(config, |compiler| { compiler.enter(|queries| { - let _lower_to_hir = queries.lower_to_hir()?; let mut global_ctxt = queries.global_ctxt()?.take(); let collector = global_ctxt.enter(|tcx| { @@ -942,9 +941,7 @@ impl Tester for Collector { // compiler failures are test failures should_panic: testing::ShouldPanic::No, allow_fail: config.allow_fail, - #[cfg(not(bootstrap))] compile_fail: config.compile_fail, - #[cfg(not(bootstrap))] no_run, test_type: testing::TestType::DocTest, }, diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 4372ece5c01..0734d2670cc 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -219,6 +219,7 @@ crate fn get_index_search_type<'tcx>( fn get_index_type(clean_type: &clean::Type) -> RenderType { RenderType { name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), + generics: get_generics(clean_type), } } @@ -251,6 +252,23 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } +/// Return a list of generic parameters for use in the search index. +/// +/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`. +/// It does return duplicates, and that's intentional, since search queries like `Result<usize, usize>` +/// are supposed to match only results where both parameters are `usize`. +fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> { + clean_type.generics().and_then(|types| { + let r = types + .iter() + .filter_map(|t| { + get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase()) + }) + .collect::<Vec<_>>(); + if r.is_empty() { None } else { Some(r) } + }) +} + /// The point of this function is to replace bounds with types. /// /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6e73b2a5bef..0583efa92ff 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -96,6 +96,7 @@ crate struct IndexItem { #[derive(Debug)] crate struct RenderType { name: Option<String>, + generics: Option<Vec<String>>, } /// Full type of functions/methods in the search index. @@ -149,7 +150,13 @@ impl Serialize for TypeWithKind { where S: Serializer, { - (&self.ty.name, self.kind).serialize(serializer) + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty.name)?; + seq.serialize_element(&self.kind)?; + if let Some(generics) = &self.ty.generics { + seq.serialize_element(generics)?; + } + seq.end() } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 5fd0607356d..ea141c51048 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -363,10 +363,11 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl write!( w, "<div class=\"item-left {stab}{add}module-item\">\ - <a class=\"{class}\" href=\"{href}\" \ - title=\"{title}\">{name}</a>{unsafety_flag}\ + <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\ + {unsafety_flag}\ + {stab_tags}\ </div>\ - <div class=\"item-right docblock-short\">{stab_tags}{docs}</div>", + <div class=\"item-right docblock-short\">{docs}</div>", name = *myitem.name.as_ref().unwrap(), stab_tags = extra_info_tags(myitem, item, cx.tcx()), docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(), diff --git a/src/librustdoc/html/static/normalize.css b/src/librustdoc/html/static/normalize.css index 0e042627918..fdb8a8c652e 100644 --- a/src/librustdoc/html/static/normalize.css +++ b/src/librustdoc/html/static/normalize.css @@ -1,2 +1,2 @@ /* ignore-tidy-linelength */ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index db200fe7913..71123aa9a0e 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -146,9 +146,15 @@ h1.fqn > .in-band > a:hover { h2, h3, h4 { border-bottom: 1px solid; } -.impl, .impl-items .method, -.impl-items .type, .impl-items .associatedconstant, -.impl-items .associatedtype { +.impl, +.impl-items .method, +.methods .method, +.impl-items .type, +.methods .type, +.impl-items .associatedconstant, +.methods .associatedconstant, +.impl-items .associatedtype, +.methods .associatedtype { flex-basis: 100%; font-weight: 600; margin-top: 16px; @@ -200,10 +206,31 @@ summary { outline: none; } -/* FIXME: Remove after normalize.css is either upgraded or removed (#86629) */ +/* Fix some style changes due to normalize.css 8 */ + +td, +th { + padding: 0; +} + +table { + border-collapse: collapse; +} + +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} + +/* end tweaks for normalize.css 8 */ + details:not(.rustdoc-toggle) summary { margin-bottom: .6em; - display: list-item; } code, pre, a.test-arrow { @@ -923,7 +950,7 @@ body.blur > :not(#help) { font-size: 80%; line-height: 1.2; margin-bottom: 0; - margin-right: .3em; + margin-left: .3em; padding: 2px; vertical-align: text-bottom; } diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js index 0aebb0e9d65..a7fc0b831f4 100644 --- a/src/librustdoc/html/static/search.js +++ b/src/librustdoc/html/static/search.js @@ -106,7 +106,7 @@ function levenshtein(s1, s2) { window.initSearch = function(rawSearchIndex) { var MAX_LEV_DISTANCE = 3; var MAX_RESULTS = 200; - var GENERICS_DATA = 1; + var GENERICS_DATA = 2; var NAME = 0; var INPUTS_DATA = 0; var OUTPUT_DATA = 1; @@ -306,6 +306,9 @@ window.initSearch = function(rawSearchIndex) { var elems = Object.create(null); var elength = obj[GENERICS_DATA].length; for (var x = 0; x < elength; ++x) { + if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) { + elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0; + } elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; } var total = 0; @@ -354,10 +357,13 @@ window.initSearch = function(rawSearchIndex) { if (literalSearch) { if (val.generics && val.generics.length !== 0) { if (obj.length > GENERICS_DATA && - obj[GENERICS_DATA].length >= val.generics.length) { + obj[GENERICS_DATA].length > 0) { var elems = Object.create(null); len = obj[GENERICS_DATA].length; for (x = 0; x < len; ++x) { + if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) { + elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0; + } elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; } @@ -375,26 +381,23 @@ window.initSearch = function(rawSearchIndex) { if (allFound) { return true; } - } else { - return false; } + return false; } return true; - } - // If the type has generics but don't match, then it won't return at this point. - // Otherwise, `checkGenerics` will return 0 and it'll return. - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { - var tmp_lev = checkGenerics(obj, val); - if (tmp_lev <= MAX_LEV_DISTANCE) { - return tmp_lev; - } } else { - return 0; + // If the type has generics but don't match, then it won't return at this point. + // Otherwise, `checkGenerics` will return 0 and it'll return. + if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { + var tmp_lev = checkGenerics(obj, val); + if (tmp_lev <= MAX_LEV_DISTANCE) { + return tmp_lev; + } + } } - } - // Names didn't match so let's check if one of the generic types could. - if (literalSearch) { - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { + } else if (literalSearch) { + if ((!val.generics || val.generics.length === 0) && + obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { return obj[GENERICS_DATA].some( function(name) { return name === val.name; @@ -801,7 +804,8 @@ window.initSearch = function(rawSearchIndex) { results_returned[fullId].lev = Math.min(results_returned[fullId].lev, returned); } - if (index !== -1 || lev <= MAX_LEV_DISTANCE) { + if (typePassesFilter(typeFilter, ty.ty) && + (index !== -1 || lev <= MAX_LEV_DISTANCE)) { if (index !== -1 && paths.length < 2) { lev = 0; } @@ -1166,7 +1170,48 @@ window.initSearch = function(rawSearchIndex) { return ret; } - var queries = query.raw.split(","); + // Split search query by ",", while respecting angle bracket nesting. + // Since "<" is an alias for the Ord family of traits, it also uses + // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket. + // + // tokenizeQuery("A<B, C>, D") == ["A<B, C>", "D"] + // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"] + function tokenizeQuery(raw) { + var i, matched; + var l = raw.length; + var depth = 0; + var nextAngle = /(<|>)/g; + var ret = []; + var start = 0; + for (i = 0; i < l; ++i) { + switch (raw[i]) { + case "<": + nextAngle.lastIndex = i + 1; + matched = nextAngle.exec(raw); + if (matched && matched[1] === '>') { + depth += 1; + } + break; + case ">": + if (depth > 0) { + depth -= 1; + } + break; + case ",": + if (depth === 0) { + ret.push(raw.substring(start, i)); + start = i + 1; + } + break; + } + } + if (start !== i) { + ret.push(raw.substring(start, i)); + } + return ret; + } + + var queries = tokenizeQuery(query.raw); var results = { "in_args": [], "returned": [], diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ee7a716655b..64a9905b33f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,6 @@ extern crate tracing; // Dependencies listed in Cargo.toml do not need `extern crate`. extern crate rustc_ast; -extern crate rustc_ast_lowering; extern crate rustc_ast_pretty; extern crate rustc_attr; extern crate rustc_data_structures; @@ -714,6 +713,7 @@ fn main_options(options: config::Options) -> MainResult { let default_passes = options.default_passes; let output_format = options.output_format; // FIXME: fix this clone (especially render_options) + let externs = options.externs.clone(); let manual_passes = options.manual_passes.clone(); let render_options = options.render_options.clone(); let config = core::create_config(options); @@ -731,7 +731,7 @@ fn main_options(options: config::Options) -> MainResult { // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. - let resolver = core::create_resolver(queries, &sess); + let resolver = core::create_resolver(externs, queries, &sess); if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc"); diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 376c83b1a6e..49d8d7fb7fb 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -193,7 +193,7 @@ crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) { ); for lint in &*RUSTDOC_LINTS { let name = lint.name_lower(); - lint_store.register_alias(&name.replace("rustdoc::", ""), &name); + lint_store.register_renamed(&name.replace("rustdoc::", ""), &name); } lint_store .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links"); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index c7e2ce74019..1113d610128 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -37,9 +37,6 @@ use crate::html::markdown::{markdown_links, MarkdownLink}; use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}; use crate::passes::Pass; -mod early; -crate use early::IntraLinkCrateLoader; - crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass { name: "collect-intra-doc-links", run: collect_intra_doc_links, diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs deleted file mode 100644 index 7cba2523d1a..00000000000 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ /dev/null @@ -1,63 +0,0 @@ -use rustc_ast as ast; -use rustc_hir::def::Namespace::TypeNS; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; -use rustc_interface::interface; - -use std::cell::RefCell; -use std::mem; -use std::rc::Rc; - -// Letting the resolver escape at the end of the function leads to inconsistencies between the -// crates the TyCtxt sees and the resolver sees (because the resolver could load more crates -// after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ... -crate struct IntraLinkCrateLoader { - current_mod: DefId, - crate resolver: Rc<RefCell<interface::BoxedResolver>>, -} - -impl IntraLinkCrateLoader { - crate fn new(resolver: Rc<RefCell<interface::BoxedResolver>>) -> Self { - let crate_id = LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(); - Self { current_mod: crate_id, resolver } - } -} - -impl ast::visit::Visitor<'_> for IntraLinkCrateLoader { - fn visit_attribute(&mut self, attr: &ast::Attribute) { - use crate::html::markdown::markdown_links; - use crate::passes::collect_intra_doc_links::preprocess_link; - - if let Some(doc) = attr.doc_str() { - for link in markdown_links(&doc.as_str()) { - let path_str = if let Some(Ok(x)) = preprocess_link(&link) { - x.path_str - } else { - continue; - }; - self.resolver.borrow_mut().access(|resolver| { - let _ = resolver.resolve_str_path_error( - attr.span, - &path_str, - TypeNS, - self.current_mod, - ); - }); - } - } - ast::visit::walk_attribute(self, attr); - } - - fn visit_item(&mut self, item: &ast::Item) { - use rustc_ast_lowering::ResolverAstLowering; - - if let ast::ItemKind::Mod(..) = item.kind { - let new_mod = - self.resolver.borrow_mut().access(|resolver| resolver.local_def_id(item.id)); - let old_mod = mem::replace(&mut self.current_mod, new_mod.to_def_id()); - ast::visit::walk_item(self, item); - self.current_mod = old_mod; - } else { - ast::visit::walk_item(self, item); - } - } -} diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 6d7c45f6eea..8280bbf0858 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -29,7 +29,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { let mut new_items = Vec::new(); - for &cnum in cx.tcx.crates().iter() { + for &cnum in cx.tcx.crates(()).iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| { inline::build_impl(cx, None, did, None, &mut new_items); @@ -85,7 +85,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } }); - // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` + // `tcx.crates(())` doesn't include the local crate, and `tcx.all_trait_implementations` // doesn't work with it anyway, so pull them from the HIR map instead let mut extra_attrs = Vec::new(); for &trait_did in cx.tcx.all_traits(()).iter() { diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 0e86fe45640..390ab1694a0 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -30,7 +30,7 @@ crate use self::unindent_comments::UNINDENT_COMMENTS; mod propagate_doc_cfg; crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; -crate mod collect_intra_doc_links; +mod collect_intra_doc_links; crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; mod doc_test_lints; diff --git a/src/stage0.txt b/src/stage0.txt index 1027057f385..e9d0b73e94d 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # stable release's version number. `date` is the date where the release we're # bootstrapping off was released. -date: 2021-05-23 +date: 2021-06-23 rustc: beta # We use a nightly rustfmt to format the source because it solves some diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index e410180bfff..8efa1b15b3f 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -17,7 +17,7 @@ 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" +// 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, diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index 7de115f7e91..39319a3ea72 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -17,7 +17,7 @@ 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_structure_type, name: "generator-0", scope: [[ASYNC_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/codegen/fn-impl-trait-self.rs b/src/test/codegen/fn-impl-trait-self.rs index f9113d50197..4bd811bed10 100644 --- a/src/test/codegen/fn-impl-trait-self.rs +++ b/src/test/codegen/fn-impl-trait-self.rs @@ -1,7 +1,8 @@ // compile-flags: -g // // CHECK-LABEL: @main -// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}} +// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}} +// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}} // // CHECK: {{.*}}DISubroutineType{{.*}} // CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned) diff --git a/src/test/codegen/frame-pointer.rs b/src/test/codegen/frame-pointer.rs new file mode 100644 index 00000000000..367591dcb96 --- /dev/null +++ b/src/test/codegen/frame-pointer.rs @@ -0,0 +1,35 @@ +// compile-flags: --crate-type=rlib +// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux +// [aarch64-apple] needs-llvm-components: aarch64 +// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin +// [aarch64-linux] needs-llvm-components: aarch64 +// [aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu +// [force] needs-llvm-components: x86 +// [force] compile-flags: --target=x86_64-unknown-linux-gnu -Cforce-frame-pointers=yes +// [x64-apple] needs-llvm-components: x86 +// [x64-apple] compile-flags: --target=x86_64-apple-darwin +// [x64-linux] needs-llvm-components: x86 +// [x64-linux] compile-flags: --target=x86_64-unknown-linux-gnu + +#![feature(no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } + + + +// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] { +#[no_mangle] +pub fn peach(x: u32) -> u32 { + x +} + +// CHECK: attributes [[PEACH_ATTRS]] = { +// x64-linux-NOT: {{.*}}"frame-pointer"{{.*}} +// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}} +// x64-apple-SAME: {{.*}}"frame-pointer"="all" +// force-SAME: {{.*}}"frame-pointer"="all" +// aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf" +// CHECK-SAME: } diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 7edb07d224c..e2ba4ad3089 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -21,7 +21,7 @@ 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" +// 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, diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 8b87a2f0646..ea324695c15 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -21,7 +21,7 @@ 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_structure_type, name: "generator-0", scope: [[GEN_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 3721b87678d..c35c3255498 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -6,9 +6,8 @@ // min-lldb-version: 310 -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -// only-macos +// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. +// ignore-linux // compile-flags:-g @@ -44,6 +43,9 @@ // gdb-check:$13 = 2.5 // gdb-command:print f64 // gdb-check:$14 = 3.5 +// gdb-command:print s +// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13} +// gdbr-check:$15 = "Hello, World!" // === LLDB TESTS ================================================================================== @@ -94,6 +96,41 @@ // lldbg-check:[...]$12 = 3.5 // lldbr-check:(f64) f64 = 3.5 + +// === CDB TESTS =================================================================================== + +// cdb-command:g +// cdb-command:dx b +// cdb-check:b : false [Type: bool] +// cdb-command:dx i +// cdb-check:i : -1 [Type: [...]] +// The variable 'c' doesn't appear for some reason... +// cdb-command:dx i8 +// cdb-check:i8 : 68 [Type: char] +// cdb-command:dx i16 +// cdb-check:i16 : -16 [Type: short] +// cdb-command:dx i32 +// cdb-check:i32 : -32 [Type: int] +// cdb-command:dx i64 +// cdb-check:i64 : -64 [Type: __int64] +// cdb-command:dx u +// cdb-check:u : 0x1 [Type: [...]] +// cdb-command:dx u8 +// cdb-check:u8 : 0x64 [Type: unsigned char] +// cdb-command:dx u16 +// cdb-check:u16 : 0x10 [Type: unsigned short] +// cdb-command:dx u32 +// cdb-check:u32 : 0x20 [Type: unsigned int] +// cdb-command:dx u64 +// cdb-check:u64 : 0x40 [Type: unsigned __int64] +// cdb-command:dx f32 +// cdb-check:f32 : 2.500000 [Type: float] +// cdb-command:dx f64 +// cdb-check:f64 : 3.500000 [Type: double] +// cdb-command:.enable_unicode 1 +// cdb-command:dx s +// cdb-check:s : "Hello, World!" [Type: str] + #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -113,6 +150,7 @@ fn main() { let u64: u64 = 64; let f32: f32 = 2.5; let f64: f64 = 3.5; + let s: &str = "Hello, World!"; _zzz(); // #break } diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs new file mode 100644 index 00000000000..26317f5c3ff --- /dev/null +++ b/src/test/debuginfo/function-names.rs @@ -0,0 +1,175 @@ +// Function names are formatted differently in old versions of GDB +// min-gdb-version: 9.2 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// Top-level function +// gdb-command:info functions -q function_names::main +// gdb-check:[...]static fn function_names::main(); +// gdb-command:info functions -q function_names::generic_func<* +// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; + +// Implementations +// gdb-command:info functions -q function_names::.*::impl_function.* +// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function(); +// gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function(); +// gdb-check:[...]static fn function_names::TestStruct1::impl_function(); + +// Trait implementations +// gdb-command:info functions -q function_names::.*::trait_function.* +// gdb-check:[...]static fn <function_names::GenericStruct<T,i32> as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn <function_names::GenericStruct<[T; N],f32> as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn <function_names::Mod1::TestStruct2 as function_names::Mod1::TestTrait2>::trait_function(); +// gdb-check:[...]static fn <function_names::TestStruct1 as function_names::TestTrait1>::trait_function(); + +// Closure +// gdb-command:info functions -q function_names::.*::{{closure.* +// gdb-check:[...]static fn function_names::GenericStruct<T1,T2>::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0}); +// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0}); +// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0}); + +// Generator +// Generators don't seem to appear in GDB's symbol table. + +// === CDB TESTS =================================================================================== + +// Top-level function +// cdb-command:x a!function_names::main +// cdb-check:[...] a!function_names::main (void) +// cdb-command:x a!function_names::generic_func<* +// cdb-check:[...] a!function_names::generic_func<i32> (int) + +// Implementations +// cdb-command:x a!function_names::*::impl_function* +// cdb-check:[...] a!function_names::Mod1::TestStruct2::impl_function (void) +// cdb-check:[...] a!function_names::TestStruct1::impl_function (void) +// cdb-check:[...] a!function_names::GenericStruct<i32, i32>::impl_function<i32, i32> (void) + +// Trait implementations +// cdb-command:x a!function_names::*::trait_function* +// cdb-check:[...] a!function_names::impl$6::trait_function<i32, 0x1> (void) +// cdb-check:[...] a!function_names::impl$3::trait_function<i32> (void) +// cdb-check:[...] a!function_names::impl$1::trait_function (void) +// cdb-check:[...] a!function_names::impl$5::trait_function3<function_names::TestStruct1> (void) +// cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void) + +// Closure +// cdb-command:x a!function_names::*::closure* +// cdb-check:[...] a!function_names::main::closure$0 (void) +// cdb-check:[...] a!function_names::generic_func::closure$0<i32> (void) +// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0<i32, i32> (void) + +// Generator +// cdb-command:x a!function_names::*::generator* +// cdb-check:[...] a!function_names::main::generator$1 (void) + +#![allow(unused_variables)] +#![feature(omit_gdb_pretty_printer_section)] +#![omit_gdb_pretty_printer_section] +#![feature(generators, generator_trait)] + +use Mod1::TestTrait2; +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + // Implementations + TestStruct1::impl_function(); + Mod1::TestStruct2::impl_function(); + GenericStruct::<i32, i32>::impl_function(); + + // Trait implementations + TestStruct1::trait_function(); + Mod1::TestStruct2::trait_function(); + GenericStruct::<i32, i32>::trait_function(); + GenericStruct::<[i32; 1], f32>::trait_function(); + GenericStruct::<TestStruct1, usize>::trait_function3(); + + // Generic function + let _ = generic_func(42); + + // Closure + let closure = || { TestStruct1 }; + closure(); + + // Generator + let mut generator = || { yield; return; }; + Pin::new(&mut generator).resume(()); +} + +struct TestStruct1; +trait TestTrait1 { + fn trait_function(); +} + +// Implementation +impl TestStruct1 { + pub fn impl_function() {} +} + +// Implementation for a trait +impl TestTrait1 for TestStruct1 { + fn trait_function() {} +} + +// Implementation and implementation within a mod +mod Mod1 { + pub struct TestStruct2; + pub trait TestTrait2 { + fn trait_function(); + } + + impl TestStruct2 { + pub fn impl_function() {} + } + + impl TestTrait2 for TestStruct2 { + fn trait_function() {} + } +} + +struct GenericStruct<T1, T2>(std::marker::PhantomData<(T1, T2)>); + +// Generic implementation +impl<T1, T2> GenericStruct<T1, T2> { + pub fn impl_function() { + // Closure in a generic implementation + let closure = || { TestStruct1 }; + closure(); + } +} + +// Generic trait implementation +impl<T> TestTrait1 for GenericStruct<T, i32> { + fn trait_function() {} +} + +// Implementation based on associated type +trait TestTrait3 { + type AssocType; + fn trait_function3(); +} +impl TestTrait3 for TestStruct1 { + type AssocType = usize; + fn trait_function3() {} +} +impl<T: TestTrait3> TestTrait3 for GenericStruct<T, T::AssocType> { + type AssocType = T::AssocType; + fn trait_function3() {} +} + +// Generic trait implementation with const generics +impl<T, const N: usize> TestTrait1 for GenericStruct<[T; N], f32> { + fn trait_function() {} +} + +// Generic function +fn generic_func<T>(value: T) -> T { + // Closure in a generic function + let closure = || { TestStruct1 }; + closure(); + + value +} diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 1beed1c835d..7ac3304aa96 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -11,31 +11,31 @@ // gdb-command:run // gdb-command:print b -// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...]) +// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed(0x[...]) // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]} +// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]} +// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...]) +// gdb-check:$4 = generator_objects::main::{generator#0}::Returned(0x[...]) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $0 = +// lldbg-check:(generator_objects::main::{generator#0}) $0 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $1 = +// lldbg-check:(generator_objects::main::{generator#0}) $1 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $2 = +// lldbg-check:(generator_objects::main::{generator#0}) $2 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $3 = +// lldbg-check:(generator_objects::main::{generator#0}) $3 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 170a610c621..c0135de1219 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -39,6 +39,27 @@ // lldbg-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } } // lldbr-check:(generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>>) float_int_float = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } } +// === CDB TESTS =================================================================================== + +// cdb-command:g + +// cdb-command:dx int_int +// cdb-check:int_int [Type: generic_struct::AGenericStruct<i32, i32>] +// cdb-check:[...]key : 0 [Type: int] +// cdb-check:[...]value : 1 [Type: int] +// cdb-command:dx int_float +// cdb-check:int_float [Type: generic_struct::AGenericStruct<i32, f64>] +// cdb-check:[...]key : 2 [Type: int] +// cdb-check:[...]value : 3.500000 [Type: double] +// cdb-command:dx float_int +// cdb-check:float_int [Type: generic_struct::AGenericStruct<f64, i32>] +// cdb-check:[...]key : 4.500000 [Type: double] +// cdb-check:[...]value : 5 [Type: int] +// cdb-command:dx float_int_float +// cdb-check:float_int_float [Type: generic_struct::AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64> >] +// cdb-check:[...]key : 6.500000 [Type: double] +// cdb-check:[...]value [Type: generic_struct::AGenericStruct<i32, f64>] + #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index 6b2b12edda5..f6d2146fe11 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -11,20 +11,20 @@ // gdb-command:run // gdb-command:print g -// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) +// gdb-check:$1 = issue_57822::main::{closure#1} (issue_57822::main::{closure#0} (1)) // gdb-command:print b -// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2)) +// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed(issue_57822::main::{generator#2}::Unresumed(2)) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print g -// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } } +// lldbg-check:(issue_57822::main::{closure#1}) $0 = { 0 = { 0 = 1 } } // lldb-command:print b -// lldbg-check:(issue_57822::main::generator-3) $1 = +// lldbg-check:(issue_57822::main::{generator#3}) $1 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 550cc66f389..cf3be2e7196 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -1,5 +1,4 @@ // only-cdb -// ignore-tidy-linelength // compile-flags:-g // cdb-command: g @@ -8,16 +7,16 @@ // 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: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-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: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-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>] @@ -38,24 +37,24 @@ // 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:f,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<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-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<ref$<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:g,! [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$<core::option::Option<ref$<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-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$] // cdb-command: dx h -// cdb-check:h : Some [Type: enum$<core::option::Option<u32>>] +// 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:i : None [Type: enum$<core::option::Option<u32> >] // cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option] // cdb-command: dx j diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 969099359ab..40bea30f125 100644 --- a/src/test/debuginfo/mutex.rs +++ b/src/test/debuginfo/mutex.rs @@ -3,7 +3,6 @@ // cdb-only // min-cdb-version: 10.0.21287.1005 // compile-flags:-g -// ignore-tidy-linelength // === CDB TESTS ================================================================================== // @@ -22,7 +21,7 @@ // // cdb-command:dx lock,d -// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32>>, 0, 1, Poisoned>>>] +// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >] // cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result] // cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>] diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs index 7115aec1041..ede15578712 100644 --- a/src/test/debuginfo/pretty-std-collections-hash.rs +++ b/src/test/debuginfo/pretty-std-collections-hash.rs @@ -77,6 +77,8 @@ // cdb-command: dx hash_map,d // cdb-check: ["0xe"] : 14 [Type: unsigned __int64] +// cdb-command: dx x + #![allow(unused_variables)] use std::collections::HashSet; use std::collections::HashMap; @@ -95,6 +97,9 @@ fn main() { hash_map.insert(i as u64, i as u64); } + let x = &(123u64, 456u64); + let string = "awefawefawe".to_string(); + zzz(); // #break } diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index aeee1e6258d..a7f384c0500 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,7 +1,6 @@ // 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 @@ -72,7 +71,7 @@ // cdb-command: g // cdb-command: dx slice,d -// cdb-check:slice,d : { len=4 } [Type: slice<i32>] +// cdb-check:slice,d : { len=4 } [Type: slice$<i32>] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [0] : 0 [Type: int] // cdb-check: [1] : 1 [Type: int] @@ -116,12 +115,12 @@ // NOTE: OsString doesn't have a .natvis entry yet. // cdb-command: dx some -// cdb-check:some : Some [Type: enum$<core::option::Option<i16>>] +// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >] // cdb-check: [...] variant$ : Some (0x1) [Type: core::option::Option] // cdb-check: [...] __0 : 8 [Type: short] // cdb-command: dx none -// cdb-check:none : None [Type: enum$<core::option::Option<i64>>] +// cdb-check:none : None [Type: enum$<core::option::Option<i64> >] // cdb-check: [...] variant$ : None (0x0) [Type: core::option::Option] // cdb-command: dx some_string diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index 9f1e856ab42..6e558bd3c13 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -1,6 +1,5 @@ // pretty-printers are not loaded // compile-flags:-g -// ignore-tidy-linelength // min-gdb-version: 8.1 // min-cdb-version: 10.0.18317.1001 @@ -36,7 +35,7 @@ // cdb-command:dx w1,d // cdb-check:w1,d [Type: alloc::rc::Weak<i32>] -// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32>>] +// cdb-check: [...] ptr : [...] [Type: core::ptr::non_null::NonNull<alloc::rc::RcBox<i32> >] // cdb-command:dx a,d // cdb-check:a,d : 42 [Type: alloc::sync::Arc<i32>] diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs index 18eae7f301f..a075c437c46 100644 --- a/src/test/debuginfo/result-types.rs +++ b/src/test/debuginfo/result-types.rs @@ -7,11 +7,11 @@ // cdb-command: g // cdb-command: dx x,d -// cdb-check:x,d : Ok [Type: enum$<core::result::Result<i32, str>>] +// cdb-check:x,d : Ok [Type: enum$<core::result::Result<i32, str> >] // cdb-check: [...] __0 : -3 [Type: int] // cdb-command: dx y -// cdb-check:y : Err [Type: enum$<core::result::Result<i32, str>>] +// cdb-check:y : Err [Type: enum$<core::result::Result<i32, str> >] // cdb-check: [...] __0 : "Some error message" [Type: str] fn main() diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index b7fcfeef090..0807cfedce0 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -129,38 +129,38 @@ // cdb-command: g // cdb-command:dx noPadding8,d -// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple<i8, u8>] +// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$<i8,u8>] // cdb-check:[...][0] : -100 [Type: [...]] // cdb-check:[...][1] : 100 [Type: [...]] // cdb-command:dx noPadding16,d -// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple<i16, i16, u16>] +// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$<i16,i16,u16>] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-check:[...][2] : 2 [Type: [...]] // cdb-command:dx noPadding32,d -// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple<i32, f32, u32>] +// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$<i32,f32,u32>] // cdb-check:[...][0] : 3 [Type: [...]] // cdb-check:[...][1] : 4.5[...] [Type: [...]] // cdb-check:[...][2] : 5 [Type: [...]] // cdb-command:dx noPadding64,d -// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple<i64, f64, u64>] +// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$<i64,f64,u64>] // cdb-check:[...][0] : 6 [Type: [...]] // cdb-check:[...][1] : 7.500000 [Type: [...]] // cdb-check:[...][2] : 8 [Type: [...]] // cdb-command:dx internalPadding1,d -// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple<i16, i32>] +// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$<i16,i32>] // cdb-check:[...][0] : 9 [Type: short] // cdb-check:[...][1] : 10 [Type: int] // cdb-command:dx internalPadding2,d -// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple<i16, i32, u32, u64>] +// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$<i16,i32,u32,u64>] // cdb-check:[...][0] : 11 [Type: [...]] // cdb-check:[...][1] : 12 [Type: [...]] // cdb-check:[...][2] : 13 [Type: [...]] // cdb-check:[...][3] : 14 [Type: [...]] // cdb-command:dx paddingAtEnd,d -// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple<i32, i16>] +// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$<i32,i16>] // cdb-check:[...][0] : 15 [Type: [...]] // cdb-check:[...][1] : 16 [Type: [...]] diff --git a/src/test/debuginfo/thread.rs b/src/test/debuginfo/thread.rs index af35ad6af07..531c37a3421 100644 --- a/src/test/debuginfo/thread.rs +++ b/src/test/debuginfo/thread.rs @@ -9,8 +9,8 @@ // cdb-command:g // // cdb-command:dx join_handle,d -// cdb-check:join_handle,d [Type: std::thread::JoinHandle<tuple<>>] -// cdb-check: [...] __0 [Type: std::thread::JoinInner<tuple<>>] +// cdb-check:join_handle,d [Type: std::thread::JoinHandle<tuple$<> >] +// cdb-check: [...] __0 [Type: std::thread::JoinInner<tuple$<> >] // // cdb-command:dx t,d // cdb-check:t,d : [...] [Type: std::thread::Thread *] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index 0447d8e9dde..578db74e9ee 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -65,64 +65,64 @@ // cdb-command: g // cdb-command:dx no_padding1,d -// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple<tuple<u32, u32>, u32, u32>] -// cdb-check:[...][0] : (0, 1) [Type: tuple<u32, u32>] +// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$<tuple$<u32,u32>,u32,u32>] +// cdb-check:[...][0] : (0, 1) [Type: tuple$<u32,u32>] // cdb-check:[...][1] : 2 [Type: [...]] // cdb-check:[...][2] : 3 [Type: [...]] // cdb-command:dx no_padding1.__0,d -// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple<u32, u32>] +// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$<u32,u32>] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-command:dx no_padding2,d -// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple<u32, tuple<u32, u32>, u32>] +// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$<u32,tuple$<u32,u32>,u32>] // cdb-check:[...][0] : 4 [Type: [...]] -// cdb-check:[...][1] : (5, 6) [Type: tuple<u32, u32>] +// cdb-check:[...][1] : (5, 6) [Type: tuple$<u32,u32>] // cdb-check:[...][2] : 7 [Type: [...]] // cdb-command:dx no_padding2.__1,d -// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple<u32, u32>] +// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$<u32,u32>] // cdb-check:[...][0] : 5 [Type: [...]] // cdb-check:[...][1] : 6 [Type: [...]] // cdb-command:dx no_padding3,d -// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple<u32, u32, tuple<u32, u32>>] +// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$<u32,u32,tuple$<u32,u32> >] // cdb-check:[...][0] : 8 [Type: [...]] // cdb-check:[...][1] : 9 [Type: [...]] -// cdb-check:[...][2] : (10, 11) [Type: tuple<u32, u32>] +// cdb-check:[...][2] : (10, 11) [Type: tuple$<u32,u32>] // cdb-command:dx no_padding3.__2,d -// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple<u32, u32>] +// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$<u32,u32>] // cdb-check:[...][0] : 10 [Type: [...]] // cdb-check:[...][1] : 11 [Type: [...]] // cdb-command:dx internal_padding1,d -// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple<i16, tuple<i32, i32>>] +// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$<i16,tuple$<i32,i32> >] // cdb-check:[...][0] : 12 [Type: [...]] -// cdb-check:[...][1] : (13, 14) [Type: tuple<i32, i32>] +// cdb-check:[...][1] : (13, 14) [Type: tuple$<i32,i32>] // cdb-command:dx internal_padding1.__1,d -// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple<i32, i32>] +// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$<i32,i32>] // cdb-check:[...][0] : 13 [Type: [...]] // cdb-check:[...][1] : 14 [Type: [...]] // cdb-command:dx internal_padding2,d -// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple<i16, tuple<i16, i32>>] +// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$<i16,tuple$<i16,i32> >] // cdb-check:[...][0] : 15 [Type: [...]] -// cdb-check:[...][1] : (16, 17) [Type: tuple<i16, i32>] +// cdb-check:[...][1] : (16, 17) [Type: tuple$<i16,i32>] // cdb-command:dx internal_padding2.__1,d -// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple<i16, i32>] +// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$<i16,i32>] // cdb-check:[...][0] : 16 [Type: [...]] // cdb-check:[...][1] : 17 [Type: [...]] // cdb-command:dx padding_at_end1,d -// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple<i32, tuple<i32, i16>>] +// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$<i32,tuple$<i32,i16> >] // cdb-check:[...][0] : 18 [Type: [...]] -// cdb-check:[...][1] : (19, 20) [Type: tuple<i32, i16>] +// cdb-check:[...][1] : (19, 20) [Type: tuple$<i32,i16>] // cdb-command:dx padding_at_end1.__1,d -// cdb-check:padding_at_end1.__1,d [...][Type: tuple<i32, i16>] +// cdb-check:padding_at_end1.__1,d [...][Type: tuple$<i32,i16>] // cdb-check:[...][0] : 19 [Type: [...]] // cdb-check:[...][1] : 20 [Type: [...]] // cdb-command:dx padding_at_end2,d -// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple<tuple<i32, i16>, i32>] -// cdb-check:[...][0] : (21, 22) [Type: tuple<i32, i16>] +// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$<tuple$<i32,i16>,i32>] +// cdb-check:[...][0] : (21, 22) [Type: tuple$<i32,i16>] // cdb-check:[...][1] : 23 [Type: [...]] // cdb-command:dx padding_at_end2.__0,d -// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple<i32, i16>] +// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$<i32,i16>] // cdb-check:[...][0] : 21 [Type: [...]] // cdb-check:[...][1] : 22 [Type: [...]] diff --git a/src/test/debuginfo/type-names.cdb.js b/src/test/debuginfo/type-names.cdb.js new file mode 100644 index 00000000000..8f8b20bfaeb --- /dev/null +++ b/src/test/debuginfo/type-names.cdb.js @@ -0,0 +1,17 @@ +// Helper functions for running the type-names.rs test under CDB + +// CDB exposes an "object model" via JavaScript that allows you to inspect debugging info - in this +// case we want to ask the object model for the return and parameter types for a local variable +// that is a function pointer to make sure that we are emitting the function pointer type in such a +// way that CDB understands how to parse it. + +"use strict"; + +function getFunctionDetails(name) +{ + var localVariable = host.currentThread.Stack.Frames[0].LocalVariables[name]; + var functionPointerType = localVariable.targetType.genericArguments[0]; + var functionType = functionPointerType.baseType; + host.diagnostics.debugLog("Return Type: ", functionType.functionReturnType, "\n"); + host.diagnostics.debugLog("Parameter Types: ", functionType.functionParameterTypes, "\n"); +} diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index cc4a4476d16..d1f322fa76c 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -1,208 +1,268 @@ // ignore-lldb -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 + +// GDB changed the way that it formatted Foreign types +// min-gdb-version: 9.2 // compile-flags:-g +// === GDB TESTS =================================================================================== + // gdb-command:run // STRUCTS // gdb-command:whatis simple_struct -// gdbg-check:type = struct Struct1 -// gdbr-check:type = type_names::Struct1 +// gdb-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdbg-check:type = struct GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3> -// gdbr-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3> +// gdb-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3> // gdb-command:whatis generic_struct2 -// gdbg-check:type = struct GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize> -// gdbr-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize> +// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize> // gdb-command:whatis mod_struct -// gdbg-check:type = struct Struct2 -// gdbr-check:type = type_names::mod1::Struct2 +// gdb-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdbg-check:type = union Enum2 -// gdbr-check:type = type_names::mod1::Enum2 +// gdb-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdbg-check:type = union Enum3<type_names::mod1::Struct2> -// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> +// gdb-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdbg-check:type = union Enum3<type_names::Struct1> -// gdbr-check:type = type_names::mod1::mod2::Enum3<type_names::Struct1> +// gdb-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>) -// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>) +// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>) // gdb-command:whatis tuple2 -// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) -// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdb-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdbg-check:type = struct (alloc::boxed::Box<f32>, i32) -// gdbr-check:type = (alloc::boxed::Box<f32>, i32) +// gdb-check:type = (alloc::boxed::Box<f32, alloc::alloc::Global>, i32) // gdb-command:whatis box2 -// gdbg-check:type = struct (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32) -// gdbr-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>>, i32) +// gdb-check:type = (alloc::boxed::Box<type_names::mod1::mod2::Enum3<f32>, alloc::alloc::Global>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdbg-check:type = struct (&type_names::Struct1, i32) -// gdbr-check:type = (&type_names::Struct1, i32) +// gdb-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdbg-check:type = struct (&type_names::GenericStruct<char, type_names::Struct1>, i32) -// gdbr-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32) +// gdb-check:type = (&type_names::GenericStruct<char, type_names::Struct1>, i32) // gdb-command:whatis mut_ref1 -// gdbg-check:type = struct (&mut type_names::Struct1, i32) -// gdbr-check:type = (&mut type_names::Struct1, i32) +// gdb-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdbg-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32) -// gdbr-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32) +// gdb-check:type = (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdbg-check:type = struct (*mut type_names::Struct1, isize) -// gdbr-check:type = (*mut type_names::Struct1, isize) +// gdb-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdbg-check:type = struct (*mut isize, isize) -// gdbr-check:type = (*mut isize, isize) +// gdb-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) -// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) +// gdb-check:type = (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) // gdb-command:whatis const_ptr1 -// gdbg-check:type = struct (*const type_names::Struct1, isize) -// gdbr-check:type = (*const type_names::Struct1, isize) +// gdb-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdbg-check:type = struct (*const isize, isize) -// gdbr-check:type = (*const isize, isize) +// gdb-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) -// gdbr-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) +// gdb-check:type = (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdbg-check:type = struct ([type_names::Struct1; 3], i16) -// gdbr-check:type = ([type_names::Struct1; 3], i16) +// gdb-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdbg-check:type = struct ([usize; 3], i16) -// gdbr-check:type = ([usize; 3], i16) +// gdb-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdbg-check:type = struct &[usize] -// gdbr-check:type = &[usize] +// gdb-check:type = &[usize] // gdb-command:whatis slice2 -// gdbg-check:type = struct &[type_names::mod1::Enum2] -// gdbr-check:type = &[type_names::mod1::Enum2] +// gdb-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdbg-check:type = struct Box<Trait1> -// gdbr-check:type = type_names::Box<Trait1> +// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait1, alloc::alloc::Global> // gdb-command:whatis ref_trait -// gdbg-check:type = struct &Trait1 -// gdbr-check:type = type_names::&Trait1 +// gdb-check:type = &dyn type_names::Trait1 // gdb-command:whatis mut_ref_trait -// gdbg-check:type = struct &mut Trait1 -// gdbr-check:type = type_names::&mut Trait1 +// gdb-check:type = &mut dyn type_names::Trait1 // gdb-command:whatis generic_box_trait -// gdbg-check:type = struct Box<Trait2<i32, type_names::mod1::Struct2>> -// gdbr-check:type = type_names::Box<Trait2<i32, type_names::mod1::Struct2>> +// gdb-check:type = alloc::boxed::Box<dyn type_names::Trait2<i32, type_names::mod1::Struct2>, alloc::alloc::Global> // gdb-command:whatis generic_ref_trait -// gdbg-check:type = struct &Trait2<type_names::Struct1, type_names::Struct1> -// gdbr-check:type = type_names::&Trait2<type_names::Struct1, type_names::Struct1> +// gdb-check:type = &dyn type_names::Trait2<type_names::Struct1, type_names::Struct1> // gdb-command:whatis generic_mut_ref_trait -// gdbg-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>> -// gdbr-check:type = type_names::&mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>> +// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>> + +// gdb-command:whatis no_principal_trait +// gdb-check:type = alloc::boxed::Box<dyn core::marker::Send + core::marker::Sync, alloc::alloc::Global> // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdbg-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize) -// gdbr-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdb-check:type = (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdbg-check:type = struct (extern "C" fn(isize), usize) -// gdbr-check:type = (extern "C" fn(isize), usize) +// gdb-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdbg-check:type = struct (unsafe fn(core::result::Result<char, f64>), usize) -// gdbr-check:type = (unsafe fn(core::result::Result<char, f64>), usize) - -// gdb-command:whatis extern_stdcall_fn -// gdbg-check:type = struct (extern "stdcall" fn(), usize) -// gdbr-check:type = (extern "stdcall" fn(), usize) +// gdb-check:type = (unsafe fn(core::result::Result<char, f64>), usize) // gdb-command:whatis rust_fn_with_return_value -// gdbg-check:type = struct (fn(f64) -> usize, usize) -// gdbr-check:type = (fn(f64) -> usize, usize) +// gdb-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) -// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) +// gdb-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize) -// gdbr-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize) - -// gdb-command:whatis extern_stdcall_fn_with_return_value -// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize) -// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box<isize>) -> usize, usize) +// gdb-check:type = (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize) // gdb-command:whatis generic_function_int -// gdbg-check:type = struct (fn(isize) -> isize, usize) -// gdbr-check:type = (fn(isize) -> isize, usize) +// gdb-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) -// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdb-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) -// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdb-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#0}, usize) // gdb-command:whatis closure2 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#1}, usize) + +// FOREIGN TYPES +// gdb-command:whatis foreign1 +// gdb-check:type = *mut ForeignType1 + +// gdb-command:whatis foreign2 +// gdb-check:type = *mut ForeignType2 + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// STRUCTS +// 0-sized structs appear to be optimized away in some cases, so only check the structs that do +// actually appear. +// cdb-command:dv /t *_struct +// cdb-check:struct type_names::GenericStruct<enum$<type_names::mod1::Enum2>, f64> mut_generic_struct = [...] + +// ENUMS +// cdb-command:dv /t *_enum_* +// cdb-check:union enum$<type_names::Enum1> simple_enum_1 = [...] +// cdb-check:union enum$<type_names::Enum1> simple_enum_2 = [...] +// cdb-check:type_names::mod1::Enum2 simple_enum_3 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_1 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_2 = [...] + +// TUPLES +// cdb-command:dv /t tuple* +// cdb-check:struct tuple$<u32,type_names::Struct1,enum$<type_names::mod1::mod2::Enum3<type_names::mod1::Struct2> > > tuple1 = [...] +// cdb-check:struct tuple$<tuple$<type_names::Struct1,type_names::mod1::mod2::Struct3>,enum$<type_names::mod1::Enum2>,char> tuple2 = [...] + +// BOX +// cdb-command:dv /t box* +// cdb-check:struct tuple$<alloc::boxed::Box<f32, alloc::alloc::Global>,i32> box1 = [...] +// cdb-check:struct tuple$<alloc::boxed::Box<enum$<type_names::mod1::mod2::Enum3<f32> >, alloc::alloc::Global>,i32> box2 = [...] + +// REFERENCES +// cdb-command:dv /t *ref* +// cdb-check:struct tuple$<ref$<type_names::Struct1>,i32> ref1 = [...] +// cdb-check:struct tuple$<ref$<type_names::GenericStruct<char, type_names::Struct1> >,i32> ref2 = [...] +// cdb-check:struct tuple$<ref_mut$<type_names::Struct1>,i32> mut_ref1 = [...] +// cdb-check:struct tuple$<ref_mut$<type_names::GenericStruct<enum$<type_names::mod1::Enum2>, f64> >,i32> mut_ref2 = [...] + +// RAW POINTERS +// cdb-command:dv /t *_ptr* +// cdb-check:struct tuple$<ptr_mut$<type_names::Struct1>,isize> mut_ptr1 = [...] +// cdb-check:struct tuple$<ptr_mut$<isize>,isize> mut_ptr2 = [...] +// cdb-check:struct tuple$<ptr_mut$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> mut_ptr3 = [...] +// cdb-check:struct tuple$<ptr_const$<type_names::Struct1>,isize> const_ptr1 = [...] +// cdb-check:struct tuple$<ptr_const$<isize>,isize> const_ptr2 = [...] +// cdb-check:struct tuple$<ptr_const$<enum$<type_names::mod1::mod2::Enum3<type_names::Struct1> > >,isize> const_ptr3 = [...] + +// VECTORS +// cdb-command:dv /t *vec* +// cdb-check:struct tuple$<array$<type_names::Struct1,3>,i16> fixed_size_vec1 = [...] +// cdb-check:struct tuple$<array$<usize,3>,i16> fixed_size_vec2 = [...] +// cdb-check:struct alloc::vec::Vec<usize, alloc::alloc::Global> vec1 = [...] +// cdb-check:struct alloc::vec::Vec<enum$<type_names::mod1::Enum2>, alloc::alloc::Global> vec2 = [...] +// cdb-command:dv /t slice* +// cdb-check:struct slice$<usize> slice1 = [...] +// cdb-check:struct slice$<enum$<type_names::mod1::Enum2> > slice2 = [...] + +// TRAITS +// cdb-command:dv /t *_trait +// cdb-check:struct ref_mut$<dyn$<type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize> > > > generic_mut_ref_trait = [...] +// cdb-check:struct ref$<dyn$<type_names::Trait2<type_names::Struct1, type_names::Struct1> > > generic_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait2<i32, type_names::mod1::Struct2> >, alloc::alloc::Global> generic_box_trait = [...] +// cdb-check:struct alloc::boxed::Box<dyn$<type_names::Trait1>, alloc::alloc::Global> box_trait = [...] +// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...] +// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...] +// cdb-check:struct ref$<dyn$<type_names::Trait3> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3> > + +// BARE FUNCTIONS +// cdb-command:dv /t *_fn* +// cdb-check:struct tuple$<type_names::mod1::Struct2 (*)(type_names::GenericStruct<u16, u8>),usize> unsafe_fn_with_return_value = [...] +// cdb-check:struct tuple$<type_names::Struct1 (*)(),usize> extern_c_fn_with_return_value = [...] +// cdb-check:struct tuple$<usize (*)(f64),usize> rust_fn_with_return_value = [...] +// cdb-check:struct tuple$<void (*)(enum$<core::result::Result<char, f64> >),usize> unsafe_fn = [...] +// cdb-check:struct tuple$<void (*)(isize),usize> extern_c_fn = [...] +// cdb-check:struct tuple$<void (*)(enum$<core::option::Option<isize> >, enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some>),usize> rust_fn = [...] +// cdb-command:dv /t *_function* +// cdb-check:struct tuple$<isize (*)(ptr_const$<u8>, ...),usize> variadic_function = [...] +// cdb-check:struct tuple$<type_names::mod1::mod2::Struct3 (*)(type_names::mod1::mod2::Struct3),usize> generic_function_struct3 = [...] +// cdb-check:struct tuple$<isize (*)(isize),usize> generic_function_int = [...] +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn") +// cdb-check:Return Type: void +// cdb-check:Parameter Types: enum$<core::option::Option<isize> >,enum$<core::option::Option<ref$<type_names::mod1::Struct2> >, 1, [...], Some> +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value") +// cdb-check:Return Type: usize +// cdb-check:Parameter Types: f64 +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("extern_c_fn_with_return_value") +// cdb-check:Return Type: type_names::Struct1 +// cdb-check:Parameter Types: + +// CLOSURES +// cdb-command:dv /t closure* +// cdb-check:struct tuple$<type_names::main::closure$1,usize> closure2 = [...] +// cdb-check:struct tuple$<type_names::main::closure$0,usize> closure1 = [...] + +// FOREIGN TYPES +// cdb-command:dv /t foreign* +// cdb-check:struct ForeignType2 * foreign2 = [...] +// cdb-check:struct ForeignType1 * foreign1 = [...] #![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] +#![feature(extern_types)] use self::Enum1::{Variant1, Variant2}; use std::marker::PhantomData; @@ -216,6 +276,8 @@ enum Enum1 { Variant2(isize), } +extern { type ForeignType1; } + mod mod1 { pub use self::Enum2::{Variant1, Variant2}; pub struct Struct2; @@ -234,6 +296,8 @@ mod mod1 { Variant2(T), } } + + extern { pub type ForeignType2; } } trait Trait1 { @@ -242,14 +306,20 @@ trait Trait1 { trait Trait2<T1, T2> { fn dummy(&self, _: T1, _: T2) {} } +trait Trait3 { + type AssocType; + fn dummy(&self) {} +} impl Trait1 for isize {} impl<T1, T2> Trait2<T1, T2> for isize {} +impl Trait3 for isize { + type AssocType = isize; +} fn rust_fn(_: Option<isize>, _: Option<&mod1::Struct2>) {} extern "C" fn extern_c_fn(_: isize) {} unsafe fn unsafe_fn(_: Result<char, f64>) {} -extern "stdcall" fn extern_stdcall_fn() {} fn rust_fn_with_return_value(_: f64) -> usize { 4 @@ -260,9 +330,6 @@ extern "C" fn extern_c_fn_with_return_value() -> Struct1 { unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 { mod1::Struct2 } -extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize { - 0 -} fn generic_function<T>(x: T) -> T { x @@ -333,28 +400,28 @@ fn main() { let slice2 = &*vec2; // Trait Objects - let box_trait = (box 0_isize) as Box<Trait1>; - let ref_trait = &0_isize as &Trait1; + let box_trait = (box 0_isize) as Box<dyn Trait1>; + let ref_trait = &0_isize as &dyn Trait1; let mut mut_int1 = 0_isize; - let mut_ref_trait = (&mut mut_int1) as &mut Trait1; + let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1; + let no_principal_trait = (box 0_isize) as Box<dyn Send + Sync>; + let has_associated_type_trait = &0_isize as &dyn Trait3<AssocType = isize>; - let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>; - let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>; + let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>; + let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>; let mut generic_mut_ref_trait_impl = 0_isize; let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) - as &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>; + as &mut dyn Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>; // Bare Functions let rust_fn = (rust_fn, 0_usize); let extern_c_fn = (extern_c_fn, 0_usize); let unsafe_fn = (unsafe_fn, 0_usize); - let extern_stdcall_fn = (extern_stdcall_fn, 0_usize); let rust_fn_with_return_value = (rust_fn_with_return_value, 0_usize); let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0_usize); let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0_usize); - let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize); let generic_function_int = (generic_function::<isize>, 0_usize); let generic_function_struct3 = (generic_function::<mod1::mod2::Struct3>, 0_usize); @@ -370,6 +437,10 @@ fn main() { let closure1 = (|x: isize| {}, 0_usize); let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize); + // Foreign Types + let foreign1 = unsafe{ 0 as *const ForeignType1 }; + let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 }; + zzz(); // #break } diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 695cdc4f41f..a2778fc6090 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -108,7 +108,7 @@ // cdb-command: dx closure_local // cdb-check:closure_local : 8 [Type: [...]] // cdb-command: dx nested_closure -// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::{{closure}}::closure-0] +// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::closure$0::closure$0] // cdb-command: g diff --git a/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile new file mode 100644 index 00000000000..bc4562bef3a --- /dev/null +++ b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse diff --git a/src/test/run-make/track-path-dep-info/Makefile b/src/test/run-make/track-path-dep-info/Makefile new file mode 100644 index 00000000000..465d3744789 --- /dev/null +++ b/src/test/run-make/track-path-dep-info/Makefile @@ -0,0 +1,13 @@ +-include ../../run-make-fulldeps/tools.mk + +# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC` +# instead of hardcoding them everywhere they're needed. +ifeq ($(IS_MUSL_HOST),1) +ADDITIONAL_ARGS := $(RUSTFLAGS) +endif + +all: + # Proc macro + $(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs + EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs + $(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d diff --git a/src/test/run-make/track-path-dep-info/emojis.txt b/src/test/run-make/track-path-dep-info/emojis.txt new file mode 100644 index 00000000000..e1a728461f3 --- /dev/null +++ b/src/test/run-make/track-path-dep-info/emojis.txt @@ -0,0 +1 @@ +👾👾👾👾👾👾 diff --git a/src/test/run-make/track-path-dep-info/macro_def.rs b/src/test/run-make/track-path-dep-info/macro_def.rs new file mode 100644 index 00000000000..8777ce21f8b --- /dev/null +++ b/src/test/run-make/track-path-dep-info/macro_def.rs @@ -0,0 +1,11 @@ +#![feature(track_path)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn access_tracked_paths(_: TokenStream) -> TokenStream { + tracked_path::path("emojis.txt"); + TokenStream::new() +} diff --git a/src/test/run-make/track-path-dep-info/macro_use.rs b/src/test/run-make/track-path-dep-info/macro_use.rs new file mode 100644 index 00000000000..3c49fd05dd9 --- /dev/null +++ b/src/test/run-make/track-path-dep-info/macro_use.rs @@ -0,0 +1,6 @@ +#[macro_use] +extern crate macro_def; + +access_tracked_paths!(); + +fn main() {} diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml index 80618112103..84e898660fa 100644 --- a/src/test/rustdoc-gui/font-weight.goml +++ b/src/test/rustdoc-gui/font-weight.goml @@ -5,3 +5,16 @@ assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']" assert-css: ("#method\.a_method > code", {"font-weight": "600"}) assert-css: ("#associatedtype\.X > code", {"font-weight": "600"}) assert-css: ("#associatedconstant\.Y > code", {"font-weight": "600"}) + +goto: file://|DOC_PATH|/test_docs/type.SomeType.html +assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL) + +goto: file://|DOC_PATH|/test_docs/struct.Foo.html +assert-css: (".impl-items .method", {"font-weight": "600"}, ALL) + +goto: file://|DOC_PATH|/lib2/trait.Trait.html +assert-count: (".methods .type", 1) +assert-css: (".methods .type", {"font-weight": "600"}) +assert-count: (".methods .constant", 1) +assert-css: (".methods .constant", {"font-weight": "600"}) +assert-css: (".methods .method", {"font-weight": "600"}) diff --git a/src/test/rustdoc-gui/label-next-to-symbol.goml b/src/test/rustdoc-gui/label-next-to-symbol.goml new file mode 100644 index 00000000000..4fef4e655fd --- /dev/null +++ b/src/test/rustdoc-gui/label-next-to-symbol.goml @@ -0,0 +1,36 @@ +// These tests verify that labels like "UNIX" and "Deprecated" stay on the same line as their symbol. +// It also verifies the staggered layout on mobile. +goto: file://|DOC_PATH|/test_docs/index.html + +// Desktop view +size: (1080, 600) +assert: (".stab.deprecated") +assert: (".stab.portability") + +// make sure that deprecated and portability are different colours +assert-css: (".item-table .item-left .stab.deprecated", { "background-color": "rgb(255, 196, 196)" }) +assert-css: (".item-table .item-left .stab.portability", { "background-color": "rgb(243, 223, 255)" }) + +// table like view +assert-css: (".item-right.docblock-short", { "padding-left": "0px" }) +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 2}) +compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y")) + +// Ensure no wrap +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 2}) +// compare parent elements +compare-elements-position: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y")) + + +// Mobile view +size: (600, 600) +// staggered layout with 2em spacing +assert-css: (".item-right.docblock-short", { "padding-left": "32px" }) +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 1}) +compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y")) + +// Ensure wrap +compare-elements-position-near-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 12}) +// compare parent elements +compare-elements-position-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y")) +compare-elements-position-false: (".item-left .stab.deprecated", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", ("y")) diff --git a/src/test/rustdoc-gui/src/lib.rs b/src/test/rustdoc-gui/src/lib.rs index 5141b6d1920..3e753cb4de8 100644 --- a/src/test/rustdoc-gui/src/lib.rs +++ b/src/test/rustdoc-gui/src/lib.rs @@ -3,6 +3,7 @@ #![crate_name = "test_docs"] #![feature(doc_keyword)] +#![feature(doc_cfg)] use std::fmt; @@ -90,6 +91,11 @@ pub trait AnotherOne { /// ``` pub fn check_list_code_block() {} +/// a thing with a label +#[deprecated(since = "1.0.0", note = "text why this deprecated")] +#[doc(cfg(unix))] +pub fn replaced_function() {} + pub enum AnEnum { WithVariants { and: usize, sub: usize, variants: usize }, } diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2.rs index 6fa1b36b29b..77d384f3113 100644 --- a/src/test/rustdoc-gui/src/lib2.rs +++ b/src/test/rustdoc-gui/src/lib2.rs @@ -23,6 +23,8 @@ impl Foo { pub trait Trait { type X; const Y: u32; + + fn foo() {} } impl Trait for Foo { diff --git a/src/test/rustdoc-gui/type-weight.rs b/src/test/rustdoc-gui/type-weight.rs deleted file mode 100644 index 8b6518e7f31..00000000000 --- a/src/test/rustdoc-gui/type-weight.rs +++ /dev/null @@ -1,2 +0,0 @@ -goto: file://|DOC_PATH|/test_docs/type.SomeType.html -assert-all: (".top-block .docblock p", {"font-weight": "400"}) diff --git a/src/test/rustdoc-js-std/alias-4.js b/src/test/rustdoc-js-std/alias-4.js new file mode 100644 index 00000000000..bf2bb4d2981 --- /dev/null +++ b/src/test/rustdoc-js-std/alias-4.js @@ -0,0 +1,7 @@ +const QUERY = '<'; + +const EXPECTED = { + 'others': [ + { 'name': 'Ord' }, + ], +}; diff --git a/src/test/rustdoc-js-std/typed-query.js b/src/test/rustdoc-js-std/typed-query.js new file mode 100644 index 00000000000..f656aa72986 --- /dev/null +++ b/src/test/rustdoc-js-std/typed-query.js @@ -0,0 +1,12 @@ +// exact-check + +const QUERY = 'macro:print'; + +const EXPECTED = { + 'others': [ + { 'path': 'std', 'name': 'print' }, + { 'path': 'std', 'name': 'eprint' }, + { 'path': 'std', 'name': 'println' }, + { 'path': 'std', 'name': 'eprintln' }, + ], +}; diff --git a/src/test/rustdoc-js/generics-trait.js b/src/test/rustdoc-js/generics-trait.js new file mode 100644 index 00000000000..7876622435b --- /dev/null +++ b/src/test/rustdoc-js/generics-trait.js @@ -0,0 +1,23 @@ +const QUERY = [ + 'Result<SomeTrait>', + 'OtherThingxxxxxxxx', +]; + +const EXPECTED = [ + { + 'in_args': [ + { 'path': 'generics_trait', 'name': 'beta' }, + ], + 'returned': [ + { 'path': 'generics_trait', 'name': 'bet' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics_trait', 'name': 'alpha' }, + ], + 'returned': [ + { 'path': 'generics_trait', 'name': 'alef' }, + ], + }, +]; diff --git a/src/test/rustdoc-js/generics-trait.rs b/src/test/rustdoc-js/generics-trait.rs new file mode 100644 index 00000000000..20db117ccd5 --- /dev/null +++ b/src/test/rustdoc-js/generics-trait.rs @@ -0,0 +1,8 @@ +pub trait SomeTrait {} +pub trait OtherThingxxxxxxxx {} + +pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> { loop {} } +pub fn bet<T: SomeTrait>() -> Result<T, ()> { loop {} } + +pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) { loop {} } +pub fn beta<T: SomeTrait>(_param: Result<T, ()>) { loop {} } diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js new file mode 100644 index 00000000000..49a80ae2360 --- /dev/null +++ b/src/test/rustdoc-js/generics.js @@ -0,0 +1,44 @@ +// exact-check + +const QUERY = [ + '"R<P>"', + '"P"', + 'P', + '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"', +]; + +const EXPECTED = [ + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'others': [ + { 'path': 'generics', 'name': 'P' }, + ], + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics', 'name': 'extracreditlabhomework' }, + ], + 'returned': [], + }, +]; diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs new file mode 100644 index 00000000000..a0dc086e9f9 --- /dev/null +++ b/src/test/rustdoc-js/generics.rs @@ -0,0 +1,21 @@ +pub struct P; +pub struct Q; +pub struct R<T>(T); + +// returns test +pub fn alef() -> R<P> { loop {} } +pub fn bet() -> R<Q> { loop {} } + +// in_args test +pub fn alpha(_x: R<P>) { loop {} } +pub fn beta(_x: R<Q>) { loop {} } + +// test case with multiple appearances of the same type +pub struct ExtraCreditStructMulti<T, U> { t: T, u: U } +pub struct ExtraCreditInnerMulti {} +pub fn extracreditlabhomework( + _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti> +) { loop {} } +pub fn redherringmatchforextracredit( + _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()> +) { loop {} } diff --git a/src/test/rustdoc-ui/auxiliary/panic-item.rs b/src/test/rustdoc-ui/auxiliary/panic-item.rs deleted file mode 100644 index 17b26850d4d..00000000000 --- a/src/test/rustdoc-ui/auxiliary/panic-item.rs +++ /dev/null @@ -1,17 +0,0 @@ -// no-prefer-dynamic -#![crate_type = "lib"] -#![no_std] -#![feature(lang_items)] - -use core::panic::PanicInfo; -use core::sync::atomic::{self, Ordering}; - -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop { - atomic::compiler_fence(Ordering::SeqCst); - } -} - -#[lang = "eh_personality"] -fn foo() {} diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.rs b/src/test/rustdoc-ui/renamed-lint-still-applies.rs index 05a32d3cc31..a4d3a4b4971 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.rs +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.rs @@ -1,7 +1,6 @@ // compile-args: --crate-type lib #![deny(broken_intra_doc_links)] -// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the -// stable channel. +//~^ WARNING renamed to `rustdoc::broken_intra_doc_links` //! [x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr index 3040cad532c..8e2a2cdd759 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr @@ -1,13 +1,19 @@ +warning: lint `broken_intra_doc_links` has been renamed to `rustdoc::broken_intra_doc_links` + --> $DIR/renamed-lint-still-applies.rs:2:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` - --> $DIR/renamed-lint-still-applies.rs:8:9 + --> $DIR/renamed-lint-still-applies.rs:7:9 | LL | #![deny(rustdoc::non_autolinks)] | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` - | - = note: `#[warn(renamed_and_removed_lints)]` on by default error: unresolved link to `x` - --> $DIR/renamed-lint-still-applies.rs:5:6 + --> $DIR/renamed-lint-still-applies.rs:4:6 | LL | //! [x] | ^ no item named `x` in scope @@ -17,21 +23,20 @@ note: the lint level is defined here | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(broken_intra_doc_links)]` = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: this URL is not a hyperlink - --> $DIR/renamed-lint-still-applies.rs:10:5 + --> $DIR/renamed-lint-still-applies.rs:9:5 | LL | //! http://example.com | ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.com>` | note: the lint level is defined here - --> $DIR/renamed-lint-still-applies.rs:8:9 + --> $DIR/renamed-lint-still-applies.rs:7:9 | LL | #![deny(rustdoc::non_autolinks)] | ^^^^^^^^^^^^^^^^^^^^^^ = note: bare URLs are not automatically turned into clickable links -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs index 9096cce1276..ddf03dd079f 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.rs +++ b/src/test/rustdoc-ui/unknown-renamed-lints.rs @@ -14,8 +14,7 @@ //~^ ERROR renamed to `rustdoc::bare_urls` #![deny(private_doc_tests)] -// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the -// stable channel. +//~^ ERROR renamed to `rustdoc::private_doc_tests` #![deny(rustdoc)] //~^ ERROR removed: use `rustdoc::all` instead diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr index 51e06821cf7..ad814b82352 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.stderr +++ b/src/test/rustdoc-ui/unknown-renamed-lints.stderr @@ -40,19 +40,25 @@ error: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` LL | #![deny(rustdoc::non_autolinks)] | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` +error: lint `private_doc_tests` has been renamed to `rustdoc::private_doc_tests` + --> $DIR/unknown-renamed-lints.rs:16:9 + | +LL | #![deny(private_doc_tests)] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::private_doc_tests` + error: lint `rustdoc` has been removed: use `rustdoc::all` instead - --> $DIR/unknown-renamed-lints.rs:20:9 + --> $DIR/unknown-renamed-lints.rs:19:9 | LL | #![deny(rustdoc)] | ^^^^^^^ error: unknown lint: `rustdoc::intra_doc_link_resolution_failure` - --> $DIR/unknown-renamed-lints.rs:24:9 + --> $DIR/unknown-renamed-lints.rs:23:9 | LL | #![deny(rustdoc::intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Compilation failed, aborting rustdoc -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/rustdoc-ui/unused-extern-crate.rs b/src/test/rustdoc-ui/unused-extern-crate.rs deleted file mode 100644 index f703a183790..00000000000 --- a/src/test/rustdoc-ui/unused-extern-crate.rs +++ /dev/null @@ -1,3 +0,0 @@ -// check-pass -// aux-crate:panic_item=panic-item.rs -// @has unused_extern_crate/index.html diff --git a/src/test/rustdoc/auxiliary/issue-66159-1.rs b/src/test/rustdoc/auxiliary/issue-66159-1.rs new file mode 100644 index 00000000000..2f3d069bd51 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-66159-1.rs @@ -0,0 +1,2 @@ +/// This will be referred to by the test docstring +pub struct Something; diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index 444624b034c..b3178da98ee 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -1,4 +1,4 @@ -// @has deprecated/index.html '//*[@class="item-right docblock-short"]/span[@class="stab deprecated"]' \ +// @has deprecated/index.html '//*[@class="item-left module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' // @has - '//*[@class="item-right docblock-short"]' 'Deprecated docs' diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index bd47ae4438d..416ffb60098 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -12,7 +12,7 @@ pub struct Portable; // @has doc_cfg/unix_only/index.html \ // '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ // 'This is supported on Unix only.' -// @matches - '//*[@class="item-right docblock-short"]//*[@class="stab portability"]' '\AARM\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(unix))] pub mod unix_only { @@ -42,7 +42,7 @@ pub mod unix_only { // @has doc_cfg/wasi_only/index.html \ // '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ // 'This is supported on WASI only.' -// @matches - '//*[@class="item-right docblock-short"]//*[@class="stab portability"]' '\AWebAssembly\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(target_os = "wasi"))] pub mod wasi_only { @@ -74,7 +74,7 @@ pub mod wasi_only { // the portability header is different on the module view versus the full view // @has doc_cfg/index.html -// @matches - '//*[@class="item-right docblock-short"]//*[@class="stab portability"]' '\Aavx\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\Aavx\Z' // @has doc_cfg/fn.uses_target_feature.html // @has - '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index e3241a8746e..886ec675030 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -2,13 +2,14 @@ #![feature(doc_cfg)] // @has 'foo/index.html' -// @matches '-' '//*[@class="item-right docblock-short"]//*[@class="stab portability"]' '^sync$' -// @has '-' '//*[@class="item-right docblock-short"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' +// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$' +// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' // @has 'foo/struct.Foo.html' // @has '-' '//*[@class="stab portability"]' 'sync' #[doc(cfg(feature = "sync"))] #[doc(cfg(feature = "sync"))] +/// my feature sync struct pub struct Foo; // @has 'foo/bar/index.html' diff --git a/src/test/rustdoc/inline_cross/macros.rs b/src/test/rustdoc/inline_cross/macros.rs index 601797fd64c..9cb933c177b 100644 --- a/src/test/rustdoc/inline_cross/macros.rs +++ b/src/test/rustdoc/inline_cross/macros.rs @@ -7,8 +7,10 @@ extern crate macros; -// @has foo/index.html '//*[@class="item-right docblock-short"]/span[@class="stab deprecated"]' Deprecated -// @has - '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]' Experimental +// @has foo/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ +// Deprecated +// @has - '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \ +// Experimental // @has foo/macro.my_macro.html // @has - '//*[@class="docblock"]' 'docs for my_macro' diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 604451eb7e8..4e92ae49a20 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -3,9 +3,9 @@ #![unstable(feature="test", issue = "32374")] -// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/span[@class="stab deprecated"]' \ +// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' -// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]' \ +// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \ // 'Experimental' // @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs' diff --git a/src/test/rustdoc/issue-66159.rs b/src/test/rustdoc/issue-66159.rs new file mode 100644 index 00000000000..003d079a470 --- /dev/null +++ b/src/test/rustdoc/issue-66159.rs @@ -0,0 +1,10 @@ +// aux-crate:priv:issue_66159_1=issue-66159-1.rs +// compile-flags:-Z unstable-options + +// The issue was an ICE which meant that we never actually generated the docs +// so if we have generated the docs, we're okay. +// Since we don't generate the docs for the auxiliary files, we can't actually +// verify that the struct is linked correctly. + +// @has issue_66159/index.html +//! [issue_66159_1::Something] diff --git a/src/test/ui/issues/issue-82869.rs b/src/test/ui/asm/issue-82869.rs index a8e688cbe1f..a8e688cbe1f 100644 --- a/src/test/ui/issues/issue-82869.rs +++ b/src/test/ui/asm/issue-82869.rs diff --git a/src/test/ui/issues/issue-82869.stderr b/src/test/ui/asm/issue-82869.stderr index d05714ea6f2..d05714ea6f2 100644 --- a/src/test/ui/issues/issue-82869.stderr +++ b/src/test/ui/asm/issue-82869.stderr diff --git a/src/test/ui/issues/issue-20005.rs b/src/test/ui/associated-types/issue-20005.rs index 36350bff100..36350bff100 100644 --- a/src/test/ui/issues/issue-20005.rs +++ b/src/test/ui/associated-types/issue-20005.rs diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/associated-types/issue-20005.stderr index bc414044f78..bc414044f78 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/associated-types/issue-20005.stderr diff --git a/src/test/ui/async-await/issue-84841.rs b/src/test/ui/async-await/issue-84841.rs new file mode 100644 index 00000000000..ba3a1617b9c --- /dev/null +++ b/src/test/ui/async-await/issue-84841.rs @@ -0,0 +1,16 @@ +// edition:2018 + +fn main() { + +} + +async fn foo() { + // Adding an .await here avoids the ICE + test()?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be used in an async function that returns +} + +// Removing the const generic parameter here avoids the ICE +async fn test<const N: usize>() { +} diff --git a/src/test/ui/async-await/issue-84841.stderr b/src/test/ui/async-await/issue-84841.stderr new file mode 100644 index 00000000000..170dcf581ed --- /dev/null +++ b/src/test/ui/async-await/issue-84841.stderr @@ -0,0 +1,28 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-84841.rs:9:5 + | +LL | test()?; + | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | + = help: the trait `Try` is not implemented for `impl Future` + = note: required by `branch` + +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/issue-84841.rs:9:11 + | +LL | async fn foo() { + | ________________- +LL | | // Adding an .await here avoids the ICE +LL | | test()?; + | | ^ cannot use the `?` operator in an async function that returns `()` +LL | | +LL | | +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + = note: required by `from_residual` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/fsu-moves-and-copies.rs b/src/test/ui/borrowck/fsu-moves-and-copies.rs index 6a0b4ed17b9..6a0b4ed17b9 100644 --- a/src/test/ui/fsu-moves-and-copies.rs +++ b/src/test/ui/borrowck/fsu-moves-and-copies.rs diff --git a/src/test/ui/cast/fat-ptr-cast-rpass.rs b/src/test/ui/cast/fat-ptr-cast-rpass.rs index 9fa2255e1b3..f5747eb8b96 100644 --- a/src/test/ui/cast/fat-ptr-cast-rpass.rs +++ b/src/test/ui/cast/fat-ptr-cast-rpass.rs @@ -1,12 +1,6 @@ // run-pass -// Remove this file when `std::raw` is removed. -// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs -#![allow(deprecated)] -#![feature(raw)] - -use std::mem; -use std::raw; +#![feature(ptr_metadata)] trait Foo { fn foo(&self) {} @@ -31,13 +25,10 @@ fn main() { // And conversion to a void pointer/address for trait objects too. let a: *mut dyn Foo = &mut Bar; - let b = a as *mut (); + let b = a as *mut () as usize; let c = a as *const () as usize; - let d = unsafe { - let r: raw::TraitObject = mem::transmute(a); - r.data - }; + let d = a.to_raw_parts().0 as usize; assert_eq!(b, d); - assert_eq!(c, d as usize); + assert_eq!(c, d); } diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs index 131af6a10c8..7a4b21f0223 100644 --- a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs +++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 #![feature(rustc_attrs)] // Ensure that capture analysis results in arrays being completely captured. diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr index 2a350f30331..69ec53447b8 100644 --- a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr +++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/arrays-completely-captured.rs:11:17 + --> $DIR/arrays-completely-captured.rs:8:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let mut c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/arrays-completely-captured.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/arrays-completely-captured.rs:14:5 + --> $DIR/arrays-completely-captured.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing m[] -> MutBorrow - --> $DIR/arrays-completely-captured.rs:17:9 + --> $DIR/arrays-completely-captured.rs:14:9 | LL | m[0] += 10; | ^ error: Min Capture analysis includes: - --> $DIR/arrays-completely-captured.rs:14:5 + --> $DIR/arrays-completely-captured.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture m[] -> MutBorrow - --> $DIR/arrays-completely-captured.rs:17:9 + --> $DIR/arrays-completely-captured.rs:14:9 | LL | m[0] += 10; | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.rs b/src/test/ui/closures/2229_closure_analysis/by_value.rs index 27c8fb1363f..02a243e0506 100644 --- a/src/test/ui/closures/2229_closure_analysis/by_value.rs +++ b/src/test/ui/closures/2229_closure_analysis/by_value.rs @@ -1,11 +1,7 @@ +// edition:2021 + // Test that we handle derferences properly when only some of the captures are being moved with // `capture_disjoint_fields` enabled. - - -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] #[derive(Debug, Default)] diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/by_value.stderr index 944e4c40a78..7014ae6a5e6 100644 --- a/src/test/ui/closures/2229_closure_analysis/by_value.stderr +++ b/src/test/ui/closures/2229_closure_analysis/by_value.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/by_value.rs:22:13 + --> $DIR/by_value.rs:18:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by_value.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/by_value.rs:25:5 + --> $DIR/by_value.rs:21:5 | LL | / || { LL | | @@ -29,23 +20,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/by_value.rs:28:17 + --> $DIR/by_value.rs:24:17 | LL | let p = t.0.0; | ^^^^^ note: Capturing t[(0, 0)] -> ByValue - --> $DIR/by_value.rs:28:17 + --> $DIR/by_value.rs:24:17 | LL | let p = t.0.0; | ^^^^^ note: Capturing t[(1, 0)] -> ImmBorrow - --> $DIR/by_value.rs:32:29 + --> $DIR/by_value.rs:28:29 | LL | println!("{} {:?}", t.1, p); | ^^^ error: Min Capture analysis includes: - --> $DIR/by_value.rs:25:5 + --> $DIR/by_value.rs:21:5 | LL | / || { LL | | @@ -57,16 +48,16 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/by_value.rs:28:17 + --> $DIR/by_value.rs:24:17 | LL | let p = t.0.0; | ^^^^^ note: Min Capture t[(1, 0)] -> ImmBorrow - --> $DIR/by_value.rs:32:29 + --> $DIR/by_value.rs:28:29 | LL | println!("{} {:?}", t.1, p); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs index 4368c830e1c..dc53b31768e 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr index 09255343af0..fceafb9c84e 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-1.rs:17:13 + --> $DIR/capture-analysis-1.rs:15:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-1.rs:20:5 + --> $DIR/capture-analysis-1.rs:18:5 | LL | / || { LL | | @@ -29,28 +20,28 @@ LL | | }; | |_____^ | note: Capturing p[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:23:26 + --> $DIR/capture-analysis-1.rs:21:26 | LL | println!("{:?}", p); | ^ note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:26:26 + --> $DIR/capture-analysis-1.rs:24:26 | LL | println!("{:?}", p.x); | ^^^ note: Capturing q[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:29:26 + --> $DIR/capture-analysis-1.rs:27:26 | LL | println!("{:?}", q.x); | ^^^ note: Capturing q[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:31:26 + --> $DIR/capture-analysis-1.rs:29:26 | LL | println!("{:?}", q); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-1.rs:20:5 + --> $DIR/capture-analysis-1.rs:18:5 | LL | / || { LL | | @@ -62,16 +53,16 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:23:26 + --> $DIR/capture-analysis-1.rs:21:26 | LL | println!("{:?}", p); | ^ note: Min Capture q[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:31:26 + --> $DIR/capture-analysis-1.rs:29:26 | LL | println!("{:?}", q); | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs index ab7fce6a430..99d12f8d8f1 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr index 0e48d6b300b..cb44ca26652 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-2.rs:16:13 + --> $DIR/capture-analysis-2.rs:14:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-2.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-2.rs:19:5 + --> $DIR/capture-analysis-2.rs:17:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ByValue - --> $DIR/capture-analysis-2.rs:22:18 + --> $DIR/capture-analysis-2.rs:20:18 | LL | let _x = p.x; | ^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/capture-analysis-2.rs:25:26 + --> $DIR/capture-analysis-2.rs:23:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-2.rs:19:5 + --> $DIR/capture-analysis-2.rs:17:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ByValue - --> $DIR/capture-analysis-2.rs:22:18 + --> $DIR/capture-analysis-2.rs:20:18 | LL | let _x = p.x; | ^^^ p[] captured as ByValue here @@ -60,6 +51,6 @@ LL | let _x = p.x; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs index 817ade899e2..3f337097dbd 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr index 263e9ca56eb..71e7bdc354f 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-3.rs:21:13 + --> $DIR/capture-analysis-3.rs:19:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-3.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-3.rs:24:5 + --> $DIR/capture-analysis-3.rs:22:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0),(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:27:18 + --> $DIR/capture-analysis-3.rs:25:18 | LL | let _x = a.b.c; | ^^^^^ note: Capturing a[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-3.rs:30:26 + --> $DIR/capture-analysis-3.rs:28:26 | LL | println!("{:?}", a.b); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-3.rs:24:5 + --> $DIR/capture-analysis-3.rs:22:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:27:18 + --> $DIR/capture-analysis-3.rs:25:18 | LL | let _x = a.b.c; | ^^^^^ a[(0, 0)] captured as ByValue here @@ -60,6 +51,6 @@ LL | let _x = a.b.c; LL | println!("{:?}", a.b); | ^^^ a[(0, 0)] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs index e8401299b30..bc46ec99736 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr index f4605c1d51b..7e6e625bc7d 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-4.rs:21:13 + --> $DIR/capture-analysis-4.rs:19:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-4.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-4.rs:24:5 + --> $DIR/capture-analysis-4.rs:22:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:27:18 + --> $DIR/capture-analysis-4.rs:25:18 | LL | let _x = a.b; | ^^^ note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-4.rs:30:26 + --> $DIR/capture-analysis-4.rs:28:26 | LL | println!("{:?}", a.b.c); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-4.rs:24:5 + --> $DIR/capture-analysis-4.rs:22:5 | LL | / || { LL | | @@ -52,11 +43,11 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:27:18 + --> $DIR/capture-analysis-4.rs:25:18 | LL | let _x = a.b; | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs index ba495508537..6fd15155331 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr index 5fac6963afd..0f64ecf3a0c 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-struct.rs:17:13 + --> $DIR/capture-disjoint-field-struct.rs:13:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-struct.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:20:5 + --> $DIR/capture-disjoint-field-struct.rs:16:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-struct.rs:23:24 + --> $DIR/capture-disjoint-field-struct.rs:19:24 | LL | println!("{}", p.x); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:20:5 + --> $DIR/capture-disjoint-field-struct.rs:16:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-struct.rs:23:24 + --> $DIR/capture-disjoint-field-struct.rs:19:24 | LL | println!("{}", p.x); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs index c1693fbad79..8d3bb3262fb 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr index 1bfd63f2ace..a8ca9622a6a 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-tuple.rs:12:13 + --> $DIR/capture-disjoint-field-tuple.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:15:5 + --> $DIR/capture-disjoint-field-tuple.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-tuple.rs:18:24 + --> $DIR/capture-disjoint-field-tuple.rs:14:24 | LL | println!("{}", t.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:15:5 + --> $DIR/capture-disjoint-field-tuple.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-tuple.rs:18:24 + --> $DIR/capture-disjoint-field-tuple.rs:14:24 | LL | println!("{}", t.0); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs b/src/test/ui/closures/2229_closure_analysis/capture-enums.rs index 8fb2f7f16d6..322ae99b861 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-enums.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] enum Info { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr b/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr index ebe1dcb9884..8a6ba8444a8 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:18:13 + --> $DIR/capture-enums.rs:16:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:49:13 + --> $DIR/capture-enums.rs:47:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,17 +16,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-enums.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/capture-enums.rs:21:5 + --> $DIR/capture-enums.rs:19:5 | LL | / || { LL | | @@ -38,28 +29,28 @@ LL | | }; | |_____^ | note: Capturing point[] -> ImmBorrow - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing meta[] -> ImmBorrow - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ note: Capturing meta[(1, 1)] -> ByValue - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:21:5 + --> $DIR/capture-enums.rs:19:5 | LL | / || { LL | | @@ -71,18 +62,18 @@ LL | | }; | |_____^ | note: Min Capture point[] -> ByValue - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Min Capture meta[] -> ByValue - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: First Pass analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:50:5 | LL | / || { LL | | @@ -94,13 +85,13 @@ LL | | }; | |_____^ | note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:53:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:50:5 | LL | / || { LL | | @@ -112,11 +103,11 @@ LL | | }; | |_____^ | note: Min Capture point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:53:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs index f81866bb7e0..3341166e22b 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr index 863f1009131..29e1af0431e 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-struct.rs:36:13 + --> $DIR/deep-multilevel-struct.rs:34:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/deep-multilevel-struct.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/deep-multilevel-struct.rs:39:5 + --> $DIR/deep-multilevel-struct.rs:37:5 | LL | / || { LL | | @@ -29,23 +20,23 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/deep-multilevel-struct.rs:42:18 + --> $DIR/deep-multilevel-struct.rs:40:18 | LL | let x = &p.a.p.x; | ^^^^^^^ note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow - --> $DIR/deep-multilevel-struct.rs:44:9 + --> $DIR/deep-multilevel-struct.rs:42:9 | LL | p.b.q.y = 9; | ^^^^^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/deep-multilevel-struct.rs:47:26 + --> $DIR/deep-multilevel-struct.rs:45:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-struct.rs:39:5 + --> $DIR/deep-multilevel-struct.rs:37:5 | LL | / || { LL | | @@ -57,7 +48,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> MutBorrow - --> $DIR/deep-multilevel-struct.rs:44:9 + --> $DIR/deep-multilevel-struct.rs:42:9 | LL | p.b.q.y = 9; | ^^^^^^^ p[] captured as MutBorrow here @@ -65,6 +56,6 @@ LL | p.b.q.y = 9; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs index fb03a02efa0..34b0132f3cb 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr index 252db444732..e917516765c 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-tuple.rs:11:13 + --> $DIR/deep-multilevel-tuple.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/deep-multilevel-tuple.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/deep-multilevel-tuple.rs:14:5 + --> $DIR/deep-multilevel-tuple.rs:11:5 | LL | / || { LL | | @@ -29,23 +20,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/deep-multilevel-tuple.rs:17:18 + --> $DIR/deep-multilevel-tuple.rs:14:18 | LL | let x = &t.0.0.0; | ^^^^^^^ note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow - --> $DIR/deep-multilevel-tuple.rs:19:9 + --> $DIR/deep-multilevel-tuple.rs:16:9 | LL | t.1.1.1 = 9; | ^^^^^^^ note: Capturing t[] -> ImmBorrow - --> $DIR/deep-multilevel-tuple.rs:22:26 + --> $DIR/deep-multilevel-tuple.rs:19:26 | LL | println!("{:?}", t); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-tuple.rs:14:5 + --> $DIR/deep-multilevel-tuple.rs:11:5 | LL | / || { LL | | @@ -57,7 +48,7 @@ LL | | }; | |_____^ | note: Min Capture t[] -> MutBorrow - --> $DIR/deep-multilevel-tuple.rs:19:9 + --> $DIR/deep-multilevel-tuple.rs:16:9 | LL | t.1.1.1 = 9; | ^^^^^^^ t[] captured as MutBorrow here @@ -65,6 +56,6 @@ LL | t.1.1.1 = 9; LL | println!("{:?}", t); | ^ t[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs index 080ca0405b4..9918802334e 100644 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] // Test to ensure Index projections are handled properly during capture analysis diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr index 06ccc2d7a88..b53adb52481 100644 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:12:13 + --> $DIR/destructure_patterns.rs:10:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:38:13 + --> $DIR/destructure_patterns.rs:36:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:58:13 + --> $DIR/destructure_patterns.rs:56:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:15:5 + --> $DIR/destructure_patterns.rs:13:5 | LL | / || { LL | | @@ -47,13 +38,13 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 + --> $DIR/destructure_patterns.rs:16:29 | LL | let [a, b, .., e] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:15:5 + --> $DIR/destructure_patterns.rs:13:5 | LL | / || { LL | | @@ -65,13 +56,13 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 + --> $DIR/destructure_patterns.rs:16:29 | LL | let [a, b, .., e] = arr; | ^^^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:41:5 + --> $DIR/destructure_patterns.rs:39:5 | LL | / || { LL | | @@ -83,18 +74,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Capturing p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:41:5 + --> $DIR/destructure_patterns.rs:39:5 | LL | / || { LL | | @@ -106,18 +97,18 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Min Capture p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:61:5 + --> $DIR/destructure_patterns.rs:59:5 | LL | / || { LL | | @@ -129,23 +120,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:61:5 + --> $DIR/destructure_patterns.rs:59:5 | LL | / || { LL | | @@ -157,21 +148,21 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs index 0b94317fd71..93131b2ac4e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs @@ -1,7 +1,6 @@ -// Test that arrays are completely captured by closures by relying on the borrow check diagnostics +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// Test that arrays are completely captured by closures by relying on the borrow check diagnostics fn arrays_1() { let mut arr = [1, 2, 3, 4, 5]; diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr index 77e3e71bc61..a3f2f25e447 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/arrays.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:15:5 + --> $DIR/arrays.rs:14:5 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -22,7 +13,7 @@ LL | c(); | - borrow later used here error[E0503]: cannot use `arr[_]` because it was mutably borrowed - --> $DIR/arrays.rs:15:5 + --> $DIR/arrays.rs:14:5 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -36,7 +27,7 @@ LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:30:5 + --> $DIR/arrays.rs:29:5 | LL | let c = || { | -- borrow of `arr[_]` occurs here @@ -50,7 +41,7 @@ LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:44:5 + --> $DIR/arrays.rs:43:5 | LL | let c = || { | -- borrow of `arr[_]` occurs here @@ -64,7 +55,7 @@ LL | c(); | - borrow later used here error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:58:20 + --> $DIR/arrays.rs:57:20 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -78,7 +69,7 @@ LL | c(); | - borrow later used here error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:58:20 + --> $DIR/arrays.rs:57:20 | LL | let mut c = || { | -- mutable borrow occurs here @@ -92,7 +83,7 @@ LL | c(); | - mutable borrow later used here error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:74:24 + --> $DIR/arrays.rs:73:24 | LL | let mut c = || { | -- mutable borrow occurs here @@ -105,7 +96,7 @@ LL | println!("{:#?}", &arr[3..2]); LL | c(); | - mutable borrow later used here -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 7 previous errors Some errors have detailed explanations: E0502, E0503, E0506. For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs index 2f3358dcd8d..3664d76c203 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr index e15067b264d..341d2bc6563 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0499]: cannot borrow `p` as mutable more than once at a time - --> $DIR/borrowck-1.rs:13:17 + --> $DIR/borrowck-1.rs:12:17 | LL | let y = &mut p.y; | -------- first mutable borrow occurs here @@ -23,6 +14,6 @@ LL | println!("{:?}", p); LL | *y+=1; | ----- first borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs index 06c6a87eb10..ae416bab65e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr index a195b981eaa..584bb862b2c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-2.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-2.rs:13:17 + --> $DIR/borrowck-2.rs:12:17 | LL | let y = &p.y; | ---- immutable borrow occurs here @@ -23,6 +14,6 @@ LL | let x = &mut p.x; LL | println!("{}", y); | - immutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs index ba998f78c87..bdd6cb79b60 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr index b54c729a307..dab1809a381 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-3.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0597]: `p` does not live long enough - --> $DIR/borrowck-3.rs:14:29 + --> $DIR/borrowck-3.rs:13:29 | LL | let mut c = { | ----- borrow later stored here @@ -22,6 +13,6 @@ LL | println!("{:?}", p); LL | }; | - `p` dropped here while still borrowed -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs index 4fab0189c27..a2290d85020 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr index 905fa3475ed..29bd4b27d6b 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-4.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function - --> $DIR/borrowck-4.rs:11:17 + --> $DIR/borrowck-4.rs:10:17 | LL | let mut c = || { | ^^ may outlive borrowed value `p` @@ -17,7 +8,7 @@ LL | println!("{:?}", p); | - `p` is borrowed here | note: closure is returned here - --> $DIR/borrowck-4.rs:9:14 + --> $DIR/borrowck-4.rs:8:14 | LL | fn foo () -> impl FnMut()->() { | ^^^^^^^^^^^^^^^^ @@ -26,6 +17,6 @@ help: to force the closure to take ownership of `p` (and any other referenced va LL | let mut c = move || { | ^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs index b23947ad5d1..6a8c9664051 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -1,8 +1,8 @@ +// edition:2021 + // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![feature(box_syntax)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr index 58975c6f46f..5f1dae2972f 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-closures-mut-and-imm.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 | @@ -25,6 +16,6 @@ LL | }; LL | drop(c2); | -- immutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs index 15be1d8c722..a110fa4e2cb 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs @@ -1,7 +1,6 @@ -// Test borrow checker when we precise capture when using boxes +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// Test borrow checker when we precise capture when using boxes struct MetaData { x: String, name: String } struct Data { m: MetaData } diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr index 174faa33c49..2badf051418 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed - --> $DIR/box.rs:22:5 + --> $DIR/box.rs:21:5 | LL | let mut c = || { | -- borrow of `e.0.0.m.x` occurs here @@ -22,7 +13,7 @@ LL | c(); | - borrow later used here error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable - --> $DIR/box.rs:39:20 + --> $DIR/box.rs:38:20 | LL | let mut c = || { | -- mutable borrow occurs here @@ -36,7 +27,7 @@ LL | c(); | - mutable borrow later used here error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed - --> $DIR/box.rs:56:5 + --> $DIR/box.rs:55:5 | LL | let c = || { | -- borrow of `e.0.0.m.x` occurs here @@ -49,7 +40,7 @@ LL | LL | c(); | - borrow later used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0502, E0506. For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs index 1ea38e260b6..a5b4a19d8c3 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs @@ -1,9 +1,8 @@ +// edition:2021 + // Test that if we deref an immutable borrow to access a Place, // then we can't mutate the final place. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn main() { let mut x = (format!(""), format!("X2")); let mut y = (&x, "Y"); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr index 39a11fb3327..cfe531e17d3 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cant-mutate-imm-borrow.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference - --> $DIR/cant-mutate-imm-borrow.rs:14:17 + --> $DIR/cant-mutate-imm-borrow.rs:13:17 | LL | let mut c = || { | ^^ cannot borrow as mutable @@ -16,6 +7,6 @@ LL | LL | z.0.0.0 = format!("X1"); | ------- mutable borrow occurs due to use of `z.0.0.0` in closure -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs index 928c866726f..25ee9a1490e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 // Ensure that diagnostics for mutability error (because the root variable // isn't mutable) work with `capture_disjoint_fields` enabled. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr index 9fb8dd4a1c3..98414fa8a3d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cant-mutate-imm.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable - --> $DIR/cant-mutate-imm.rs:13:9 + --> $DIR/cant-mutate-imm.rs:12:9 | LL | let z = (y, 10); | - help: consider changing this to be mutable: `mut z` @@ -17,7 +8,7 @@ LL | z.0.0.0 = 20; | ^^^^^^^^^^^^ cannot assign error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable - --> $DIR/cant-mutate-imm.rs:25:9 + --> $DIR/cant-mutate-imm.rs:24:9 | LL | let bx = Box::new(x); | -- help: consider changing this to be mutable: `mut bx` @@ -25,6 +16,6 @@ LL | let bx = Box::new(x); LL | bx.0 = 20; | ^^^^^^^^^ cannot assign -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs index cd7c25620a7..f3be542e40d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 // Test that array access is not stored as part of closure kind origin diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr index bd9428771f4..bcde35983fc 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-array-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-array-diagnostics.rs:12:13 + --> $DIR/closure-origin-array-diagnostics.rs:9:13 | LL | let c = || { | ^^ this closure implements `FnOnce`, not `Fn` @@ -18,6 +9,6 @@ LL | }; LL | expect_fn(c); | --------- the requirement to implement `Fn` derives from here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs index 2916d8c794f..aa85b55b15c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs @@ -1,11 +1,7 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 // Check that precise paths are being reported back in the error message. - enum MultiVariant { Point(i32, i32), Meta(i32) diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr index de0bfe3bd76..066c000c832 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0382]: use of moved value: `c` - --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13 + --> $DIR/closure-origin-multi-variant-diagnostics.rs:26:13 | LL | let a = c; | - value moved here @@ -16,11 +7,11 @@ LL | let b = c; | ^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment - --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52 + --> $DIR/closure-origin-multi-variant-diagnostics.rs:16:52 | LL | if let MultiVariant::Point(ref mut x, _) = point { | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs index 2ed0149b9db..bedb103cc4c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs @@ -1,9 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 -// Check that precise paths are being reported back in the error message. enum SingleVariant { Point(i32, i32), diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr index 402f5e4f33e..2a6e00850fa 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0382]: use of moved value: `c` - --> $DIR/closure-origin-single-variant-diagnostics.rs:21:13 + --> $DIR/closure-origin-single-variant-diagnostics.rs:17:13 | LL | let b = c; | - value moved here @@ -16,11 +7,11 @@ LL | let a = c; | ^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment - --> $DIR/closure-origin-single-variant-diagnostics.rs:16:50 + --> $DIR/closure-origin-single-variant-diagnostics.rs:12:50 | LL | let SingleVariant::Point(ref mut x, _) = point; | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs index 103890f1f35..3277a83c4e1 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 // Check that precise paths are being reported back in the error message. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr index 474d77b7cd2..d7fc51c55ea 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-struct-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0382]: use of moved value: `hello` - --> $DIR/closure-origin-struct-diagnostics.rs:24:13 + --> $DIR/closure-origin-struct-diagnostics.rs:21:13 | LL | let b = hello; | ----- value moved here @@ -16,11 +7,11 @@ LL | let c = hello; | ^^^^^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment - --> $DIR/closure-origin-struct-diagnostics.rs:20:9 + --> $DIR/closure-origin-struct-diagnostics.rs:17:9 | LL | x.y.a += 1; | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs index 6b078d2329c..dc3a57ae793 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 // Check that precise paths are being reported back in the error message. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr index 716728e96ec..63e2d300eb0 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0382]: use of moved value: `hello` - --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13 + --> $DIR/closure-origin-tuple-diagnostics-1.rs:12:13 | LL | let b = hello; | ----- value moved here @@ -16,11 +7,11 @@ LL | let c = hello; | ^^^^^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment - --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9 + --> $DIR/closure-origin-tuple-diagnostics-1.rs:8:9 | LL | x.0 += 1; | ^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs index 0638db60769..fa1328013db 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + struct S(String, String); fn expect_fn<F: Fn()>(_f: F) {} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr index 77eb2a94ffb..df33c4f1fd6 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-tuple-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-tuple-diagnostics.rs:11:13 + --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 | LL | let c = || { | ^^ this closure implements `FnOnce`, not `Fn` @@ -18,6 +9,6 @@ LL | }; LL | expect_fn(c); | --------- the requirement to implement `Fn` derives from here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs index 09491f296f6..1cc22fac352 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -1,6 +1,6 @@ +// edition:2021 + // check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![allow(unreachable_code)] #![warn(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr index 81bbc4e1dc0..4eac5a2d282 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/liveness.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - warning: value captured by `a` is never read --> $DIR/liveness.rs:23:9 | @@ -75,5 +66,5 @@ LL | b = Some("e1"); | = help: did you mean to capture by reference instead? -warning: 8 warnings emitted +warning: 7 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs index e2035464dfa..10a7d07a1df 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs @@ -1,6 +1,6 @@ +// edition:2021 + // check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr index 35b0c22fc4f..f74303e3dd6 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/liveness_unintentional_copy.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - warning: value assigned to `a` is never read --> $DIR/liveness_unintentional_copy.rs:19:9 | @@ -43,5 +34,5 @@ LL | a += x; | = help: did you mean to capture by reference instead? -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs index 39b04c833e3..fa73ff23f9c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs @@ -1,8 +1,8 @@ +// edition:2021 + // Test that when a borrow checker diagnostics are emitted, it's as precise // as the capture by the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![allow(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr index a3d1f550557..ac4c9c93769 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time --> $DIR/multilevel-path.rs:23:14 | @@ -21,6 +12,6 @@ LL | LL | c(); | - first borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs index 676fde558df..3d5a31e8b8e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs @@ -1,9 +1,8 @@ +// edition:2021 + // Test that we can't mutate a place if we need to deref an imm-borrow // to reach it. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn imm_mut_ref() { let mut x = String::new(); let y = String::new(); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr index 831e486db82..dbf8523a3ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference - --> $DIR/mut_ref.rs:13:13 + --> $DIR/mut_ref.rs:12:13 | LL | let ref_mref_x = &mref_x; | ------- help: consider changing this to be a mutable reference: `&mut mref_x` @@ -20,7 +11,7 @@ LL | **ref_mref_x = y; | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference - --> $DIR/mut_ref.rs:27:13 + --> $DIR/mut_ref.rs:26:13 | LL | let c = || { | ^^ cannot borrow as mutable @@ -28,6 +19,6 @@ LL | LL | **mref_ref_x = y; | ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs index 82ec60a2e79..4799f488d7d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -1,7 +1,6 @@ -// check-pass +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// check-pass // Given how the closure desugaring is implemented (at least at the time of writing this test), // we don't need to truncate the captured path to a reference into a packed-struct if the field diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr index e8cc164be87..d2466681a08 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/repr_packed.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - warning: reference to packed field is unaligned - --> $DIR/repr_packed.rs:25:24 + --> $DIR/repr_packed.rs:24:24 | LL | println!("{}", foo.x); | ^^^^^ @@ -18,5 +9,5 @@ LL | println!("{}", foo.x); = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs index e78d8715e48..ed2d9a3de00 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs @@ -1,9 +1,8 @@ +// edition:2021 + // Test that borrow checker error is accurate and that min capture pass of the // closure analysis is working as expected. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug)] struct Point { x: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr index f1748fda151..32705af3d01 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/simple-struct-min-capture.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable - --> $DIR/simple-struct-min-capture.rs:23:22 + --> $DIR/simple-struct-min-capture.rs:22:22 | LL | let mut c = || { | -- mutable borrow occurs here @@ -23,6 +14,6 @@ LL | LL | c(); | - mutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs index a3222635b62..269cf76e673 100644 --- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs +++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr index a031360ed34..b936c5ee35a 100644 --- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr +++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/feature-gate-capture_disjoint_fields.rs:10:13 + --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/feature-gate-capture_disjoint_fields.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing s[] -> ImmBorrow - --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ error: Min Capture analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture s[] -> ImmBorrow - --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs index 9466e103897..bfa3ebcd6d2 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] struct Filter { diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr index e9420fe5a0c..10e0d076b42 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr @@ -1,35 +1,26 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/filter-on-struct-member.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 + --> $DIR/filter-on-struct-member.rs:24:13 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Capturing self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 + --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 + --> $DIR/filter-on-struct-member.rs:24:13 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Min Capture self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 + --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index 93e6cf03405..ee8dd4b4fc3 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -11,7 +11,7 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Send` trait implementation //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; } }); @@ -28,7 +28,7 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Sync`, `Send` trait implementation //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; } }); @@ -49,7 +49,7 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { let _ = &f; - //~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Clone` trait implementation, and drop order //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; println!("{:?}", f_1.0); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index 2c0dbd01754..7a6dcc55bbb 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -11,7 +11,7 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Send` trait implementation //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; }); @@ -28,7 +28,7 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Sync`, `Send` trait implementation //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; }); @@ -49,7 +49,7 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Clone` trait implementation, and drop order //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; println!("{:?}", f_1.0); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 6e3723b8bdb..d8420f9652e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -1,4 +1,4 @@ -error: `Send` trait implementation affected for closure because of `capture_disjoint_fields` +error: `Send` trait implementation will change in Rust 2021 --> $DIR/auto_traits.rs:13:19 | LL | thread::spawn(move || unsafe { @@ -14,6 +14,7 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `fptr` to be fully captured | LL | thread::spawn(move || { let _ = &fptr; unsafe { @@ -23,7 +24,7 @@ LL | *fptr.0 = 20; LL | } }); | -error: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` +error: `Sync`, `Send` trait implementation will change in Rust 2021 --> $DIR/auto_traits.rs:30:19 | LL | thread::spawn(move || unsafe { @@ -34,6 +35,7 @@ LL | | *fptr.0.0 = 20; LL | | }); | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `fptr` to be fully captured | LL | thread::spawn(move || { let _ = &fptr; unsafe { @@ -43,7 +45,7 @@ LL | *fptr.0.0 = 20; LL | } }); | -error: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` +error: `Clone` trait implementation, and drop order will change in Rust 2021 --> $DIR/auto_traits.rs:51:13 | LL | let c = || { @@ -55,6 +57,7 @@ LL | | println!("{:?}", f_1.0); LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `f` to be fully captured | LL | let c = || { let _ = &f; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed index 3770e93239a..4bc9b19642f 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed @@ -13,7 +13,8 @@ fn test1_all_need_migration() { let t2 = (String::new(), String::new()); let c = || { let _ = (&t, &t1, &t2); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; @@ -32,7 +33,8 @@ fn test2_only_precise_paths_need_migration() { let t2 = (String::new(), String::new()); let c = || { let _ = (&t, &t1); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -48,7 +50,8 @@ fn test3_only_by_value_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{}", t1.1); @@ -66,7 +69,8 @@ fn test4_only_non_copy_types_need_migration() { let t1 = (0i32, 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -84,7 +88,8 @@ fn test5_only_drop_types_need_migration() { let s = S(0i32, 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _s = s.0; @@ -99,7 +104,8 @@ fn test6_move_closures_non_copy_types_might_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = move || { let _ = (&t1, &t); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); }; @@ -114,7 +120,8 @@ fn test7_drop_non_drop_aggregate_need_migration() { let t = (String::new(), String::new(), 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs index 2015ab7e9b8..446ce43a469 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs @@ -13,7 +13,8 @@ fn test1_all_need_migration() { let t2 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; @@ -32,7 +33,8 @@ fn test2_only_precise_paths_need_migration() { let t2 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -48,7 +50,8 @@ fn test3_only_by_value_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{}", t1.1); @@ -66,7 +69,8 @@ fn test4_only_non_copy_types_need_migration() { let t1 = (0i32, 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -84,7 +88,8 @@ fn test5_only_drop_types_need_migration() { let s = S(0i32, 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _s = s.0; @@ -99,7 +104,8 @@ fn test6_move_closures_non_copy_types_might_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); }; @@ -114,7 +120,8 @@ fn test7_drop_non_drop_aggregate_need_migration() { let t = (String::new(), String::new(), 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr index 69a99f7a53a..0dfbcddc279 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr @@ -1,4 +1,4 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/insignificant_drop.rs:15:13 | LL | let c = || { @@ -16,141 +16,155 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | LL | let c = || { let _ = (&t, &t1, &t2); LL | LL | +LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:34:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:35:13 | LL | let c = || { | _____________^ LL | | LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; +LL | | +... | LL | | let _t2 = t2; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1` to be fully captured | LL | let c = || { let _ = (&t, &t1); LL | LL | +LL | LL | let _t = t.0; LL | let _t1 = t1.0; -LL | let _t2 = t2; ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:50:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:52:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | println!("{}", t1.1); LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | println!("{}", t1.1); -LL | }; - | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:68:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:71:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | let _t1 = t1.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | let _t1 = t1.0; -LL | }; - | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:86:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:90:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | let _s = s.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | let _s = s.0; -LL | }; - | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:101:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:106:13 | LL | let c = move || { | _____________^ LL | | LL | | +LL | | LL | | println!("{} {}", t1.1, t.1); LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t1`, `t` to be fully captured | LL | let c = move || { let _ = (&t1, &t); LL | LL | +LL | LL | println!("{} {}", t1.1, t.1); LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:116:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop.rs:122:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | }; | diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed index e89cc2c8fb3..5a781219a72 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed @@ -36,7 +36,8 @@ fn significant_drop_needs_migration() { let t = (SigDrop {}, SigDrop {}); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -53,7 +54,8 @@ fn generic_struct_with_significant_drop_needs_migration() { // move is used to force i32 to be copied instead of being a ref let c = move || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs index e16cd9d52b7..d57da326556 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs @@ -36,7 +36,8 @@ fn significant_drop_needs_migration() { let t = (SigDrop {}, SigDrop {}); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -53,7 +54,8 @@ fn generic_struct_with_significant_drop_needs_migration() { // move is used to force i32 to be copied instead of being a ref let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr index 2b141656be2..d25f8f635be 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr @@ -1,10 +1,11 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/insignificant_drop_attr_migrations.rs:38:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | }; | |_____^ @@ -14,31 +15,36 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop_attr_migrations.rs:55:13 +error: drop order will change in Rust 2021 + --> $DIR/insignificant_drop_attr_migrations.rs:56:13 | LL | let c = move || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.1; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = move || { let _ = &t; LL | LL | +LL | LL | let _t = t.1; LL | }; | diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs new file mode 100644 index 00000000000..fce9cac627b --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs @@ -0,0 +1,34 @@ +// edition:2018 +// check-pass + +#![warn(rust_2021_compatibility)] + +use std::future::Future; + +struct Runtime; + +impl Runtime { + pub fn block_on<F: Future>(&self, _future: F) -> F::Output { + unimplemented!() + } +} + +pub fn http<F, Fut>(_func: F) +where + F: Fn() -> Fut, + Fut: Future<Output = ()>, +{ + let rt = Runtime {}; + let srv = rt.block_on(async move { serve(move || async move { unimplemented!() }) }); + let _ = || rt.block_on(async { srv }); +} + +pub struct Server<S> { + _marker: std::marker::PhantomData<S>, +} + +pub fn serve<S>(_new_service: S) -> Server<S> { + unimplemented!() +} + +fn main() { } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed index 979c023fc53..42b6ce54d3c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed @@ -17,7 +17,8 @@ impl Drop for Foo { fn closure_contains_block() { let t = (Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -28,7 +29,8 @@ fn closure_contains_block() { fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || { let _ = &t; t.0 }; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs index c2a700bd9ca..ab0ed460fba 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs @@ -17,7 +17,8 @@ impl Drop for Foo { fn closure_contains_block() { let t = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -28,7 +29,8 @@ fn closure_contains_block() { fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || t.0; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr index a968d3a093b..7b654f480a3 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr @@ -1,10 +1,11 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/migrations_rustfix.rs:19:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | }; | |_____^ @@ -14,21 +15,24 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/migrations_rustfix.rs:30:13 +error: drop order will change in Rust 2021 + --> $DIR/migrations_rustfix.rs:31:13 | LL | let c = || t.0; | ^^^^^^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; t.0 }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index 95463a62185..abff6802e95 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -13,7 +13,7 @@ fn foo_diverges() -> ! { panic!() } fn assert_panics<F>(f: F) where F: FnOnce() { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation //~| HELP: add a dummy let to cause `f` to be fully captured f.0() }); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index fae7fc87c02..baa17e85b52 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -13,7 +13,7 @@ fn foo_diverges() -> ! { panic!() } fn assert_panics<F>(f: F) where F: FnOnce() { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation //~| HELP: add a dummy let to cause `f` to be fully captured f.0() }); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index bbc8eb9a9cd..8dca06a836c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,4 +1,4 @@ -error: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` +error: `UnwindSafe`, `RefUnwindSafe` trait implementation will change in Rust 2021 --> $DIR/mir_calls_to_shims.rs:15:38 | LL | let result = panic::catch_unwind(move || { @@ -14,6 +14,7 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `f` to be fully captured | LL | let result = panic::catch_unwind(move || { let _ = &f; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed index 5c93fce9250..90ea1ed2883 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed @@ -17,7 +17,7 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let t = ConstainsDropField(Foo(10), Foo(20)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t = &t.1; @@ -40,7 +40,7 @@ fn test_precise_analysis_long_path_missing() { let u = U(T(S, S), T(S, S)); let c = || { let _ = &u; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; let _x = u.0.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs index fb4af00aa06..cb432304592 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -17,7 +17,7 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let t = ConstainsDropField(Foo(10), Foo(20)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; let _t = &t.1; @@ -40,7 +40,7 @@ fn test_precise_analysis_long_path_missing() { let u = U(T(S, S), T(S, S)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; let _x = u.0.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr index 0cd191e2c98..f010c51f136 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -1,4 +1,4 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/precise.rs:19:13 | LL | let c = || { @@ -15,6 +15,7 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; @@ -25,7 +26,7 @@ LL | let _t = &t.1; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/precise.rs:42:13 | LL | let c = || { @@ -38,6 +39,7 @@ LL | | let _x = u.1.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `u` to be fully captured | LL | let c = || { let _ = &u; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed index 1fa0fb3db2f..1c970175d18 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed @@ -23,7 +23,8 @@ fn test1_all_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { let _ = (&t, &t1, &t2); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -41,7 +42,8 @@ fn test2_only_precise_paths_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { let _ = (&t, &t1); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -57,7 +59,8 @@ fn test3_only_by_value_need_migration() { let t = (Foo(0), Foo(0)); let t1 = (Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{:?}", t1.1); @@ -74,7 +77,8 @@ fn test4_type_contains_drop_need_migration() { let t = ConstainsDropField(Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -89,7 +93,8 @@ fn test5_drop_non_drop_aggregate_need_migration() { let t = (Foo(0), Foo(0), 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -102,7 +107,8 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() { let t = (Foo(0), String::new()); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; }; @@ -117,7 +123,8 @@ fn test7_move_closures_non_copy_types_might_need_migration() { let t1 = (Foo(0), Foo(0), Foo(0)); let c = move || { let _ = (&t1, &t); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs index 1f0efbe1ebc..c479a6a54f0 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs @@ -23,7 +23,8 @@ fn test1_all_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -41,7 +42,8 @@ fn test2_only_precise_paths_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; let _t1 = t1.0; @@ -57,7 +59,8 @@ fn test3_only_by_value_need_migration() { let t = (Foo(0), Foo(0)); let t1 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; println!("{:?}", t1.1); @@ -74,7 +77,8 @@ fn test4_type_contains_drop_need_migration() { let t = ConstainsDropField(Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -89,7 +93,8 @@ fn test5_drop_non_drop_aggregate_need_migration() { let t = (Foo(0), Foo(0), 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; }; @@ -102,7 +107,8 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() { let t = (Foo(0), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; }; @@ -117,7 +123,8 @@ fn test7_move_closures_non_copy_types_might_need_migration() { let t1 = (Foo(0), Foo(0), Foo(0)); let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); }; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr index 91e75ffb81a..873a9100bee 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -1,12 +1,12 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: drop order will change in Rust 2021 --> $DIR/significant_drop.rs:25:13 | LL | let c = || { | _____________^ LL | | LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; +LL | | +... | LL | | let _t2 = t2.0; LL | | }; | |_____^ @@ -16,137 +16,153 @@ note: the lint level is defined here | LL | #![deny(disjoint_capture_migration)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | LL | let c = || { let _ = (&t, &t1, &t2); LL | LL | +LL | LL | let _t = t.0; LL | let _t1 = t1.0; -LL | let _t2 = t2.0; ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:43:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:44:13 | LL | let c = || { | _____________^ LL | | LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; +LL | | +... | LL | | let _t2 = t2; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1` to be fully captured | LL | let c = || { let _ = (&t, &t1); LL | LL | +LL | LL | let _t = t.0; LL | let _t1 = t1.0; -LL | let _t2 = t2; ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:59:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:61:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | println!("{:?}", t1.1); LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | println!("{:?}", t1.1); -LL | }; - | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:76:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:79:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:91:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:95:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.0; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:104:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:109:13 | LL | let c = || { | _____________^ LL | | LL | | +LL | | LL | | let _t = t.1; LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.1; LL | }; | -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:119:13 +error: drop order will change in Rust 2021 + --> $DIR/significant_drop.rs:125:13 | LL | let c = move || { | _____________^ LL | | LL | | +LL | | LL | | println!("{:?} {:?}", t1.1, t.1); LL | | }; | |_____^ | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t1`, `t` to be fully captured | LL | let c = move || { let _ = (&t1, &t); LL | LL | +LL | LL | println!("{:?} {:?}", t1.1, t.1); LL | }; | diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/move_closure.rs index f96370eb203..06db19974eb 100644 --- a/src/test/ui/closures/2229_closure_analysis/move_closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/move_closure.rs @@ -1,9 +1,7 @@ +// edition:2021 + // Test that move closures drop derefs with `capture_disjoint_fields` enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] fn simple_move_closure() { diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr index 82aa7ab8912..013cacfb9f2 100644 --- a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:14:17 + --> $DIR/move_closure.rs:12:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:32:17 + --> $DIR/move_closure.rs:30:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:53:17 + --> $DIR/move_closure.rs:51:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:76:17 + --> $DIR/move_closure.rs:74:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:98:17 + --> $DIR/move_closure.rs:96:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:120:13 + --> $DIR/move_closure.rs:118:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:137:13 + --> $DIR/move_closure.rs:135:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:154:13 + --> $DIR/move_closure.rs:152:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,17 +70,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/move_closure.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/move_closure.rs:17:5 + --> $DIR/move_closure.rs:15:5 | LL | / move || { LL | | @@ -92,13 +83,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),(0, 0)] -> ByValue - --> $DIR/move_closure.rs:20:9 + --> $DIR/move_closure.rs:18:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:17:5 + --> $DIR/move_closure.rs:15:5 | LL | / move || { LL | | @@ -110,13 +101,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),(0, 0)] -> ByValue - --> $DIR/move_closure.rs:20:9 + --> $DIR/move_closure.rs:18:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:33:5 | LL | / move || { LL | | @@ -128,13 +119,13 @@ LL | | }; | |_____^ | note: Capturing ref_s[Deref] -> UniqueImmBorrow - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:36:9 | LL | *ref_s += 10; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:33:5 | LL | / move || { LL | | @@ -146,13 +137,13 @@ LL | | }; | |_____^ | note: Min Capture ref_s[Deref] -> UniqueImmBorrow - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:36:9 | LL | *ref_s += 10; | ^^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:56:5 + --> $DIR/move_closure.rs:54:5 | LL | / move || { LL | | @@ -164,13 +155,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow - --> $DIR/move_closure.rs:59:9 + --> $DIR/move_closure.rs:57:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:56:5 + --> $DIR/move_closure.rs:54:5 | LL | / move || { LL | | @@ -182,13 +173,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow - --> $DIR/move_closure.rs:59:9 + --> $DIR/move_closure.rs:57:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:79:5 + --> $DIR/move_closure.rs:77:5 | LL | / move || { LL | | @@ -200,13 +191,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:82:18 + --> $DIR/move_closure.rs:80:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:79:5 + --> $DIR/move_closure.rs:77:5 | LL | / move || { LL | | @@ -218,13 +209,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:82:18 + --> $DIR/move_closure.rs:80:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:101:5 + --> $DIR/move_closure.rs:99:5 | LL | / move || { LL | | @@ -236,18 +227,18 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:104:18 + --> $DIR/move_closure.rs:102:18 | LL | let _t = t.0.0; | ^^^^^ note: Capturing t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:104:18 + --> $DIR/move_closure.rs:102:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:101:5 + --> $DIR/move_closure.rs:99:5 | LL | / move || { LL | | @@ -259,13 +250,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:104:18 + --> $DIR/move_closure.rs:102:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:123:5 + --> $DIR/move_closure.rs:121:5 | LL | / move || { LL | | @@ -277,18 +268,18 @@ LL | | }; | |_____^ | note: Capturing b[Deref,(0, 0)] -> ByValue - --> $DIR/move_closure.rs:126:18 + --> $DIR/move_closure.rs:124:18 | LL | let _t = b.0; | ^^^ note: Capturing b[] -> ByValue - --> $DIR/move_closure.rs:126:18 + --> $DIR/move_closure.rs:124:18 | LL | let _t = b.0; | ^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:123:5 + --> $DIR/move_closure.rs:121:5 | LL | / move || { LL | | @@ -300,13 +291,13 @@ LL | | }; | |_____^ | note: Min Capture b[] -> ByValue - --> $DIR/move_closure.rs:126:18 + --> $DIR/move_closure.rs:124:18 | LL | let _t = b.0; | ^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:140:5 + --> $DIR/move_closure.rs:138:5 | LL | / move || { LL | | @@ -318,13 +309,13 @@ LL | | }; | |_____^ | note: Capturing b[Deref,(0, 0)] -> ByValue - --> $DIR/move_closure.rs:143:24 + --> $DIR/move_closure.rs:141:24 | LL | println!("{}", b.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:140:5 + --> $DIR/move_closure.rs:138:5 | LL | / move || { LL | | @@ -336,13 +327,13 @@ LL | | }; | |_____^ | note: Min Capture b[] -> ByValue - --> $DIR/move_closure.rs:143:24 + --> $DIR/move_closure.rs:141:24 | LL | println!("{}", b.0); | ^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:157:5 + --> $DIR/move_closure.rs:155:5 | LL | / move || { LL | | @@ -354,13 +345,13 @@ LL | | }; | |_____^ | note: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue - --> $DIR/move_closure.rs:160:24 + --> $DIR/move_closure.rs:158:24 | LL | println!("{}", t.1.0); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:157:5 + --> $DIR/move_closure.rs:155:5 | LL | / move || { LL | | @@ -372,11 +363,11 @@ LL | | }; | |_____^ | note: Min Capture t[(1, 0)] -> ByValue - --> $DIR/move_closure.rs:160:24 + --> $DIR/move_closure.rs:158:24 | LL | println!("{}", t.1.0); | ^^^^^ -error: aborting due to 24 previous errors; 1 warning emitted +error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs index 7d2d4c104d4..a8a2acfa78d 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr index 1c8db7952af..29ad1c59198 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-1.rs:24:13 + --> $DIR/multilevel-path-1.rs:22:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/multilevel-path-1.rs:27:5 + --> $DIR/multilevel-path-1.rs:25:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-1.rs:30:19 + --> $DIR/multilevel-path-1.rs:28:19 | LL | let wp = &w.p; | ^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-1.rs:27:5 + --> $DIR/multilevel-path-1.rs:25:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-1.rs:30:19 + --> $DIR/multilevel-path-1.rs:28:19 | LL | let wp = &w.p; | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs index 540e70138e5..e21fe318cd1 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr index 37287f6b3bc..929cba11314 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-2.rs:21:13 + --> $DIR/multilevel-path-2.rs:17:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-2.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/multilevel-path-2.rs:24:5 + --> $DIR/multilevel-path-2.rs:20:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-2.rs:27:24 + --> $DIR/multilevel-path-2.rs:23:24 | LL | println!("{}", w.p.x); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-2.rs:24:5 + --> $DIR/multilevel-path-2.rs:20:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-2.rs:27:24 + --> $DIR/multilevel-path-2.rs:23:24 | LL | println!("{}", w.p.x); | ^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs index 88620550f2e..f6775b3a3a5 100644 --- a/src/test/ui/closures/2229_closure_analysis/nested-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr index 21147be3f1d..013bc74e67e 100644 --- a/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:23:18 + --> $DIR/nested-closure.rs:19:18 | LL | let mut c1 = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c1 = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:33:22 + --> $DIR/nested-closure.rs:29:22 | LL | let mut c2 = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,51 +16,42 @@ LL | let mut c2 = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/nested-closure.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/nested-closure.rs:36:9 + --> $DIR/nested-closure.rs:32:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Capturing p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ note: Capturing incr[] -> ImmBorrow - --> $DIR/nested-closure.rs:36:19 + --> $DIR/nested-closure.rs:32:19 | LL | || p.y += incr; | ^^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:36:9 + --> $DIR/nested-closure.rs:32:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Min Capture p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ note: Min Capture incr[] -> ImmBorrow - --> $DIR/nested-closure.rs:36:19 + --> $DIR/nested-closure.rs:32:19 | LL | || p.y += incr; | ^^^^ error: First Pass analysis includes: - --> $DIR/nested-closure.rs:26:5 + --> $DIR/nested-closure.rs:22:5 | LL | / || { LL | | @@ -72,18 +63,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/nested-closure.rs:29:24 + --> $DIR/nested-closure.rs:25:24 | LL | println!("{}", p.x); | ^^^ note: Capturing p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:26:5 + --> $DIR/nested-closure.rs:22:5 | LL | / || { LL | | @@ -95,16 +86,16 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/nested-closure.rs:29:24 + --> $DIR/nested-closure.rs:25:24 | LL | println!("{}", p.x); | ^^^ note: Min Capture p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs index 16acd2f3206..0c10319314a 100644 --- a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs +++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr index 3c8d07ed9ba..124b7bf6fe2 100644 --- a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr +++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/path-with-array-access.rs:25:13 + --> $DIR/path-with-array-access.rs:23:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/path-with-array-access.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/path-with-array-access.rs:28:5 + --> $DIR/path-with-array-access.rs:26:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing pent[(0, 0)] -> ImmBorrow - --> $DIR/path-with-array-access.rs:31:24 + --> $DIR/path-with-array-access.rs:29:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/path-with-array-access.rs:28:5 + --> $DIR/path-with-array-access.rs:26:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture pent[(0, 0)] -> ImmBorrow - --> $DIR/path-with-array-access.rs:31:24 + --> $DIR/path-with-array-access.rs:29:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs index 609a11a578a..0f288ffa95a 100644 --- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs +++ b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(never_type)] // Should fake read the discriminant and throw an error diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr index c225abb58b7..45641ea3de3 100644 --- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr +++ b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/pattern-matching-should-fail.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/pattern-matching-should-fail.rs:72:23 + --> $DIR/pattern-matching-should-fail.rs:70:23 | LL | let c1 = || match x { }; | ^ @@ -17,13 +8,13 @@ LL | let c1 = || match x { }; = note: the matched value is of type `u8` error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:10:23 + --> $DIR/pattern-matching-should-fail.rs:8:23 | LL | let c1 = || match x { }; | ^ use of possibly-uninitialized `x` error[E0381]: borrow of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:17:14 + --> $DIR/pattern-matching-should-fail.rs:15:14 | LL | let c2 = || match x { _ => () }; | ^^ - borrow occurs due to use in closure @@ -31,7 +22,7 @@ LL | let c2 = || match x { _ => () }; | use of possibly-uninitialized `x` error[E0381]: borrow of possibly-uninitialized variable: `variant` - --> $DIR/pattern-matching-should-fail.rs:29:13 + --> $DIR/pattern-matching-should-fail.rs:27:13 | LL | let c = || { | ^^ use of possibly-uninitialized `variant` @@ -40,7 +31,7 @@ LL | match variant { | ------- borrow occurs due to use in closure error[E0381]: borrow of possibly-uninitialized variable: `variant` - --> $DIR/pattern-matching-should-fail.rs:41:13 + --> $DIR/pattern-matching-should-fail.rs:39:13 | LL | let c = || { | ^^ use of possibly-uninitialized `variant` @@ -49,24 +40,24 @@ LL | match variant { | ------- borrow occurs due to use in closure error[E0381]: use of possibly-uninitialized variable: `g` - --> $DIR/pattern-matching-should-fail.rs:57:15 + --> $DIR/pattern-matching-should-fail.rs:55:15 | LL | match g { }; | ^ use of possibly-uninitialized `g` error[E0381]: use of possibly-uninitialized variable: `t` - --> $DIR/pattern-matching-should-fail.rs:60:19 + --> $DIR/pattern-matching-should-fail.rs:58:19 | LL | match t { }; | ^ use of possibly-uninitialized `t` error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:72:23 + --> $DIR/pattern-matching-should-fail.rs:70:23 | LL | let c1 = || match x { }; | ^ use of possibly-uninitialized `x` -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 8 previous errors Some errors have detailed explanations: E0004, E0381. For more information about an error, try `rustc --explain E0004`. diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs index 0a877dd366c..56f5ac44db0 100644 --- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs +++ b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] // Should capture the discriminant since a variant of a multivariant enum is diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr index ad3e96a5753..46081333395 100644 --- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr +++ b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:12:14 + --> $DIR/patterns-capture-analysis.rs:10:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:33:14 + --> $DIR/patterns-capture-analysis.rs:31:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:54:14 + --> $DIR/patterns-capture-analysis.rs:52:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:70:14 + --> $DIR/patterns-capture-analysis.rs:68:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:92:14 + --> $DIR/patterns-capture-analysis.rs:90:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:116:14 + --> $DIR/patterns-capture-analysis.rs:114:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,17 +52,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/patterns-capture-analysis.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:16:5 + --> $DIR/patterns-capture-analysis.rs:14:5 | LL | / || { LL | | @@ -74,13 +65,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:19:15 + --> $DIR/patterns-capture-analysis.rs:17:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:16:5 + --> $DIR/patterns-capture-analysis.rs:14:5 | LL | / || { LL | | @@ -92,13 +83,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:19:15 + --> $DIR/patterns-capture-analysis.rs:17:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:36:5 + --> $DIR/patterns-capture-analysis.rs:34:5 | LL | / || { LL | | @@ -109,7 +100,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:57:5 + --> $DIR/patterns-capture-analysis.rs:55:5 | LL | / || { LL | | @@ -120,7 +111,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:73:5 + --> $DIR/patterns-capture-analysis.rs:71:5 | LL | / || { LL | | @@ -132,18 +123,18 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ note: Capturing variant[(0, 0)] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:73:5 + --> $DIR/patterns-capture-analysis.rs:71:5 | LL | / || { LL | | @@ -155,13 +146,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:95:5 + --> $DIR/patterns-capture-analysis.rs:93:5 | LL | / || { LL | | @@ -172,7 +163,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:119:5 + --> $DIR/patterns-capture-analysis.rs:117:5 | LL | / || { LL | | @@ -184,13 +175,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:122:15 + --> $DIR/patterns-capture-analysis.rs:120:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:119:5 + --> $DIR/patterns-capture-analysis.rs:117:5 | LL | / || { LL | | @@ -202,11 +193,11 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:122:15 + --> $DIR/patterns-capture-analysis.rs:120:15 | LL | match variant { | ^^^^^^^ -error: aborting due to 15 previous errors; 1 warning emitted +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/repr_packed.rs index 2b9ef2a76bb..7d472ad020f 100644 --- a/src/test/ui/closures/2229_closure_analysis/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/repr_packed.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 #![feature(rustc_attrs)] diff --git a/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr index 0517dd04b6f..405f66210aa 100644 --- a/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:16:17 + --> $DIR/repr_packed.rs:13:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:47:17 + --> $DIR/repr_packed.rs:44:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:81:13 + --> $DIR/repr_packed.rs:78:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/repr_packed.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/repr_packed.rs:19:5 + --> $DIR/repr_packed.rs:16:5 | LL | / || { LL | | @@ -47,18 +38,18 @@ LL | | }; | |_____^ | note: Capturing foo[(0, 0)] -> ImmBorrow - --> $DIR/repr_packed.rs:22:24 + --> $DIR/repr_packed.rs:19:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ note: Capturing foo[(1, 0)] -> MutBorrow - --> $DIR/repr_packed.rs:25:32 + --> $DIR/repr_packed.rs:22:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:19:5 + --> $DIR/repr_packed.rs:16:5 | LL | / || { LL | | @@ -70,18 +61,18 @@ LL | | }; | |_____^ | note: Min Capture foo[(0, 0)] -> ImmBorrow - --> $DIR/repr_packed.rs:22:24 + --> $DIR/repr_packed.rs:19:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ note: Min Capture foo[(1, 0)] -> MutBorrow - --> $DIR/repr_packed.rs:25:32 + --> $DIR/repr_packed.rs:22:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:50:5 + --> $DIR/repr_packed.rs:47:5 | LL | / || { LL | | @@ -93,13 +84,13 @@ LL | | }; | |_____^ | note: Capturing foo[] -> MutBorrow - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:51:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:50:5 + --> $DIR/repr_packed.rs:47:5 | LL | / || { LL | | @@ -111,13 +102,13 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> MutBorrow - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:51:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:84:5 + --> $DIR/repr_packed.rs:81:5 | LL | / || { LL | | @@ -129,18 +120,18 @@ LL | | }; | |_____^ | note: Capturing foo[] -> ImmBorrow - --> $DIR/repr_packed.rs:87:24 + --> $DIR/repr_packed.rs:84:24 | LL | println!("{}", foo.x); | ^^^^^ note: Capturing foo[(0, 0)] -> ByValue - --> $DIR/repr_packed.rs:91:18 + --> $DIR/repr_packed.rs:88:18 | LL | let _z = foo.x; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:84:5 + --> $DIR/repr_packed.rs:81:5 | LL | / || { LL | | @@ -152,7 +143,7 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> ByValue - --> $DIR/repr_packed.rs:87:24 + --> $DIR/repr_packed.rs:84:24 | LL | println!("{}", foo.x); | ^^^^^ foo[] used here @@ -160,6 +151,6 @@ LL | println!("{}", foo.x); LL | let _z = foo.x; | ^^^^^ foo[] captured as ByValue here -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs index 3a66399d028..73aca288faa 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs @@ -1,13 +1,8 @@ +// edition:2021 // run-pass // Test precise capture when using boxes -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - - struct MetaData { x: String, name: String } struct Data { m: MetaData } struct BoxedData(Box<Data>); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr deleted file mode 100644 index 9883c01b946..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs index 9a93e6cf1e1..2c828aed528 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs @@ -1,11 +1,9 @@ +// edition:2021 // run-pass // Test that ByValue captures compile sucessefully especially when the captures are // derefenced within the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug, Default)] struct SomeLargeType; struct MuchLargerType([SomeLargeType; 32]); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr deleted file mode 100644 index 98715c6b943..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by_value.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs index 2c359519b76..3cb1eb32952 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs @@ -1,13 +1,9 @@ +// edition:2021 // run-pass // Test that we can immutably borrow field of an instance of a structure from within a closure, // while having a mutable borrow to another field of the same instance outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - struct Point { x: i32, y: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr deleted file mode 100644 index 9b0dea770fb..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-struct.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs index 2c6679feabe..0f79b7ae7b8 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs @@ -1,12 +1,9 @@ +// edition:2021 // run-pass // Test that we can mutate an element of a tuple from within a closure // while immutably borrowing another element of the same tuple outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr deleted file mode 100644 index 28d09153952..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple-mut.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs index 52f5cef9f01..81f0328b9ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs @@ -1,12 +1,9 @@ +// edition:2021 // run-pass // Test that we can immutably borrow an element of a tuple from within a closure, // while having a mutable borrow to another element of the same tuple outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr deleted file mode 100644 index 4fb37f85f88..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs index eaea0dbfb5e..cea02fbe15d 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete fn test1() { let foo : [Vec<u8>; 3] = ["String".into(), "String".into(), "String".into()]; diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr deleted file mode 100644 index 2c17a189afb..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture_with_wildcard_match.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs index 3ad083a92d5..5c278bff90b 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![warn(unused)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr index c4abf934123..40274c88318 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr @@ -1,30 +1,21 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure-pattern-closure-within-closure.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - warning: unused variable: `t2` - --> $DIR/destructure-pattern-closure-within-closure.rs:14:21 + --> $DIR/destructure-pattern-closure-within-closure.rs:13:21 | LL | let (_, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` | note: the lint level is defined here - --> $DIR/destructure-pattern-closure-within-closure.rs:4:9 + --> $DIR/destructure-pattern-closure-within-closure.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `g2` - --> $DIR/destructure-pattern-closure-within-closure.rs:11:17 + --> $DIR/destructure-pattern-closure-within-closure.rs:10:17 | LL | let (_, g2) = g; | ^^ help: if this is intentional, prefix it with an underscore: `_g2` -warning: 3 warnings emitted +warning: 2 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs index 65527648b2c..07adbee03f9 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![warn(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr index fcfe9ee95f1..6523f2b34d5 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr @@ -1,66 +1,57 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure_patterns.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - warning: unused variable: `t1` - --> $DIR/destructure_patterns.rs:15:14 + --> $DIR/destructure_patterns.rs:14:14 | LL | let (t1, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t1` | note: the lint level is defined here - --> $DIR/destructure_patterns.rs:4:9 + --> $DIR/destructure_patterns.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `t2` - --> $DIR/destructure_patterns.rs:15:18 + --> $DIR/destructure_patterns.rs:14:18 | LL | let (t1, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` warning: unused variable: `t1` - --> $DIR/destructure_patterns.rs:27:14 + --> $DIR/destructure_patterns.rs:26:14 | LL | let (t1, _) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t1` warning: unused variable: `t2` - --> $DIR/destructure_patterns.rs:38:17 + --> $DIR/destructure_patterns.rs:37:17 | LL | let (_, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` warning: unused variable: `t` - --> $DIR/destructure_patterns.rs:46:9 + --> $DIR/destructure_patterns.rs:45:9 | LL | let t = (String::from("Hello"), String::from("World")); | ^ help: if this is intentional, prefix it with an underscore: `_t` warning: unused variable: `x` - --> $DIR/destructure_patterns.rs:92:21 + --> $DIR/destructure_patterns.rs:91:21 | LL | let Point { x, y } = p; | ^ help: try ignoring the field: `x: _` warning: unused variable: `x` - --> $DIR/destructure_patterns.rs:84:9 + --> $DIR/destructure_patterns.rs:83:9 | LL | let x = 0; | ^ help: if this is intentional, prefix it with an underscore: `_x` warning: unused variable: `tup` - --> $DIR/destructure_patterns.rs:86:9 + --> $DIR/destructure_patterns.rs:85:9 | LL | let tup = (1, 2); | ^^^ help: if this is intentional, prefix it with an underscore: `_tup` -warning: 9 warnings emitted +warning: 8 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs index 3f8e197b783..88a9816a052 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs @@ -1,10 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - // Tests that if a closure uses indivual fields of the same object // then that case is handled properly. diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr deleted file mode 100644 index bba90f8917a..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/disjoint-capture-in-same-closure.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs index dae50854d82..477fdd613f5 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr deleted file mode 100644 index 7f811875d13..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop_then_use_fake_reads.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs index 8c12593430e..e19f5ff1bae 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs @@ -1,12 +1,8 @@ +// edition:2021 // run-pass // Test disjoint capture within an impl block -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - struct Filter { div: i32, } diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr deleted file mode 100644 index 6930e18992a..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/filter-on-struct-member.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs index e89cf4550c1..1286613cb13 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -1,13 +1,9 @@ +// edition:2021 // run-pass // Test that functional record update/struct update syntax works inside // a closure when the feature `capture_disjoint_fields` is enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - #[derive(Clone)] struct S { a: String, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr deleted file mode 100644 index 7ed73abba86..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fru_syntax.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs index 9c086fe4bdf..d2375aa69ec 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #![feature(rustc_attrs)] #![feature(btree_drain_filter)] diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr deleted file mode 100644 index bc046ecad68..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lit-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs index afaafbda018..65c8a5a7850 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs @@ -1,10 +1,8 @@ +// edition:2021 // run-pass // Test that move closures compile properly with `capture_disjoint_fields` enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn simple_ref() { let mut s = 10; let ref_s = &mut s; diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr deleted file mode 100644 index c1d8ba575d6..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/move_closure.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs index 142c156bd56..b8e46403181 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs @@ -1,3 +1,4 @@ +// edition:2021 // run-pass // Test that closures can catpure paths that are more precise than just one level @@ -7,10 +8,6 @@ // while being able to mutate another path outside the closure, where the two paths are disjoint // after applying two projections on the root variable. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![allow(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr deleted file mode 100644 index 94b877522f4..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-1.rs:10:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs index d8f7d55d5aa..11a324d8a34 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs @@ -1,9 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![allow(unused)] // If the closures can handle such precison we should be able to read one path in the closure diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr deleted file mode 100644 index 100a0e167c5..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-2.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs index fc3d48ec458..8fc0efb60b7 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs @@ -1,9 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![allow(unused)] // Test that when `capture_disjoint_fields` is enabled we can read a path diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr deleted file mode 100644 index cf5be6a00e9..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-3.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs index 315622443c3..9f0c4d96aa5 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs @@ -1,11 +1,9 @@ +// edition:2021 // run-pass // Test that we can mutate a place through a mut-borrow // that is captured by the closure -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - // Check that we can mutate when one deref is required fn mut_ref_1() { let mut x = String::new(); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr deleted file mode 100644 index 4b37a0b405f..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs index 2dba923647a..bb784774b8c 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs @@ -1,3 +1,4 @@ +// edition:2021 // run-pass // Test that we can mutate a place through a mut-borrow @@ -6,9 +7,6 @@ // More specifically we test that the if the mutable reference isn't root variable of a capture // but rather accessed while acessing the precise capture. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn mut_tuple() { let mut t = (10, 10); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr deleted file mode 100644 index 418ab29098b..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref_struct_mem.rs:9:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs index 238580929ef..a80b40bb469 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs @@ -1,12 +1,8 @@ +// edition:2021 // run-pass // Test whether if we can do precise capture when using nested clsoure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> - struct Point { x: i32, y: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr deleted file mode 100644 index 293aa82ce9f..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/nested-closure.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs index d260a448926..045fe78040a 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #![feature(rustc_attrs)] diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr deleted file mode 100644 index 3e4303a3710..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/struct-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs index b3bee79254e..f3f44433ccf 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #[derive(Copy, Clone)] enum PointType { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr deleted file mode 100644 index ded0e37b0f3..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tuple-struct-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs index f6e9862b26c..8e4f91c27e2 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs @@ -1,10 +1,8 @@ +// edition:2021 // run-pass // Test that we can use raw ptrs when using `capture_disjoint_fields`. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug)] struct S { s: String, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr deleted file mode 100644 index c64c8b72e81..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsafe_ptr.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs index 0e6da8f4f18..0206927cc59 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr deleted file mode 100644 index 7d16d77bf73..00000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/use_of_mutable_borrow_and_fake_reads.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index a6b5e12d2ed..563095d440d 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> #![feature(rustc_attrs)] // Test to ensure that min analysis meets capture kind for all paths captured. diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index cbbc8792199..05d79797ab3 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/simple-struct-min-capture.rs:27:17 + --> $DIR/simple-struct-min-capture.rs:23:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let mut c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/simple-struct-min-capture.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/simple-struct-min-capture.rs:30:5 + --> $DIR/simple-struct-min-capture.rs:26:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> MutBorrow - --> $DIR/simple-struct-min-capture.rs:33:9 + --> $DIR/simple-struct-min-capture.rs:29:9 | LL | p.x += 10; | ^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/simple-struct-min-capture.rs:36:26 + --> $DIR/simple-struct-min-capture.rs:32:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/simple-struct-min-capture.rs:30:5 + --> $DIR/simple-struct-min-capture.rs:26:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> MutBorrow - --> $DIR/simple-struct-min-capture.rs:33:9 + --> $DIR/simple-struct-min-capture.rs:29:9 | LL | p.x += 10; | ^^^ p[] captured as MutBorrow here @@ -60,6 +51,6 @@ LL | p.x += 10; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs index 79d3ecc2d2b..eab9f9d08a9 100644 --- a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs +++ b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs @@ -1,10 +1,9 @@ +// edition:2021 + // Test that we restrict precision of a capture when we access a raw ptr, // i.e. the capture doesn't deref the raw ptr. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 <https://github.com/rust-lang/rust/issues/53488> + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr index 4508b2426e8..e740a4d2d6b 100644 --- a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr +++ b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:26:13 + --> $DIR/unsafe_ptr.rs:25:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:46:13 + --> $DIR/unsafe_ptr.rs:45:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,17 +16,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsafe_ptr.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:28:6 | LL | / || unsafe { LL | | @@ -38,13 +29,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:31:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:28:6 | LL | / || unsafe { LL | | @@ -56,13 +47,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:31:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:49:5 + --> $DIR/unsafe_ptr.rs:48:5 | LL | / || { LL | | @@ -74,13 +65,13 @@ LL | | }; | |_____^ | note: Capturing p[Deref,(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:52:31 + --> $DIR/unsafe_ptr.rs:51:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:49:5 + --> $DIR/unsafe_ptr.rs:48:5 | LL | / || { LL | | @@ -92,11 +83,11 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:52:31 + --> $DIR/unsafe_ptr.rs:51:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs b/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs index 90b8033d074..7843c251666 100644 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> +// edition:2021 + #![feature(rustc_attrs)] // Test to ensure that we can handle cases where diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr index 36be8431be5..c64378091e6 100644 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:24:13 + --> $DIR/wild_patterns.rs:22:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:42:13 + --> $DIR/wild_patterns.rs:40:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:60:13 + --> $DIR/wild_patterns.rs:58:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wild_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information - error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:27:5 + --> $DIR/wild_patterns.rs:25:5 | LL | / || { LL | | @@ -47,13 +38,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 + --> $DIR/wild_patterns.rs:29:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:27:5 + --> $DIR/wild_patterns.rs:25:5 | LL | / || { LL | | @@ -65,13 +56,13 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 + --> $DIR/wild_patterns.rs:29:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:43:5 | LL | / || { LL | | @@ -83,13 +74,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:47:23 | LL | let (_x, _) = t; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:43:5 | LL | / || { LL | | @@ -101,13 +92,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:47:23 | LL | let (_x, _) = t; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:63:5 + --> $DIR/wild_patterns.rs:61:5 | LL | / || { LL | | @@ -119,13 +110,13 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/wild_patterns.rs:67:23 + --> $DIR/wild_patterns.rs:65:23 | LL | let [_x, _] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:63:5 + --> $DIR/wild_patterns.rs:61:5 | LL | / || { LL | | @@ -137,11 +128,11 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/wild_patterns.rs:67:23 + --> $DIR/wild_patterns.rs:65:23 | LL | let [_x, _] = arr; | ^^^ -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-37655.rs b/src/test/ui/coercion/issue-37655.rs index 416854d66f3..416854d66f3 100644 --- a/src/test/ui/issues/issue-37655.rs +++ b/src/test/ui/coercion/issue-37655.rs diff --git a/src/test/ui/test-cfg.rs b/src/test/ui/conditional-compilation/test-cfg.rs index 8750bae0028..8750bae0028 100644 --- a/src/test/ui/test-cfg.rs +++ b/src/test/ui/conditional-compilation/test-cfg.rs diff --git a/src/test/ui/test-cfg.stderr b/src/test/ui/conditional-compilation/test-cfg.stderr index c35fe2f9458..c35fe2f9458 100644 --- a/src/test/ui/test-cfg.stderr +++ b/src/test/ui/conditional-compilation/test-cfg.stderr diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr index 26b965901a4..ebc8f458f79 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr @@ -6,3 +6,4 @@ LL | assert_eq!(f::<4usize>(Usizable), 20usize); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr index 26b965901a4..ebc8f458f79 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr @@ -6,3 +6,4 @@ LL | assert_eq!(f::<4usize>(Usizable), 20usize); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 00000000000..f34badc693e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.rs @@ -0,0 +1,38 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {} +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR: method not compatible with trait [E0308] + self.reference.size() + //~^ ERROR: unconstrained generic constant + //~| ERROR: mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 00000000000..ef785bf07eb --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -0,0 +1,29 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:30:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected type `Self::DIM` + found type `DIM` + +error: unconstrained generic constant + --> $DIR/issue-83765.rs:32:24 + | +LL | self.reference.size() + | ^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` + +error[E0308]: mismatched types + --> $DIR/issue-83765.rs:32:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected type `DIM` + found type `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs new file mode 100644 index 00000000000..478719869b2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.rs @@ -0,0 +1,31 @@ +#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait _Contains<T> { + const does_contain: bool; +} + +trait Contains<T, const Satisfied: bool> {} + +trait Delegates<T> {} + +impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + +const fn contains<A, B>() -> bool +where + A: _Contains<B>, +{ + A::does_contain +} + +impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + +fn writes_to_path<C>(cap: &C) { + writes_to_specific_path(&cap); + //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277] + //~| ERROR: unconstrained generic constant +} + +fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr new file mode 100644 index 00000000000..5e65136a6bc --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()` +... +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ------------- required by this bound in `writes_to_specific_path` + | +note: required because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} + | ------------- required by this bound in `writes_to_specific_path` + | + = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:` +note: required because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} + | ^^^^^^^^^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr index 17a96386f4b..0818d7fbf88 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -10,7 +10,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc2──╼ ╾─alloc3──╼ │ ╾──╼╾──╼ + ╾─alloc2──╼ ╾─alloc5──╼ │ ╾──╼╾──╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr index 11922e32ae1..59dcf7aefe4 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -10,7 +10,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc2────────╼ ╾───────alloc5────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs index 36fec9976be..95e7f9e9c83 100644 --- a/src/test/ui/consts/const-float-classify.rs +++ b/src/test/ui/consts/const-float-classify.rs @@ -53,6 +53,9 @@ impl const PartialEq<NonDet> for bool { fn eq(&self, _: &NonDet) -> bool { true } + fn ne(&self, _: &NonDet) -> bool { + false + } } // The result of the `is_sign` methods are not checked for correctness, since LLVM does not diff --git a/src/test/ui/issues/issue-17756.rs b/src/test/ui/consts/issue-17756.rs index 1835b177ff3..1835b177ff3 100644 --- a/src/test/ui/issues/issue-17756.rs +++ b/src/test/ui/consts/issue-17756.rs diff --git a/src/test/ui/issues/issue-69532.rs b/src/test/ui/consts/issue-69532.rs index 81007b15074..81007b15074 100644 --- a/src/test/ui/issues/issue-69532.rs +++ b/src/test/ui/consts/issue-69532.rs diff --git a/src/test/ui/consts/issue-79690.64bit.stderr b/src/test/ui/consts/issue-79690.64bit.stderr index 57e62d0b90f..cab111ab69c 100644 --- a/src/test/ui/consts/issue-79690.64bit.stderr +++ b/src/test/ui/consts/issue-79690.64bit.stderr @@ -6,7 +6,7 @@ LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc2────────╼ ╾───────alloc5────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/large_const_alloc.rs b/src/test/ui/consts/large_const_alloc.rs new file mode 100644 index 00000000000..54abaab2247 --- /dev/null +++ b/src/test/ui/consts/large_const_alloc.rs @@ -0,0 +1,18 @@ +// only-64bit +// on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed + +const FOO: () = { + // 128 TiB, unlikely anyone has that much RAM + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR evaluation of constant value failed +}; + +static FOO2: () = { + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR could not evaluate static initializer +}; + +fn main() { + let _ = FOO; + let _ = FOO2; +} diff --git a/src/test/ui/consts/large_const_alloc.stderr b/src/test/ui/consts/large_const_alloc.stderr new file mode 100644 index 00000000000..25d660f1217 --- /dev/null +++ b/src/test/ui/consts/large_const_alloc.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/large_const_alloc.rs:6:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error[E0080]: could not evaluate static initializer + --> $DIR/large_const_alloc.rs:11:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 5374088028b..e6db2eef955 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -19,7 +19,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc6──╼ ╾─alloc7──╼ │ ╾──╼╾──╼ + ╾─alloc6──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 7c4842db24c..f48978d4af6 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -19,7 +19,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc6────────╼ ╾───────alloc7────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc6────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value diff --git a/src/test/ui/extern/extern-main-issue-86110.rs b/src/test/ui/extern/extern-main-issue-86110.rs new file mode 100644 index 00000000000..83af7a14ccc --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.rs @@ -0,0 +1,7 @@ +// missing and missing2 exist to make sure that the error only happens on a `main` declaration +extern "C" { + fn missing(); + fn main(); + //~^ the `main` function cannot be declared in an `extern` block + fn missing2(); +} diff --git a/src/test/ui/extern/extern-main-issue-86110.stderr b/src/test/ui/extern/extern-main-issue-86110.stderr new file mode 100644 index 00000000000..cd3de227dcf --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.stderr @@ -0,0 +1,8 @@ +error: the `main` function cannot be declared in an `extern` block + --> $DIR/extern-main-issue-86110.rs:4:5 + | +LL | fn main(); + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr index 32b45ee10ad..f69629232ae 100644 --- a/src/test/ui/extern/extern-types-distinct-types.stderr +++ b/src/test/ui/extern/extern-types-distinct-types.stderr @@ -6,6 +6,8 @@ LL | type A; LL | type B; | ------- the expected foreign type ... +LL | fn foo(r: &A) -> &B { + | -- expected `&B` because of return type LL | r | ^ expected extern type `B`, found extern type `A` | diff --git a/src/test/ui/future-incompatible-lint-group.rs b/src/test/ui/future-incompatible-lint-group.rs index ce158043e54..bbd0e33d719 100644 --- a/src/test/ui/future-incompatible-lint-group.rs +++ b/src/test/ui/future-incompatible-lint-group.rs @@ -1,8 +1,18 @@ +// Ensure that the future_incompatible lint group only includes +// lints for changes that are not tied to an edition #![deny(future_incompatible)] trait Tr { - fn f(u8) {} //~ ERROR anonymous parameters are deprecated - //~^ WARN this is accepted in the current edition + // Warn only since this is not a `future_incompatible` lint + fn f(u8) {} //~ WARN anonymous parameters are deprecated + //~| WARN this is accepted in the current edition +} + +pub mod submodule { + // Error since this is a `future_incompatible` lint + #![doc(test(some_test))] + //~^ ERROR this attribute can only be applied at the crate level + //~| WARN this was previously accepted by the compiler } fn main() {} diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr index 16028261eb1..cb9be88c9ee 100644 --- a/src/test/ui/future-incompatible-lint-group.stderr +++ b/src/test/ui/future-incompatible-lint-group.stderr @@ -1,17 +1,28 @@ -error: anonymous parameters are deprecated and will be removed in the next edition. - --> $DIR/future-incompatible-lint-group.rs:4:10 +warning: anonymous parameters are deprecated and will be removed in the next edition. + --> $DIR/future-incompatible-lint-group.rs:7:10 | LL | fn f(u8) {} | ^^ help: try naming the parameter or explicitly ignoring it: `_: u8` | + = note: `#[warn(anonymous_parameters)]` on by default + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686> + +error: this attribute can only be applied at the crate level + --> $DIR/future-incompatible-lint-group.rs:13:12 + | +LL | #![doc(test(some_test))] + | ^^^^^^^^^^^^^^^ + | note: the lint level is defined here - --> $DIR/future-incompatible-lint-group.rs:1:9 + --> $DIR/future-incompatible-lint-group.rs:3:9 | LL | #![deny(future_incompatible)] | ^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(anonymous_parameters)]` implied by `#[deny(future_incompatible)]` - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! - = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686> + = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(future_incompatible)]` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730> + = note: read https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level for more information -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr index 8f05ab3c494..6800b37b5b1 100644 --- a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr +++ b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr @@ -6,3 +6,4 @@ LL | foo::<String>('a'); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr index c980e9463e4..db66d461095 100644 --- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr +++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr @@ -8,3 +8,4 @@ LL | evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| { error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/inference/issue-70703.rs b/src/test/ui/inference/issue-70703.rs new file mode 100644 index 00000000000..d90498e96ea --- /dev/null +++ b/src/test/ui/inference/issue-70703.rs @@ -0,0 +1,26 @@ +// check-pass + +trait Factory { + type Product; +} + +impl Factory for () { + type Product = (); +} + +trait ProductConsumer<P> { + fn consume(self, product: P); +} + +impl<P> ProductConsumer<P> for () { + fn consume(self, _: P) {} +} + +fn make_product_consumer<F: Factory>(_: F) -> impl ProductConsumer<F::Product> { + () +} + +fn main() { + let consumer = make_product_consumer(()); + consumer.consume(()); +} diff --git a/src/test/ui/non-integer-atomic.rs b/src/test/ui/intrinsics/non-integer-atomic.rs index 00a7f368a0f..00a7f368a0f 100644 --- a/src/test/ui/non-integer-atomic.rs +++ b/src/test/ui/intrinsics/non-integer-atomic.rs diff --git a/src/test/ui/non-integer-atomic.stderr b/src/test/ui/intrinsics/non-integer-atomic.stderr index ee485c21cd6..ee485c21cd6 100644 --- a/src/test/ui/non-integer-atomic.stderr +++ b/src/test/ui/intrinsics/non-integer-atomic.stderr diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs b/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs new file mode 100644 index 00000000000..7bbf47a3839 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --llvm-args diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr b/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr new file mode 100644 index 00000000000..c5a0c29cad9 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'llvm-args'. Did you mean `-C llvm-args`? + diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.rs b/src/test/ui/invalid-compile-flags/debug-option-without-group.rs new file mode 100644 index 00000000000..86e40c17854 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/debug-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --unpretty=hir diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr b/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr new file mode 100644 index 00000000000..0e57e31ad3d --- /dev/null +++ b/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'unpretty'. Did you mean `-Z unpretty`? + diff --git a/src/test/ui/issues/issue-36638.rs b/src/test/ui/keyword/keyword-self-as-type-param.rs index 2e64853697a..785d64ec8ea 100644 --- a/src/test/ui/issues/issue-36638.rs +++ b/src/test/ui/keyword/keyword-self-as-type-param.rs @@ -1,3 +1,5 @@ +// Regression test of #36638. + struct Foo<Self>(Self); //~^ ERROR expected identifier, found keyword `Self` //~^^ ERROR E0392 diff --git a/src/test/ui/issues/issue-36638.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr index 733fc4af534..cc3df2e36f7 100644 --- a/src/test/ui/issues/issue-36638.stderr +++ b/src/test/ui/keyword/keyword-self-as-type-param.stderr @@ -1,17 +1,17 @@ error: expected identifier, found keyword `Self` - --> $DIR/issue-36638.rs:1:12 + --> $DIR/keyword-self-as-type-param.rs:3:12 | LL | struct Foo<Self>(Self); | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/issue-36638.rs:5:11 + --> $DIR/keyword-self-as-type-param.rs:7:11 | LL | trait Bar<Self> {} | ^^^^ expected identifier, found keyword error[E0392]: parameter `Self` is never used - --> $DIR/issue-36638.rs:1:12 + --> $DIR/keyword-self-as-type-param.rs:3:12 | LL | struct Foo<Self>(Self); | ^^^^ unused parameter diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr index 0e0e934c765..37c61e614f3 100644 --- a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr @@ -4,7 +4,7 @@ warning: hidden lifetime parameters in types are deprecated LL | fn foo(x: &Foo) {} | ^^^- help: indicate the anonymous lifetime: `<'_>` | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns elided-lifetimes-in-paths` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr index bad12f94b18..56b2f0236a5 100644 --- a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr @@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0; | | | attempt to divide `1_i32` by zero | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.stderr b/src/test/ui/lint/force-warn/force-allowed-warning.stderr index 145798a32a9..7eb980a1297 100644 --- a/src/test/ui/lint/force-warn/force-allowed-warning.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-warning.stderr @@ -4,7 +4,7 @@ warning: function is never used: `dead_function` LL | fn dead_function() {} | ^^^^^^^^^^^^^ | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns dead-code` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr index 4b004cf367d..8b9bb5a74cf 100644 --- a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr @@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0; | | | attempt to divide `1_i32` by zero | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns const-err` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr index 577dbe1fea8..ebdb022f2a2 100644 --- a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr +++ b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr @@ -4,7 +4,7 @@ warning: function is never used: `dead_function` LL | fn dead_function() {} | ^^^^^^^^^^^^^ | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns dead-code` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr index 8665fa2610a..7429e77fe83 100644 --- a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr +++ b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr @@ -4,7 +4,7 @@ warning: function `FUNCTION` should have a snake case name LL | pub fn FUNCTION() {} | ^^^^^^^^ help: convert the identifier to snake case: `function` | - = note: warning forced by `force-warns` commandline option + = note: `--force-warns non-snake-case` implied by `--force-warns nonstandard-style` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr index 8ecfe3a15b8..4f7bba6bba1 100644 --- a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr +++ b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr @@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box<SomeTrait>) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warns bare-trait-objects` = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165> diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr index 232edf4f1ef..65de6c9e287 100644 --- a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr +++ b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr @@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box<SomeTrait>) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option + = note: `--force-warns bare-trait-objects` implied by `--force-warns rust-2018-idioms` = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165> diff --git a/src/test/ui/lint/force-warn/force-warn-group.stderr b/src/test/ui/lint/force-warn/force-warn-group.stderr index 82781984f0c..fd3397c916a 100644 --- a/src/test/ui/lint/force-warn/force-warn-group.stderr +++ b/src/test/ui/lint/force-warn/force-warn-group.stderr @@ -4,7 +4,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box<SomeTrait>) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option + = note: `--force-warns bare-trait-objects` implied by `--force-warns rust-2018-idioms` = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165> diff --git a/src/test/ui/issues/issue-52169.rs b/src/test/ui/macros/issue-52169.rs index 60be97f0aee..60be97f0aee 100644 --- a/src/test/ui/issues/issue-52169.rs +++ b/src/test/ui/macros/issue-52169.rs diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs index 7253d35ed2d..7253d35ed2d 100644 --- a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs diff --git a/src/test/ui/issues/issue-45157.rs b/src/test/ui/nll/issue-45157.rs index 8d2bf22a03c..8d2bf22a03c 100644 --- a/src/test/ui/issues/issue-45157.rs +++ b/src/test/ui/nll/issue-45157.rs diff --git a/src/test/ui/issues/issue-45157.stderr b/src/test/ui/nll/issue-45157.stderr index 57fd8d49c88..57fd8d49c88 100644 --- a/src/test/ui/issues/issue-45157.stderr +++ b/src/test/ui/nll/issue-45157.stderr diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index 3278eb5f023..0f451c1e0a9 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -61,7 +61,8 @@ warning: panic message is not a string literal LL | assert!(false, S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | assert!(false, "{}", S); @@ -85,7 +86,8 @@ warning: panic message is not a string literal LL | panic!(C); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | panic!("{}", C); @@ -101,7 +103,8 @@ warning: panic message is not a string literal LL | panic!(S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | panic!("{}", S); @@ -117,7 +120,8 @@ warning: panic message is not a string literal LL | std::panic!(123); | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | std::panic!("{}", 123); @@ -133,7 +137,8 @@ warning: panic message is not a string literal LL | core::panic!(&*"abc"); | ^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | core::panic!("{}", &*"abc"); @@ -181,7 +186,8 @@ warning: panic message is not a string literal LL | fancy_panic::fancy_panic!(S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:36:12 @@ -189,7 +195,8 @@ warning: panic message is not a string literal LL | panic!(a!()); | ^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | panic!("{}", a!()); @@ -205,7 +212,8 @@ warning: panic message is not a string literal LL | panic!(format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> = note: the panic!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -218,7 +226,8 @@ warning: panic message is not a string literal LL | assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> = note: the assert!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -231,7 +240,8 @@ warning: panic message is not a string literal LL | debug_assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> = note: the debug_assert!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -244,7 +254,8 @@ warning: panic message is not a string literal LL | panic![123]; | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | panic!["{}", 123]; @@ -260,7 +271,8 @@ warning: panic message is not a string literal LL | panic!{123}; | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html> help: add a "{}" format string to Display the message | LL | panic!{"{}", 123}; diff --git a/src/test/ui/issues/issue-27060-2.rs b/src/test/ui/packed/issue-27060-2.rs index a001ce1e0ac..a001ce1e0ac 100644 --- a/src/test/ui/issues/issue-27060-2.rs +++ b/src/test/ui/packed/issue-27060-2.rs diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/packed/issue-27060-2.stderr index 5dbcc96e874..5dbcc96e874 100644 --- a/src/test/ui/issues/issue-27060-2.stderr +++ b/src/test/ui/packed/issue-27060-2.stderr diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/packed/issue-27060-rpass.rs index d9159f6669d..d9159f6669d 100644 --- a/src/test/ui/issues/issue-27060-rpass.rs +++ b/src/test/ui/packed/issue-27060-rpass.rs diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/packed/issue-27060.rs index 5317a616719..5317a616719 100644 --- a/src/test/ui/issues/issue-27060.rs +++ b/src/test/ui/packed/issue-27060.rs diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/packed/issue-27060.stderr index 09297884ed3..09297884ed3 100644 --- a/src/test/ui/issues/issue-27060.stderr +++ b/src/test/ui/packed/issue-27060.stderr diff --git a/src/test/ui/issues/issue-48636.fixed b/src/test/ui/parser/issue-48636.fixed index 87c19a32d4c..87c19a32d4c 100644 --- a/src/test/ui/issues/issue-48636.fixed +++ b/src/test/ui/parser/issue-48636.fixed diff --git a/src/test/ui/issues/issue-48636.rs b/src/test/ui/parser/issue-48636.rs index 8610dc2f72e..8610dc2f72e 100644 --- a/src/test/ui/issues/issue-48636.rs +++ b/src/test/ui/parser/issue-48636.rs diff --git a/src/test/ui/issues/issue-48636.stderr b/src/test/ui/parser/issue-48636.stderr index 462723d1d93..462723d1d93 100644 --- a/src/test/ui/issues/issue-48636.stderr +++ b/src/test/ui/parser/issue-48636.stderr diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/parser/issue-54521-1.rs index 8a682ef0a11..8a682ef0a11 100644 --- a/src/test/ui/issues/issue-54521-1.rs +++ b/src/test/ui/parser/issue-54521-1.rs diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/parser/issue-54521-2.fixed index a91c4fe43ea..a91c4fe43ea 100644 --- a/src/test/ui/issues/issue-54521-2.fixed +++ b/src/test/ui/parser/issue-54521-2.fixed diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/parser/issue-54521-2.rs index 3639aac87ee..3639aac87ee 100644 --- a/src/test/ui/issues/issue-54521-2.rs +++ b/src/test/ui/parser/issue-54521-2.rs diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/parser/issue-54521-2.stderr index 9556b83b730..9556b83b730 100644 --- a/src/test/ui/issues/issue-54521-2.stderr +++ b/src/test/ui/parser/issue-54521-2.stderr diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/parser/issue-54521-3.fixed index 84ab6866cf1..84ab6866cf1 100644 --- a/src/test/ui/issues/issue-54521.fixed +++ b/src/test/ui/parser/issue-54521-3.fixed diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/parser/issue-54521-3.rs index f1d68504178..f1d68504178 100644 --- a/src/test/ui/issues/issue-54521.rs +++ b/src/test/ui/parser/issue-54521-3.rs diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/parser/issue-54521-3.stderr index ffefbfd0348..0f23dd62107 100644 --- a/src/test/ui/issues/issue-54521.stderr +++ b/src/test/ui/parser/issue-54521-3.stderr @@ -1,23 +1,23 @@ error: unmatched angle brackets - --> $DIR/issue-54521.rs:11:60 + --> $DIR/issue-54521-3.rs:11:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>(); | ^^^^ help: remove extra angle brackets error: unmatched angle brackets - --> $DIR/issue-54521.rs:14:60 + --> $DIR/issue-54521-3.rs:14:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>(); | ^^^ help: remove extra angle brackets error: unmatched angle brackets - --> $DIR/issue-54521.rs:17:60 + --> $DIR/issue-54521-3.rs:17:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>(); | ^^ help: remove extra angle brackets error: unmatched angle bracket - --> $DIR/issue-54521.rs:20:60 + --> $DIR/issue-54521-3.rs:20:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>(); | ^ help: remove extra angle bracket diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr index 9b5f11ce667..798ce1199a9 100644 --- a/src/test/ui/retslot-cast.stderr +++ b/src/test/ui/retslot-cast.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/retslot-cast.rs:13:5 | +LL | -> Option<&Iterator<Item=()>> { + | -------------------------- expected `Option<&dyn Iterator<Item = ()>>` because of return type +... LL | inner(x) | ^^^^^^^^ expected trait `Iterator<Item = ()>`, found trait `Iterator<Item = ()> + Send` | diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs index 23cc9f0512c..4f076fa0693 100644 --- a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs @@ -12,6 +12,25 @@ const C: [(); 42] = { }] }; +struct S {} +trait Tr { + fn foo(); + fn bar() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} +impl Tr for S { + fn foo() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} + fn main() { //~^ NOTE: ...not the enclosing function body [(); return || { diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr index 9275cb91dd3..d7eeb3a7290 100644 --- a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -9,7 +9,31 @@ LL | | }] | |_____^ error[E0572]: return statement outside of function body - --> $DIR/issue-86188-return-not-in-fn-body.rs:17:10 + --> $DIR/issue-86188-return-not-in-fn-body.rs:20:14 + | +LL | / fn bar() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:28:14 + | +LL | / fn foo() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10 | LL | / fn main() { LL | | @@ -23,6 +47,6 @@ LL | || }]; LL | | } | |_- ...not the enclosing function body -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs new file mode 100644 index 00000000000..4285eaf18aa --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -0,0 +1,22 @@ +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +pub trait MyTrait { + fn func(self); +} + +pub struct NonConst; + +impl MyTrait for NonConst { + fn func(self) { + + } +} + +pub struct Const; + +impl const MyTrait for Const { + fn func(self) { + + } +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs new file mode 100644 index 00000000000..734ce17001e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -0,0 +1,22 @@ +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait MyTrait { + #[stable(feature = "rust1", since = "1.0.0")] + fn func(); +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Unstable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "staged", issue = "none")] +impl const MyTrait for Unstable { + fn func() { + + } +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs index ec6f45f956d..44814b0654e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -17,6 +17,9 @@ impl const PartialEq for Int { fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } } pub trait Plus { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs index c37990b1af3..47eed89d03d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -12,6 +12,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } const fn equals_self<T: PartialEq>(t: &T) -> bool { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index d553b2ab8ec..00a3c7f51fe 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -11,6 +11,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } // This duplicate bound should not result in ambiguities. It should be equivalent to a single const diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs index 74b0d5fbe47..953a6511199 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -12,6 +12,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } const fn equals_self<T: PartialEq>(t: &T) -> bool { diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr new file mode 100644 index 00000000000..30baa385475 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:16:5 + | +LL | NonConst.func(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs new file mode 100644 index 00000000000..c28ff638958 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -0,0 +1,22 @@ +// revisions: stock gated +#![cfg_attr(gated, feature(const_trait_impl))] +#![allow(incomplete_features)] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +fn non_const_context() { + NonConst.func(); + Const.func(); +} + +const fn const_context() { + NonConst.func(); + //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants + Const.func(); + //[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr new file mode 100644 index 00000000000..e6a86f251ca --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -0,0 +1,15 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:16:5 + | +LL | NonConst.func(); + | ^^^^^^^^^^^^^^^ + +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:18:5 + | +LL | Const.func(); + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs new file mode 100644 index 00000000000..4ff4fa0d83b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs @@ -0,0 +1,20 @@ +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); + self.req(); + } +} + +struct S; + +impl const Tr for S { + fn req(&self) {} +} +//~^^^ ERROR const trait implementations may not use default functions + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr new file mode 100644 index 00000000000..51a7b18fa8d --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr @@ -0,0 +1,10 @@ +error: const trait implementations may not use default functions + --> $DIR/impl-with-default-fn.rs:15:1 + | +LL | / impl const Tr for S { +LL | | fn req(&self) {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs new file mode 100644 index 00000000000..39a1b6066de --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -0,0 +1,39 @@ +// revisions: stock staged +#![cfg_attr(staged, feature(staged))] + +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(staged, rustc_const_stable(feature = "rust1", since = "1.0.0"))] +// ^ should trigger error with or without the attribute +impl const MyTrait for Stable { + fn func() { //~ ERROR trait methods cannot be stable const fn + + } +} + +fn non_const_context() { + Unstable::func(); + Stable::func(); +} + +#[unstable(feature = "none", issue = "none")] +const fn const_context() { + Unstable::func(); + //[stock]~^ ERROR `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + Stable::func(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr new file mode 100644 index 00000000000..d2ff4ce2001 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr @@ -0,0 +1,10 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr new file mode 100644 index 00000000000..91c5469bd90 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr @@ -0,0 +1,18 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:34:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(staged)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs b/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs new file mode 100644 index 00000000000..a4a5b6667df --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs @@ -0,0 +1,16 @@ +// edition:2018 +// check-pass +#![allow(unused)] +#![deny(future_prelude_collision)] + +struct S; + +impl S { + fn try_into(self) -> S { S } +} + +// See https://github.com/rust-lang/rust/issues/86633 +fn main() { + let s = S; + let s2 = s.try_into(); +} diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs new file mode 100644 index 00000000000..f276fbd6694 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -0,0 +1,19 @@ +// Check that appropriate errors are reported if an intrinsic is defined +// with the wrong number of generic lifetime/type/const parameters, and +// that no ICE occurs in these cases. + +#![feature(platform_intrinsics)] +#![crate_type="lib"] + +extern "platform-intrinsic" { + fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_add<'a, T>(x: T, y: T) -> T; + + fn simd_sub<T, U>(x: T, y: U); + //~^ ERROR: intrinsic has wrong number of type parameters + + fn simd_mul<T, const N: usize>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of const parameters +} diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr new file mode 100644 index 00000000000..fb2f1fbc5b1 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -0,0 +1,21 @@ +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:9:27 + | +LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/issue-85855.rs:14:16 + | +LL | fn simd_sub<T, U>(x: T, y: U); + | ^^^^^^ expected 1 type parameter + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:17:16 + | +LL | fn simd_mul<T, const N: usize>(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0094`. diff --git a/src/test/ui/suggestions/issue-86667.rs b/src/test/ui/suggestions/issue-86667.rs new file mode 100644 index 00000000000..6aceb137469 --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.rs @@ -0,0 +1,16 @@ +// Regression test for #86667, where a garbled suggestion was issued for +// a missing named lifetime parameter. + +// compile-flags: --edition 2018 + +async fn a(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn b(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr new file mode 100644 index 00000000000..77f7f874a4e --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -0,0 +1,27 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:6:35 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:11:29 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr index 951d7edb7f5..101132d05fa 100644 --- a/src/test/ui/synthetic-param.stderr +++ b/src/test/ui/synthetic-param.stderr @@ -18,3 +18,4 @@ LL | Bar::<i8>::func::<u8>(42); error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-attrs/test-panic-abort-disabled.rs index 874dbdb42c3..874dbdb42c3 100644 --- a/src/test/ui/test-panic-abort-disabled.rs +++ b/src/test/ui/test-attrs/test-panic-abort-disabled.rs diff --git a/src/test/ui/test-panic-abort-disabled.stderr b/src/test/ui/test-attrs/test-panic-abort-disabled.stderr index 9c65c7360c1..9c65c7360c1 100644 --- a/src/test/ui/test-panic-abort-disabled.stderr +++ b/src/test/ui/test-attrs/test-panic-abort-disabled.stderr diff --git a/src/test/ui/test-panic-abort-nocapture.rs b/src/test/ui/test-attrs/test-panic-abort-nocapture.rs index af530cc1a0b..af530cc1a0b 100644 --- a/src/test/ui/test-panic-abort-nocapture.rs +++ b/src/test/ui/test-attrs/test-panic-abort-nocapture.rs diff --git a/src/test/ui/test-panic-abort-nocapture.run.stderr b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr index 727e9691c53..727e9691c53 100644 --- a/src/test/ui/test-panic-abort-nocapture.run.stderr +++ b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr diff --git a/src/test/ui/test-panic-abort-nocapture.run.stdout b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout index 8a91732a754..8a91732a754 100644 --- a/src/test/ui/test-panic-abort-nocapture.run.stdout +++ b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-attrs/test-panic-abort.rs index 931b7993c81..931b7993c81 100644 --- a/src/test/ui/test-panic-abort.rs +++ b/src/test/ui/test-attrs/test-panic-abort.rs diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-attrs/test-panic-abort.run.stdout index f608a8cdc55..f608a8cdc55 100644 --- a/src/test/ui/test-panic-abort.run.stdout +++ b/src/test/ui/test-attrs/test-panic-abort.run.stdout diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-attrs/test-panic-while-printing.rs index 23f45407c1a..23f45407c1a 100644 --- a/src/test/ui/test-panic-while-printing.rs +++ b/src/test/ui/test-attrs/test-panic-while-printing.rs diff --git a/src/test/ui/test-passed-wasm.rs b/src/test/ui/test-attrs/test-passed-wasm.rs index 578aa4b1760..578aa4b1760 100644 --- a/src/test/ui/test-passed-wasm.rs +++ b/src/test/ui/test-attrs/test-passed-wasm.rs diff --git a/src/test/ui/test-passed-wasm.run.stdout b/src/test/ui/test-attrs/test-passed-wasm.run.stdout index c3005a77983..c3005a77983 100644 --- a/src/test/ui/test-passed-wasm.run.stdout +++ b/src/test/ui/test-attrs/test-passed-wasm.run.stdout diff --git a/src/test/ui/test-passed.rs b/src/test/ui/test-attrs/test-passed.rs index f65f0003022..f65f0003022 100644 --- a/src/test/ui/test-passed.rs +++ b/src/test/ui/test-attrs/test-passed.rs diff --git a/src/test/ui/test-passed.run.stdout b/src/test/ui/test-attrs/test-passed.run.stdout index 17f70d60749..17f70d60749 100644 --- a/src/test/ui/test-passed.run.stdout +++ b/src/test/ui/test-attrs/test-passed.run.stdout diff --git a/src/test/ui/test-thread-capture.rs b/src/test/ui/test-attrs/test-thread-capture.rs index edc972837a3..edc972837a3 100644 --- a/src/test/ui/test-thread-capture.rs +++ b/src/test/ui/test-attrs/test-thread-capture.rs diff --git a/src/test/ui/test-thread-capture.run.stdout b/src/test/ui/test-attrs/test-thread-capture.run.stdout index 487cfb55eb4..487cfb55eb4 100644 --- a/src/test/ui/test-thread-capture.run.stdout +++ b/src/test/ui/test-attrs/test-thread-capture.run.stdout diff --git a/src/test/ui/test-thread-nocapture.rs b/src/test/ui/test-attrs/test-thread-nocapture.rs index 8e8e9bbfdf0..8e8e9bbfdf0 100644 --- a/src/test/ui/test-thread-nocapture.rs +++ b/src/test/ui/test-attrs/test-thread-nocapture.rs diff --git a/src/test/ui/test-thread-nocapture.run.stderr b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr index 06495681b3e..06495681b3e 100644 --- a/src/test/ui/test-thread-nocapture.run.stderr +++ b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr diff --git a/src/test/ui/test-thread-nocapture.run.stdout b/src/test/ui/test-attrs/test-thread-nocapture.run.stdout index 9d2da50826c..9d2da50826c 100644 --- a/src/test/ui/test-thread-nocapture.run.stdout +++ b/src/test/ui/test-attrs/test-thread-nocapture.run.stdout diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs index e186570167d..1be0b05fa2b 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -17,8 +17,8 @@ pub struct Second { d: Vec<First>, } -struct Third<f> { - g: Vec<f>, +struct Third<'a, f> { + g: Vec<(f, &'a f)>, } enum Ty { @@ -38,29 +38,29 @@ struct Sixth { } #[rustc_evaluate_where_clauses] -fn forward() +fn forward<'a>() where Vec<First>: Unpin, - Third<Ty>: Unpin, + Third<'a, Ty>: Unpin, { } #[rustc_evaluate_where_clauses] -fn reverse() +fn reverse<'a>() where - Third<Ty>: Unpin, + Third<'a, Ty>: Unpin, Vec<First>: Unpin, { } fn main() { - // Key is that Vec<First> is "ok" and Third<Ty> is "ok modulo regions": + // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions": forward(); //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) reverse(); //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) } diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr index bfe3e76b214..43acc66fd73 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -7,20 +7,20 @@ LL | Vec<First>: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | -LL | Third<Ty>: Unpin, - | ----- predicate +LL | Third<'a, Ty>: Unpin, + | ----- predicate ... LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate(<Third<Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | -LL | Third<Ty>: Unpin, - | ----- predicate +LL | Third<'a, Ty>: Unpin, + | ----- predicate ... LL | reverse(); | ^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr b/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr new file mode 100644 index 00000000000..71cc6f61c37 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr @@ -0,0 +1,11 @@ +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-69323.rs:5:27 + | +LL | #![cfg_attr(full, feature(type_alias_impl_trait))] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.rs b/src/test/ui/type-alias-impl-trait/issue-69323.rs new file mode 100644 index 00000000000..824558c1b34 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-69323.rs @@ -0,0 +1,19 @@ +// check-pass + +// revisions: min full +#![feature(min_type_alias_impl_trait)] +#![cfg_attr(full, feature(type_alias_impl_trait))] +//[full]~^ WARN incomplete + +use std::iter::{once, Chain}; + +fn test1<A: Iterator<Item = &'static str>>(x: A) -> Chain<A, impl Iterator<Item = &'static str>> { + x.chain(once(",")) +} + +type I<A> = Chain<A, impl Iterator<Item = &'static str>>; +fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> { + x.chain(once(",")) +} + +fn main() {} diff --git a/src/test/ui/conversion-methods.rs b/src/test/ui/typeck/conversion-methods.rs index 46c2e511f33..46c2e511f33 100644 --- a/src/test/ui/conversion-methods.rs +++ b/src/test/ui/typeck/conversion-methods.rs diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/typeck/conversion-methods.stderr index 4f47e1fd0ff..4f47e1fd0ff 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/typeck/conversion-methods.stderr diff --git a/src/test/ui/typeck/issue-84160.rs b/src/test/ui/typeck/issue-84160.rs new file mode 100644 index 00000000000..7b444df8528 --- /dev/null +++ b/src/test/ui/typeck/issue-84160.rs @@ -0,0 +1,9 @@ +fn mismatched_types_with_reference(x: &u32) -> &u32 { + if false { + return x; + } + return "test"; + //~^ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-84160.stderr b/src/test/ui/typeck/issue-84160.stderr new file mode 100644 index 00000000000..24c188b3fcb --- /dev/null +++ b/src/test/ui/typeck/issue-84160.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-84160.rs:5:12 + | +LL | fn mismatched_types_with_reference(x: &u32) -> &u32 { + | ---- expected `&u32` because of return type +... +LL | return "test"; + | ^^^^^^ expected `u32`, found `str` + | + = note: expected reference `&u32` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr new file mode 100644 index 00000000000..b1111fcf148 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:9:22 + | +LL | const U: usize = return; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr new file mode 100644 index 00000000000..f489ae2002a --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:15:20 + | +LL | fn foo(a: [(); return]); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rs b/src/test/ui/typeck/issue-86721-return-expr-ice.rs new file mode 100644 index 00000000000..cd7135f18b1 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rs @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #86721. + +// revisions: rev1 rev2 +#![cfg_attr(any(), rev1, rev2)] +#![crate_type="lib"] + +#[cfg(any(rev1))] +trait T { + const U: usize = return; + //[rev1]~^ ERROR: return statement outside of function body [E0572] +} + +#[cfg(any(rev2))] +trait T2 { + fn foo(a: [(); return]); + //[rev2]~^ ERROR: return statement outside of function body [E0572] +} diff --git a/src/test/ui/unsized/unsized3-rpass.rs b/src/test/ui/unsized/unsized3-rpass.rs index 65efbd6b520..c5c5ed26c73 100644 --- a/src/test/ui/unsized/unsized3-rpass.rs +++ b/src/test/ui/unsized/unsized3-rpass.rs @@ -1,12 +1,11 @@ // run-pass // Test structs with always-unsized fields. - #![allow(warnings)] -#![feature(box_syntax, unsize, raw)] +#![feature(box_syntax, unsize, ptr_metadata)] use std::mem; -use std::raw; +use std::ptr; use std::slice; struct Foo<T> { @@ -28,7 +27,7 @@ trait Tr { } struct St { - f: usize + f: usize, } impl Tr for St { @@ -38,7 +37,7 @@ impl Tr for St { } struct Qux<'a> { - f: Tr+'a + f: Tr + 'a, } pub fn main() { @@ -56,10 +55,10 @@ pub fn main() { unsafe { struct Foo_<T> { - f: [T; 3] + f: [T; 3], } - let data: Box<Foo_<i32>> = box Foo_{f: [1, 2, 3] }; + let data: Box<Foo_<i32>> = box Foo_ { f: [1, 2, 3] }; let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3)); assert_eq!(x.f.len(), 3); assert_eq!(x.f[0], 1); @@ -69,8 +68,8 @@ pub fn main() { f2: [u8; 5], } - let data: Box<_> = box Baz_ { - f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; + let data: Box<_> = + box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); assert_eq!(x.f1, 42); let chs: Vec<char> = x.f2.chars().collect(); @@ -82,15 +81,13 @@ pub fn main() { assert_eq!(chs[4], 'e'); struct Qux_ { - f: St + f: St, } let obj: Box<St> = box St { f: 42 }; let obj: &Tr = &*obj; - let obj: raw::TraitObject = mem::transmute(&*obj); - let data: Box<_> = box Qux_{ f: St { f: 234 } }; - let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable, - data: mem::transmute(&*data) }); + let data: Box<_> = box Qux_ { f: St { f: 234 } }; + let x: &Qux = &*ptr::from_raw_parts::<Qux>((&*data as *const _).cast(), ptr::metadata(obj)); assert_eq!(x.f.foo(), 234); } } diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/unused/unused-doc-comments-edge-cases.rs new file mode 100644 index 00000000000..fd9baf8c6b9 --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-edge-cases.rs @@ -0,0 +1,29 @@ +#![deny(unused_doc_comments)] + +fn doc_comment_on_match_arms(num: u8) -> bool { + match num { + 3 => true, + /// useless doc comment + //~^ ERROR: unused doc comment + _ => false, + } +} + +fn doc_comment_between_if_else(num: u8) -> bool { + if num == 3 { + true //~ ERROR: mismatched types + } + /// useless doc comment + else { //~ ERROR: expected expression, found keyword `else` + false + } +} + +fn doc_comment_on_expr(num: u8) -> bool { + /// useless doc comment + //~^ ERROR: attributes on expressions are experimental + //~| ERROR: unused doc comment + num == 3 +} + +fn main() {} diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr new file mode 100644 index 00000000000..14db5f64b0c --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr @@ -0,0 +1,61 @@ +error: expected expression, found keyword `else` + --> $DIR/unused-doc-comments-edge-cases.rs:17:5 + | +LL | else { + | ^^^^ expected expression + +error[E0658]: attributes on expressions are experimental + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = help: `///` is for documentation comments. For a plain comment, use `//`. + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:6:9 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | _ => false, + | ---------- rustdoc does not generate documentation for match arms + | +note: the lint level is defined here + --> $DIR/unused-doc-comments-edge-cases.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | num == 3 + | --- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error[E0308]: mismatched types + --> $DIR/unused-doc-comments-edge-cases.rs:14:9 + | +LL | / if num == 3 { +LL | | true + | | ^^^^ expected `()`, found `bool` +LL | | } + | |_____- expected this to be `()` + | +help: you might have meant to return this value + | +LL | return true; + | ^^^^^^ ^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/unused/useless-comment.stderr b/src/test/ui/unused/useless-comment.stderr index 5a0af8db7c5..0054426fb1e 100644 --- a/src/test/ui/unused/useless-comment.stderr +++ b/src/test/ui/unused/useless-comment.stderr @@ -26,6 +26,8 @@ LL | /// a | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | let x = 12; | ----------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:16:5 @@ -40,6 +42,8 @@ LL | | 1 => {}, LL | | _ => {} LL | | } | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:20:9 @@ -48,6 +52,8 @@ LL | /// c | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | 1 => {}, | ------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:25:5 @@ -56,6 +62,8 @@ LL | /// foo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | unsafe {} | --------- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:28:5 @@ -65,6 +73,8 @@ LL | #[doc = "foo"] LL | #[doc = "bar"] LL | 3; | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:29:5 @@ -73,12 +83,16 @@ LL | #[doc = "bar"] | ^^^^^^^^^^^^^^ LL | 3; | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:35:13 | LL | let x = /** comment */ 47; | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions + | + = help: use `/* */` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:37:5 @@ -89,6 +103,8 @@ LL | / { LL | | LL | | } | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: aborting due to 10 previous errors diff --git a/src/test/ui/write-fmt-errors.rs b/src/test/ui/write-fmt-errors.rs index 7dd98564425..3fcaefaa63e 100644 --- a/src/test/ui/write-fmt-errors.rs +++ b/src/test/ui/write-fmt-errors.rs @@ -1,5 +1,7 @@ // run-pass +#![feature(io_error_uncategorized)] + use std::fmt; use std::io::{self, Error, Write, sink}; @@ -13,7 +15,7 @@ impl fmt::Display for ErrorDisplay { struct ErrorWriter; -const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Other; +const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized; const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected; impl Write for ErrorWriter { diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 9233aa06c801801cff75df65df718d70905a235 +Subproject 3ebb5f15a940810f250b68821149387af583a79 diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml index 32103f59d8b..d856c55a41a 100644 --- a/src/tools/clippy/.github/workflows/clippy.yml +++ b/src/tools/clippy/.github/workflows/clippy.yml @@ -71,7 +71,7 @@ jobs: working-directory: clippy_workspace_tests - name: Test cargo-clippy --fix - run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options + run: ../target/debug/cargo-clippy clippy --fix working-directory: clippy_workspace_tests - name: Test clippy-driver diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index f27fee87dc1..146b6fccd0c 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -90,11 +90,6 @@ jobs: - name: Checkout uses: actions/checkout@v2.3.3 - # FIXME: should not be necessary once 1.24.2 is the default version on the windows runner - - name: Update rustup - run: rustup self update - if: runner.os == 'Windows' - - name: Install toolchain run: rustup show active-toolchain @@ -139,7 +134,7 @@ jobs: working-directory: clippy_workspace_tests - name: Test cargo-clippy --fix - run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options + run: ../target/debug/cargo-clippy clippy --fix working-directory: clippy_workspace_tests - name: Test clippy-driver diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index 4f25a86b2e4..77efdec1e50 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-node@v1.4.4 - name: Install remark - run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended + run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm # Run - name: Check *.md files diff --git a/src/tools/clippy/.remarkrc b/src/tools/clippy/.remarkrc index 0ede7ac75cb..04b82b8cc58 100644 --- a/src/tools/clippy/.remarkrc +++ b/src/tools/clippy/.remarkrc @@ -1,6 +1,7 @@ { "plugins": [ "remark-preset-lint-recommended", + "remark-gfm", ["remark-lint-list-item-indent", false], ["remark-lint-no-literal-urls", false], ["remark-lint-no-shortcut-reference-link", false], diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 41af8e190dd..f3a80703238 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,139 @@ document. ## Unreleased / In Rust Nightly -[7c7683c...master](https://github.com/rust-lang/rust-clippy/compare/7c7683c...master) +[3ae8faf...master](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...master) + +## Rust 1.54 + +Current beta, release 2021-07-29 + +[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf) + +### New Lints + +- [`ref_binding_to_reference`] + [#7105](https://github.com/rust-lang/rust-clippy/pull/7105) +- [`needless_bitwise_bool`] + [#7133](https://github.com/rust-lang/rust-clippy/pull/7133) +- [`unused_async`] [#7225](https://github.com/rust-lang/rust-clippy/pull/7225) +- [`manual_str_repeat`] + [#7265](https://github.com/rust-lang/rust-clippy/pull/7265) +- [`suspicious_splitn`] + [#7292](https://github.com/rust-lang/rust-clippy/pull/7292) + +### Moves and Deprecations + +- Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of + the new `avoid_breaking_exported_api` config option (see + [Enhancements](#1-54-enhancements)) + [#7187](https://github.com/rust-lang/rust-clippy/pull/7187) +- Move [`inconsistent_struct_constructor`] to `pedantic` + [#7193](https://github.com/rust-lang/rust-clippy/pull/7193) +- Move [`needless_borrow`] to `style` (now warn-by-default) + [#7254](https://github.com/rust-lang/rust-clippy/pull/7254) +- Move [`suspicious_operation_groupings`] to `nursery` + [#7266](https://github.com/rust-lang/rust-clippy/pull/7266) +- Move [`semicolon_if_nothing_returned`] to `pedantic` + [#7268](https://github.com/rust-lang/rust-clippy/pull/7268) + +### Enhancements <a name="1-54-enhancements"></a> + +- [`while_let_on_iterator`]: Now also lints in nested loops + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`single_char_pattern`]: Now also lints on `strip_prefix` and `strip_suffix` + [#7156](https://github.com/rust-lang/rust-clippy/pull/7156) +- [`needless_collect`]: Now also lints on assignments with type annotations + [#7163](https://github.com/rust-lang/rust-clippy/pull/7163) +- [`if_then_some_else_none`]: Now works with the MSRV config + [#7177](https://github.com/rust-lang/rust-clippy/pull/7177) +- Add `avoid_breaking_exported_api` config option for the lints + [`enum_variant_names`], [`large_types_passed_by_value`], + [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`], + [`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set + this configuration option to `false` before a major release (1.0/2.0/...) to + clean up the API [#7187](https://github.com/rust-lang/rust-clippy/pull/7187) +- [`needless_collect`]: Now lints on even more data structures + [#7188](https://github.com/rust-lang/rust-clippy/pull/7188) +- [`missing_docs_in_private_items`]: No longer sees `#[<name> = "<value>"]` like + attributes as sufficient documentation + [#7281](https://github.com/rust-lang/rust-clippy/pull/7281) +- [`needless_collect`], [`short_circuit_statement`], [`unnecessary_operation`]: + Now work as expected when used with `allow` + [#7282](https://github.com/rust-lang/rust-clippy/pull/7282) + +### False Positive Fixes + +- [`implicit_return`]: Now takes all diverging functions in account to avoid + false positives [#6951](https://github.com/rust-lang/rust-clippy/pull/6951) +- [`while_let_on_iterator`]: No longer lints when the iterator is a struct field + and the struct is used in the loop + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`multiple_inherent_impl`]: No longer lints with generic arguments + [#7089](https://github.com/rust-lang/rust-clippy/pull/7089) +- [`comparison_chain`]: No longer lints in a `const` context + [#7118](https://github.com/rust-lang/rust-clippy/pull/7118) +- [`while_immutable_condition`]: Fix false positive where mutation in the loop + variable wasn't picked up + [#7144](https://github.com/rust-lang/rust-clippy/pull/7144) +- [`default_trait_access`]: No longer lints in macros + [#7150](https://github.com/rust-lang/rust-clippy/pull/7150) +- [`needless_question_mark`]: No longer lints when the inner value is implicitly + dereferenced [#7165](https://github.com/rust-lang/rust-clippy/pull/7165) +- [`unused_unit`]: No longer lints when multiple macro contexts are involved + [#7167](https://github.com/rust-lang/rust-clippy/pull/7167) +- [`eval_order_dependence`]: Fix false positive in async context + [#7174](https://github.com/rust-lang/rust-clippy/pull/7174) +- [`unnecessary_filter_map`]: No longer lints if the `filter_map` changes the + type [#7175](https://github.com/rust-lang/rust-clippy/pull/7175) +- [`wrong_self_convention`]: No longer lints in trait implementations of + non-`Copy` types [#7182](https://github.com/rust-lang/rust-clippy/pull/7182) +- [`suboptimal_flops`]: No longer lints on `powi(2)` + [#7201](https://github.com/rust-lang/rust-clippy/pull/7201) +- [`wrong_self_convention`]: No longer lints if there is no implicit `self` + [#7215](https://github.com/rust-lang/rust-clippy/pull/7215) +- [`option_if_let_else`]: No longer lints on `else if let` pattern + [#7216](https://github.com/rust-lang/rust-clippy/pull/7216) +- [`use_self`], [`useless_conversion`]: Fix false positives when generic + arguments are involved + [#7223](https://github.com/rust-lang/rust-clippy/pull/7223) +- [`manual_unwrap_or`]: Fix false positive with deref coercion + [#7233](https://github.com/rust-lang/rust-clippy/pull/7233) +- [`similar_names`]: No longer lints on `wparam`/`lparam` + [#7255](https://github.com/rust-lang/rust-clippy/pull/7255) +- [`redundant_closure`]: No longer lints on using the `vec![]` macro in a + closure [#7263](https://github.com/rust-lang/rust-clippy/pull/7263) + +### Suggestion Fixes/Improvements + +- [`implicit_return`] + [#6951](https://github.com/rust-lang/rust-clippy/pull/6951) + - Fix suggestion for async functions + - Improve suggestion with macros + - Suggest to change `break` to `return` when appropriate +- [`while_let_on_iterator`]: Now suggests `&mut iter` when necessary + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`match_single_binding`]: Improve suggestion when match scrutinee has side + effects [#7095](https://github.com/rust-lang/rust-clippy/pull/7095) +- [`needless_borrow`]: Now suggests to also change usage sites as needed + [#7105](https://github.com/rust-lang/rust-clippy/pull/7105) +- [`write_with_newline`]: Improve suggestion when only `\n` is written to the + buffer [#7183](https://github.com/rust-lang/rust-clippy/pull/7183) +- [`from_iter_instead_of_collect`]: The suggestion is now auto applicable also + when a `<_ as Trait>::_` is involved + [#7264](https://github.com/rust-lang/rust-clippy/pull/7264) +- [`not_unsafe_ptr_arg_deref`]: Improved error message + [#7294](https://github.com/rust-lang/rust-clippy/pull/7294) + +### ICE Fixes + +- Fix ICE when running Clippy on `libstd` + [#7140](https://github.com/rust-lang/rust-clippy/pull/7140) +- [`implicit_return`] + [#7242](https://github.com/rust-lang/rust-clippy/pull/7242) ## Rust 1.53 -Current beta, release 2021-06-17 +Current stable, released 2021-06-17 [6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c) @@ -194,7 +322,7 @@ Current beta, release 2021-06-17 ## Rust 1.52 -Current stable, released 2021-05-06 +Released 2021-05-06 [3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e) @@ -2295,6 +2423,7 @@ Released 2018-09-13 <!-- begin autogenerated links to lint list --> [`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped +[`append_instead_of_extend`]: https://rust-lang.github.io/rust-clippy/master/index.html#append_instead_of_extend [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions [`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants @@ -2358,6 +2487,8 @@ Released 2018-09-13 [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method +[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents +[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons @@ -2527,6 +2658,7 @@ Released 2018-09-13 [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items +[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames [`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc @@ -2574,6 +2706,7 @@ Released 2018-09-13 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options +[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index 7d7b7c81173..4273fda4e64 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -115,7 +115,7 @@ To work around this, you need to have a copy of the [rustc-repo][rustc_repo] ava `git clone https://github.com/rust-lang/rust/`. Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies which `IntelliJ Rust` will be able to understand. -Run `cargo dev ide_setup --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo +Run `cargo dev setup intellij --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo you just cloned. The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to Clippys `Cargo.toml`s and should allow `IntelliJ Rust` to understand most of the types that Clippy uses. diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index b003b15a11d..9b5d9b2adf3 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.54" +version = "0.1.55" authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index bd322cc8070..e1c968273cd 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -10,16 +10,17 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. -| Category | Description | Default level | -| --------------------- | ----------------------------------------------------------------------- | ------------- | -| `clippy::all` | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny** | -| `clippy::correctness` | code that is outright wrong or very useless | **deny** | -| `clippy::style` | code that should be written in a more idiomatic way | **warn** | -| `clippy::complexity` | code that does something simple but in a complex way | **warn** | -| `clippy::perf` | code that can be written to run faster | **warn** | -| `clippy::pedantic` | lints which are rather strict or might have false positives | allow | -| `clippy::nursery` | new lints that are still under development | allow | -| `clippy::cargo` | lints for the cargo manifest | allow | +| Category | Description | Default level | +| --------------------- | ----------------------------------------------------------------------------------- | ------------- | +| `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** | +| `clippy::correctness` | code that is outright wrong or useless | **deny** | +| `clippy::suspicious` | code that is most likely wrong or useless | **warn** | +| `clippy::style` | code that should be written in a more idiomatic way | **warn** | +| `clippy::complexity` | code that does something simple but in a complex way | **warn** | +| `clippy::perf` | code that can be written to run faster | **warn** | +| `clippy::pedantic` | lints which are rather strict or might have false positives | allow | +| `clippy::nursery` | new lints that are still under development | allow | +| `clippy::cargo` | lints for the cargo manifest | allow | More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas! @@ -75,11 +76,10 @@ cargo clippy #### Automatically applying Clippy suggestions -Clippy can automatically apply some lint suggestions. -Note that this is still experimental and only supported on the nightly channel: +Clippy can automatically apply some lint suggestions, just like the compiler. ```terminal -cargo clippy --fix -Z unstable-options +cargo clippy --fix ``` #### Workspaces diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index b1844e29b32..5c6c106e0e6 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" bytecount = "0.6" clap = "2.33" itertools = "0.9" -opener = "0.4" +opener = "0.5" regex = "1" shell-escape = "0.1" walkdir = "2" diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs index 1517cdc9419..c81eb40d52f 100644 --- a/src/tools/clippy/clippy_dev/src/fmt.rs +++ b/src/tools/clippy/clippy_dev/src/fmt.rs @@ -60,11 +60,7 @@ pub fn run(check: bool, verbose: bool) { let entry = entry?; let path = entry.path(); - if path.extension() != Some("rs".as_ref()) - || entry.file_name() == "ice-3891.rs" - // Avoid rustfmt bug rust-lang/rustfmt#1873 - || cfg!(windows) && entry.file_name() == "implicit_hasher.rs" - { + if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { continue; } @@ -90,7 +86,7 @@ pub fn run(check: bool, verbose: bool) { }, CliError::RaSetupActive => { eprintln!( - "error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`. + "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`. Not formatting because that would format the local repo as well! Please revert the changes to Cargo.tomls first." ); diff --git a/src/tools/clippy/clippy_dev/src/ide_setup.rs b/src/tools/clippy/clippy_dev/src/ide_setup.rs deleted file mode 100644 index defb1133e44..00000000000 --- a/src/tools/clippy/clippy_dev/src/ide_setup.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::fs; -use std::fs::File; -use std::io::prelude::*; -use std::path::{Path, PathBuf}; - -// This module takes an absolute path to a rustc repo and alters the dependencies to point towards -// the respective rustc subcrates instead of using extern crate xyz. -// This allows rust analyzer to analyze rustc internals and show proper information inside clippy -// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details - -/// # Panics -/// -/// Panics if `rustc_path` does not lead to a rustc repo or the files could not be read -pub fn run(rustc_path: Option<&str>) { - // we can unwrap here because the arg is required by clap - let rustc_path = PathBuf::from(rustc_path.unwrap()) - .canonicalize() - .expect("failed to get the absolute repo path"); - assert!(rustc_path.is_dir(), "path is not a directory"); - let rustc_source_basedir = rustc_path.join("compiler"); - assert!( - rustc_source_basedir.is_dir(), - "are you sure the path leads to a rustc repo?" - ); - - let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml"); - let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs"); - inject_deps_into_manifest( - &rustc_source_basedir, - "Cargo.toml", - &clippy_root_manifest, - &clippy_root_lib_rs, - ) - .expect("Failed to inject deps into ./Cargo.toml"); - - let clippy_lints_manifest = - fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml"); - let clippy_lints_lib_rs = - fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs"); - inject_deps_into_manifest( - &rustc_source_basedir, - "clippy_lints/Cargo.toml", - &clippy_lints_manifest, - &clippy_lints_lib_rs, - ) - .expect("Failed to inject deps into ./clippy_lints/Cargo.toml"); -} - -fn inject_deps_into_manifest( - rustc_source_dir: &Path, - manifest_path: &str, - cargo_toml: &str, - lib_rs: &str, -) -> std::io::Result<()> { - // do not inject deps if we have aleady done so - if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") { - eprintln!( - "cargo dev ide_setup: warning: deps already found inside {}, doing nothing.", - manifest_path - ); - return Ok(()); - } - - let extern_crates = lib_rs - .lines() - // get the deps - .filter(|line| line.starts_with("extern crate")) - // we have something like "extern crate foo;", we only care about the "foo" - // ↓ ↓ - // extern crate rustc_middle; - .map(|s| &s[13..(s.len() - 1)]); - - let new_deps = extern_crates.map(|dep| { - // format the dependencies that are going to be put inside the Cargo.toml - format!( - "{dep} = {{ path = \"{source_path}/{dep}\" }}\n", - dep = dep, - source_path = rustc_source_dir.display() - ) - }); - - // format a new [dependencies]-block with the new deps we need to inject - let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n"); - new_deps.for_each(|dep_line| { - all_deps.push_str(&dep_line); - }); - all_deps.push_str("\n[dependencies]\n"); - - // replace "[dependencies]" with - // [dependencies] - // dep1 = { path = ... } - // dep2 = { path = ... } - // etc - let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); - - // println!("{}", new_manifest); - let mut file = File::create(manifest_path)?; - file.write_all(new_manifest.as_bytes())?; - - println!("Dependency paths injected: {}", manifest_path); - - Ok(()) -} diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 69f42aca8b6..72bdaf8d592 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -14,9 +14,9 @@ use walkdir::WalkDir; pub mod bless; pub mod fmt; -pub mod ide_setup; pub mod new_lint; pub mod serve; +pub mod setup; pub mod stderr_length_check; pub mod update_lints; diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 7040c257c83..ff324ff6ee6 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -2,8 +2,8 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use clap::{App, Arg, ArgMatches, SubCommand}; -use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints}; +use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; +use clippy_dev::{bless, fmt, new_lint, serve, setup, stderr_length_check, update_lints}; fn main() { let matches = get_clap_config(); @@ -36,7 +36,22 @@ fn main() { ("limit_stderr_length", _) => { stderr_length_check::check(); }, - ("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")), + ("setup", Some(sub_command)) => match sub_command.subcommand() { + ("intellij", Some(matches)) => setup::intellij::setup_rustc_src( + matches + .value_of("rustc-repo-path") + .expect("this field is mandatory and therefore always valid"), + ), + ("git-hook", Some(matches)) => setup::git_hook::install_hook(matches.is_present("force-override")), + ("vscode-tasks", Some(matches)) => setup::vscode::install_tasks(matches.is_present("force-override")), + _ => {}, + }, + ("remove", Some(sub_command)) => match sub_command.subcommand() { + ("git-hook", Some(_)) => setup::git_hook::remove_hook(), + ("intellij", Some(_)) => setup::intellij::remove_rustc_src(), + ("vscode-tasks", Some(_)) => setup::vscode::remove_tasks(), + _ => {}, + }, ("serve", Some(matches)) => { let port = matches.value_of("port").unwrap().parse().unwrap(); let lint = matches.value_of("lint"); @@ -48,6 +63,7 @@ fn main() { fn get_clap_config<'a>() -> ArgMatches<'a> { App::new("Clippy developer tooling") + .setting(AppSettings::ArgRequiredElseHelp) .subcommand( SubCommand::with_name("bless") .about("bless the test output changes") @@ -123,6 +139,7 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .possible_values(&[ "style", "correctness", + "suspicious", "complexity", "perf", "pedantic", @@ -140,16 +157,54 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .about("Ensures that stderr files do not grow longer than a certain amount of lines."), ) .subcommand( - SubCommand::with_name("ide_setup") - .about("Alter dependencies so Intellij Rust can find rustc internals") - .arg( - Arg::with_name("rustc-repo-path") - .long("repo-path") - .short("r") - .help("The path to a rustc repo that will be used for setting the dependencies") - .takes_value(true) - .value_name("path") - .required(true), + SubCommand::with_name("setup") + .about("Support for setting up your personal development environment") + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand( + SubCommand::with_name("intellij") + .about("Alter dependencies so Intellij Rust can find rustc internals") + .arg( + Arg::with_name("rustc-repo-path") + .long("repo-path") + .short("r") + .help("The path to a rustc repo that will be used for setting the dependencies") + .takes_value(true) + .value_name("path") + .required(true), + ), + ) + .subcommand( + SubCommand::with_name("git-hook") + .about("Add a pre-commit git hook that formats your code to make it look pretty") + .arg( + Arg::with_name("force-override") + .long("force-override") + .short("f") + .help("Forces the override of an existing git pre-commit hook") + .required(false), + ), + ) + .subcommand( + SubCommand::with_name("vscode-tasks") + .about("Add several tasks to vscode for formatting, validation and testing") + .arg( + Arg::with_name("force-override") + .long("force-override") + .short("f") + .help("Forces the override of existing vscode tasks") + .required(false), + ), + ), + ) + .subcommand( + SubCommand::with_name("remove") + .about("Support for undoing changes done by the setup command") + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand(SubCommand::with_name("git-hook").about("Remove any existing pre-commit git hook")) + .subcommand(SubCommand::with_name("vscode-tasks").about("Remove any existing vscode tasks")) + .subcommand( + SubCommand::with_name("intellij") + .about("Removes rustc source paths added via `cargo dev setup intellij`"), ), ) .subcommand( diff --git a/src/tools/clippy/clippy_dev/src/setup/git_hook.rs b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs new file mode 100644 index 00000000000..3fbb77d5923 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs @@ -0,0 +1,85 @@ +use std::fs; +use std::path::Path; + +use super::verify_inside_clippy_dir; + +/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo. +/// I've decided against this for the sake of simplicity and to make sure that it doesn't install +/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool +/// for formatting and should therefor only be used in a normal clone of clippy +const REPO_GIT_DIR: &str = ".git"; +const HOOK_SOURCE_FILE: &str = "util/etc/pre-commit.sh"; +const HOOK_TARGET_FILE: &str = ".git/hooks/pre-commit"; + +pub fn install_hook(force_override: bool) { + if !check_precondition(force_override) { + return; + } + + // So a little bit of a funny story. Git on unix requires the pre-commit file + // to have the `execute` permission to be set. The Rust functions for modifying + // these flags doesn't seem to work when executed with normal user permissions. + // + // However, there is a little hack that is also being used by Rust itself in their + // setup script. Git saves the `execute` flag when syncing files. This means + // that we can check in a file with execution permissions and the sync it to create + // a file with the flag set. We then copy this file here. The copy function will also + // include the `execute` permission. + match fs::copy(HOOK_SOURCE_FILE, HOOK_TARGET_FILE) { + Ok(_) => { + println!("info: the hook can be removed with `cargo dev remove git-hook`"); + println!("git hook successfully installed"); + }, + Err(err) => eprintln!( + "error: unable to copy `{}` to `{}` ({})", + HOOK_SOURCE_FILE, HOOK_TARGET_FILE, err + ), + } +} + +fn check_precondition(force_override: bool) -> bool { + if !verify_inside_clippy_dir() { + return false; + } + + // Make sure that we can find the git repository + let git_path = Path::new(REPO_GIT_DIR); + if !git_path.exists() || !git_path.is_dir() { + eprintln!("error: clippy_dev was unable to find the `.git` directory"); + return false; + } + + // Make sure that we don't override an existing hook by accident + let path = Path::new(HOOK_TARGET_FILE); + if path.exists() { + if force_override { + return delete_git_hook_file(path); + } + + eprintln!("error: there is already a pre-commit hook installed"); + println!("info: use the `--force-override` flag to override the existing hook"); + return false; + } + + true +} + +pub fn remove_hook() { + let path = Path::new(HOOK_TARGET_FILE); + if path.exists() { + if delete_git_hook_file(path) { + println!("git hook successfully removed"); + } + } else { + println!("no pre-commit hook was found"); + } +} + +fn delete_git_hook_file(path: &Path) -> bool { + if let Err(err) = fs::remove_file(path) { + eprintln!("error: unable to delete existing pre-commit git hook ({})", err); + false + } else { + true + } +} diff --git a/src/tools/clippy/clippy_dev/src/setup/intellij.rs b/src/tools/clippy/clippy_dev/src/setup/intellij.rs new file mode 100644 index 00000000000..bf741e6d121 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/intellij.rs @@ -0,0 +1,223 @@ +use std::fs; +use std::fs::File; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; + +// This module takes an absolute path to a rustc repo and alters the dependencies to point towards +// the respective rustc subcrates instead of using extern crate xyz. +// This allows IntelliJ to analyze rustc internals and show proper information inside Clippy +// code. See https://github.com/rust-lang/rust-clippy/issues/5514 for details + +const RUSTC_PATH_SECTION: &str = "[target.'cfg(NOT_A_PLATFORM)'.dependencies]"; +const DEPENDENCIES_SECTION: &str = "[dependencies]"; + +const CLIPPY_PROJECTS: &[ClippyProjectInfo] = &[ + ClippyProjectInfo::new("root", "Cargo.toml", "src/driver.rs"), + ClippyProjectInfo::new("clippy_lints", "clippy_lints/Cargo.toml", "clippy_lints/src/lib.rs"), + ClippyProjectInfo::new("clippy_utils", "clippy_utils/Cargo.toml", "clippy_utils/src/lib.rs"), +]; + +/// Used to store clippy project information to later inject the dependency into. +struct ClippyProjectInfo { + /// Only used to display information to the user + name: &'static str, + cargo_file: &'static str, + lib_rs_file: &'static str, +} + +impl ClippyProjectInfo { + const fn new(name: &'static str, cargo_file: &'static str, lib_rs_file: &'static str) -> Self { + Self { + name, + cargo_file, + lib_rs_file, + } + } +} + +pub fn setup_rustc_src(rustc_path: &str) { + let rustc_source_dir = match check_and_get_rustc_dir(rustc_path) { + Ok(path) => path, + Err(_) => return, + }; + + for project in CLIPPY_PROJECTS { + if inject_deps_into_project(&rustc_source_dir, project).is_err() { + return; + } + } + + println!("info: the source paths can be removed again with `cargo dev remove intellij`"); +} + +fn check_and_get_rustc_dir(rustc_path: &str) -> Result<PathBuf, ()> { + let mut path = PathBuf::from(rustc_path); + + if path.is_relative() { + match path.canonicalize() { + Ok(absolute_path) => { + println!("info: the rustc path was resolved to: `{}`", absolute_path.display()); + path = absolute_path; + }, + Err(err) => { + eprintln!("error: unable to get the absolute path of rustc ({})", err); + return Err(()); + }, + }; + } + + let path = path.join("compiler"); + println!("info: looking for compiler sources at: {}", path.display()); + + if !path.exists() { + eprintln!("error: the given path does not exist"); + return Err(()); + } + + if !path.is_dir() { + eprintln!("error: the given path is not a directory"); + return Err(()); + } + + Ok(path) +} + +fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo) -> Result<(), ()> { + let cargo_content = read_project_file(project.cargo_file)?; + let lib_content = read_project_file(project.lib_rs_file)?; + + if inject_deps_into_manifest(rustc_source_dir, project.cargo_file, &cargo_content, &lib_content).is_err() { + eprintln!( + "error: unable to inject dependencies into {} with the Cargo file {}", + project.name, project.cargo_file + ); + Err(()) + } else { + Ok(()) + } +} + +/// `clippy_dev` expects to be executed in the root directory of Clippy. This function +/// loads the given file or returns an error. Having it in this extra function ensures +/// that the error message looks nice. +fn read_project_file(file_path: &str) -> Result<String, ()> { + let path = Path::new(file_path); + if !path.exists() { + eprintln!("error: unable to find the file `{}`", file_path); + return Err(()); + } + + match fs::read_to_string(path) { + Ok(content) => Ok(content), + Err(err) => { + eprintln!("error: the file `{}` could not be read ({})", file_path, err); + Err(()) + }, + } +} + +fn inject_deps_into_manifest( + rustc_source_dir: &Path, + manifest_path: &str, + cargo_toml: &str, + lib_rs: &str, +) -> std::io::Result<()> { + // do not inject deps if we have already done so + if cargo_toml.contains(RUSTC_PATH_SECTION) { + eprintln!( + "warn: dependencies are already setup inside {}, skipping file", + manifest_path + ); + return Ok(()); + } + + let extern_crates = lib_rs + .lines() + // only take dependencies starting with `rustc_` + .filter(|line| line.starts_with("extern crate rustc_")) + // we have something like "extern crate foo;", we only care about the "foo" + // extern crate rustc_middle; + // ^^^^^^^^^^^^ + .map(|s| &s[13..(s.len() - 1)]); + + let new_deps = extern_crates.map(|dep| { + // format the dependencies that are going to be put inside the Cargo.toml + format!( + "{dep} = {{ path = \"{source_path}/{dep}\" }}\n", + dep = dep, + source_path = rustc_source_dir.display() + ) + }); + + // format a new [dependencies]-block with the new deps we need to inject + let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n"); + new_deps.for_each(|dep_line| { + all_deps.push_str(&dep_line); + }); + all_deps.push_str("\n[dependencies]\n"); + + // replace "[dependencies]" with + // [dependencies] + // dep1 = { path = ... } + // dep2 = { path = ... } + // etc + let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); + + // println!("{}", new_manifest); + let mut file = File::create(manifest_path)?; + file.write_all(new_manifest.as_bytes())?; + + println!("info: successfully setup dependencies inside {}", manifest_path); + + Ok(()) +} + +pub fn remove_rustc_src() { + for project in CLIPPY_PROJECTS { + remove_rustc_src_from_project(project); + } +} + +fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool { + let mut cargo_content = if let Ok(content) = read_project_file(project.cargo_file) { + content + } else { + return false; + }; + let section_start = if let Some(section_start) = cargo_content.find(RUSTC_PATH_SECTION) { + section_start + } else { + println!( + "info: dependencies could not be found in `{}` for {}, skipping file", + project.cargo_file, project.name + ); + return true; + }; + + let end_point = if let Some(end_point) = cargo_content.find(DEPENDENCIES_SECTION) { + end_point + } else { + eprintln!( + "error: the end of the rustc dependencies section could not be found in `{}`", + project.cargo_file + ); + return false; + }; + + cargo_content.replace_range(section_start..end_point, ""); + + match File::create(project.cargo_file) { + Ok(mut file) => { + file.write_all(cargo_content.as_bytes()).unwrap(); + println!("info: successfully removed dependencies inside {}", project.cargo_file); + true + }, + Err(err) => { + eprintln!( + "error: unable to open file `{}` to remove rustc dependencies for {} ({})", + project.cargo_file, project.name, err + ); + false + }, + } +} diff --git a/src/tools/clippy/clippy_dev/src/setup/mod.rs b/src/tools/clippy/clippy_dev/src/setup/mod.rs new file mode 100644 index 00000000000..a1e4dd103b8 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/mod.rs @@ -0,0 +1,23 @@ +pub mod git_hook; +pub mod intellij; +pub mod vscode; + +use std::path::Path; + +const CLIPPY_DEV_DIR: &str = "clippy_dev"; + +/// This function verifies that the tool is being executed in the clippy directory. +/// This is useful to ensure that setups only modify Clippys resources. The verification +/// is done by checking that `clippy_dev` is a sub directory of the current directory. +/// +/// It will print an error message and return `false` if the directory could not be +/// verified. +fn verify_inside_clippy_dir() -> bool { + let path = Path::new(CLIPPY_DEV_DIR); + if path.exists() && path.is_dir() { + true + } else { + eprintln!("error: unable to verify that the working directory is clippys directory"); + false + } +} diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs new file mode 100644 index 00000000000..d59001b2c66 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs @@ -0,0 +1,104 @@ +use std::fs; +use std::path::Path; + +use super::verify_inside_clippy_dir; + +const VSCODE_DIR: &str = ".vscode"; +const TASK_SOURCE_FILE: &str = "util/etc/vscode-tasks.json"; +const TASK_TARGET_FILE: &str = ".vscode/tasks.json"; + +pub fn install_tasks(force_override: bool) { + if !check_install_precondition(force_override) { + return; + } + + match fs::copy(TASK_SOURCE_FILE, TASK_TARGET_FILE) { + Ok(_) => { + println!("info: the task file can be removed with `cargo dev remove vscode-tasks`"); + println!("vscode tasks successfully installed"); + }, + Err(err) => eprintln!( + "error: unable to copy `{}` to `{}` ({})", + TASK_SOURCE_FILE, TASK_TARGET_FILE, err + ), + } +} + +fn check_install_precondition(force_override: bool) -> bool { + if !verify_inside_clippy_dir() { + return false; + } + + let vs_dir_path = Path::new(VSCODE_DIR); + if vs_dir_path.exists() { + // verify the target will be valid + if !vs_dir_path.is_dir() { + eprintln!("error: the `.vscode` path exists but seems to be a file"); + return false; + } + + // make sure that we don't override any existing tasks by accident + let path = Path::new(TASK_TARGET_FILE); + if path.exists() { + if force_override { + return delete_vs_task_file(path); + } + + eprintln!( + "error: there is already a `task.json` file inside the `{}` directory", + VSCODE_DIR + ); + println!("info: use the `--force-override` flag to override the existing `task.json` file"); + return false; + } + } else { + match fs::create_dir(vs_dir_path) { + Ok(_) => { + println!("info: created `{}` directory for clippy", VSCODE_DIR); + }, + Err(err) => { + eprintln!( + "error: the task target directory `{}` could not be created ({})", + VSCODE_DIR, err + ); + }, + } + } + + true +} + +pub fn remove_tasks() { + let path = Path::new(TASK_TARGET_FILE); + if path.exists() { + if delete_vs_task_file(path) { + try_delete_vs_directory_if_empty(); + println!("vscode tasks successfully removed"); + } + } else { + println!("no vscode tasks were found"); + } +} + +fn delete_vs_task_file(path: &Path) -> bool { + if let Err(err) = fs::remove_file(path) { + eprintln!("error: unable to delete the existing `tasks.json` file ({})", err); + return false; + } + + true +} + +/// This function will try to delete the `.vscode` directory if it's empty. +/// It may fail silently. +fn try_delete_vs_directory_if_empty() { + let path = Path::new(VSCODE_DIR); + if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) { + // The directory is empty. We just try to delete it but allow a silence + // fail as an empty `.vscode` directory is still valid + let _silence_result = fs::remove_dir(path); + } else { + // The directory is not empty or could not be read. Either way don't take + // any further actions + } +} diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index edf6c5f57a4..db467c26f15 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -92,7 +92,10 @@ pub fn run(update_mode: UpdateMode) { || { // clippy::all should only include the following lint groups: let all_group_lints = usable_lints.iter().filter(|l| { - l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf" + matches!( + &*l.group, + "correctness" | "suspicious" | "style" | "complexity" | "perf" + ) }); gen_lint_group_list(all_group_lints) diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 48f2972ec58..42cf7547f51 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.1.54" +version = "0.1.55" # end automatic update authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" @@ -23,6 +23,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } toml = "0.5.3" unicode-normalization = "0.1" +unicode-script = { version = "0.5.3", default-features = false } semver = "0.11" rustc-semver = "1.1.0" # NOTE: cargo requires serde feat in its url dep diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs index bc6eec0051a..a8c527fe2e3 100644 --- a/src/tools/clippy/clippy_lints/src/assign_ops.rs +++ b/src/tools/clippy/clippy_lints/src/assign_ops.rs @@ -55,7 +55,7 @@ declare_clippy_lint! { /// a += a + b; /// ``` pub MISREFACTORED_ASSIGN_OP, - complexity, + suspicious, "having a variable on both sides of an assign op" } diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 932cd58bf62..f272ed010a1 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -173,7 +173,7 @@ declare_clippy_lint! { /// #![deny(clippy::as_conversions)] /// ``` pub BLANKET_CLIPPY_RESTRICTION_LINTS, - style, + suspicious, "enabling the complete restriction group" } diff --git a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs index b26ef33e056..8eb94f3c28e 100644 --- a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs +++ b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs @@ -1,6 +1,6 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::{diagnostics::span_lint, is_test_module_or_function}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Pat, PatKind}; +use rustc_hir::{Item, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -25,18 +25,37 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct BlacklistedName { blacklist: FxHashSet<String>, + test_modules_deep: u32, } impl BlacklistedName { pub fn new(blacklist: FxHashSet<String>) -> Self { - Self { blacklist } + Self { + blacklist, + test_modules_deep: 0, + } + } + + fn in_test_module(&self) -> bool { + self.test_modules_deep != 0 } } impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); impl<'tcx> LateLintPass<'tcx> for BlacklistedName { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_add(1); + } + } + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + // Check whether we are under the `test` attribute. + if self.in_test_module() { + return; + } + if let PatKind::Binding(.., ident, _) = pat.kind { if self.blacklist.contains(&ident.name.to_string()) { span_lint( @@ -48,4 +67,10 @@ impl<'tcx> LateLintPass<'tcx> for BlacklistedName { } } } + + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_sub(1); + } + } } diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index 877ae002d36..4f7ffdcdfb4 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -1,15 +1,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::match_type; -use clippy_utils::{contains_name, get_pat_name, paths, single_segment_path}; +use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::{path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, UintTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use rustc_span::Symbol; declare_clippy_lint! { /// **What it does:** Checks for naive byte counts @@ -38,42 +38,43 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]); impl<'tcx> LateLintPass<'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(count, _, count_args, _) = expr.kind; + if let ExprKind::MethodCall(count, _, [count_recv], _) = expr.kind; if count.ident.name == sym!(count); - if count_args.len() == 1; - if let ExprKind::MethodCall(filter, _, filter_args, _) = count_args[0].kind; + if let ExprKind::MethodCall(filter, _, [filter_recv, filter_arg], _) = count_recv.kind; if filter.ident.name == sym!(filter); - if filter_args.len() == 2; - if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind; + if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind; let body = cx.tcx.hir().body(body_id); - if body.params.len() == 1; - if let Some(argname) = get_pat_name(body.params[0].pat); + if let [param] = body.params; + if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind; if let ExprKind::Binary(ref op, l, r) = body.value.kind; if op.node == BinOpKind::Eq; if match_type(cx, - cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(), + cx.typeck_results().expr_ty(filter_recv).peel_refs(), &paths::SLICE_ITER); + let operand_is_arg = |expr| { + let expr = peel_ref_operators(cx, remove_blocks(expr)); + path_to_local_id(expr, arg_id) + }; + let needle = if operand_is_arg(l) { + r + } else if operand_is_arg(r) { + l + } else { + return; + }; + if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); + if !LocalUsedVisitor::new(cx, arg_id).check_expr(needle); then { - let needle = match get_path_name(l) { - Some(name) if check_arg(name, argname, r) => r, - _ => match get_path_name(r) { - Some(name) if check_arg(name, argname, l) => l, - _ => { return; } - } - }; - if ty::Uint(UintTy::U8) != *cx.typeck_results().expr_ty(needle).peel_refs().kind() { - return; - } let haystack = if let ExprKind::MethodCall(path, _, args, _) = - filter_args[0].kind { + filter_recv.kind { let p = path.ident.name; if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 { &args[0] } else { - &filter_args[0] + &filter_recv } } else { - &filter_args[0] + &filter_recv }; let mut applicability = Applicability::MaybeIncorrect; span_lint_and_sugg( @@ -91,24 +92,3 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount { }; } } - -fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool { - name == arg && !contains_name(name, needle) -} - -fn get_path_name(expr: &Expr<'_>) -> Option<Symbol> { - match expr.kind { - ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) | ExprKind::Unary(UnOp::Deref, e) => { - get_path_name(e) - }, - ExprKind::Block(b, _) => { - if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { - None - } - }, - ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), - _ => None, - } -} diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs index ab22578abd6..a6c3a5b0e83 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::LocalUsedVisitor; -use clippy_utils::{is_lang_ctor, path_to_local, SpanlessEq}; +use clippy_utils::{is_lang_ctor, path_to_local, peel_ref_operators, SpanlessEq}; use if_chain::if_chain; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind, UnOp}; +use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::TypeckResults; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{MultiSpan, Span}; @@ -73,7 +72,7 @@ fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext if arms_inner.iter().all(|arm| arm.guard.is_none()); // match expression must be a local binding // match <local> { .. } - if let Some(binding_id) = path_to_local(strip_ref_operators(expr_in, cx.typeck_results())); + if let Some(binding_id) = path_to_local(peel_ref_operators(cx, expr_in)); // one of the branches must be "wild-like" if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(cx, arm_inner)); let (wild_inner_arm, non_wild_inner_arm) = @@ -163,16 +162,3 @@ fn pat_contains_or(pat: &Pat<'_>) -> bool { }); result } - -/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is -/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed. -fn strip_ref_operators<'hir>(mut expr: &'hir Expr<'hir>, typeck_results: &TypeckResults<'_>) -> &'hir Expr<'hir> { - loop { - match expr.kind { - ExprKind::AddrOf(_, _, e) => expr = e, - ExprKind::Unary(UnOp::Deref, e) if typeck_results.expr_ty(e).is_ref() => expr = e, - _ => break, - } - } - expr -} diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 7a53d390bb4..947479db8f5 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{Ident, Symbol}; @@ -122,7 +121,7 @@ impl LateLintPass<'_> for Default { if let StmtKind::Local(local) = stmt.kind; if let Some(expr) = local.init; if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); - if !in_external_macro(cx.tcx.sess, expr.span); + if !in_macro(expr.span); // only take bindings to identifiers if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind; // only when assigning `... = Default::default()` 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 759f7d4062d..a125376bffa 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -7,9 +7,10 @@ use rustc_hir::{ intravisit::{walk_expr, walk_stmt, NestedVisitorMap, Visitor}, Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind, }; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::{ hir::map::Map, + lint::in_external_macro, ty::{self, FloatTy, IntTy, PolyFnSig, Ty}, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -73,6 +74,7 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> { /// Check whether a passed literal has potential to cause fallback or not. fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>) { if_chain! { + if !in_external_macro(self.cx.sess(), lit.span); if let Some(ty_bound) = self.ty_bounds.last(); if matches!(lit.node, LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)); diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 04f3d77464f..2933fbc9341 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -149,7 +149,7 @@ declare_deprecated_lint! { /// 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" + "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items" } declare_deprecated_lint! { @@ -158,5 +158,5 @@ declare_deprecated_lint! { /// **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" + "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/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 729941f345a..3ac20fd9849 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -410,11 +410,8 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } if let ExprKind::Block(block, _) = expr.kind { - match block.rules { - BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => { - self.has_unsafe = true; - }, - _ => {}, + if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules { + self.has_unsafe = true; } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_method.rs b/src/tools/clippy/clippy_lints/src/disallowed_method.rs index ded0a0fff54..aa1a609afed 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_method.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_method.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::fn_def_id; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::Expr; +use rustc_hir::{def::Res, def_id::DefId, Crate, Expr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Symbol; @@ -13,21 +13,14 @@ declare_clippy_lint! { /// **Why is this bad?** Some methods are undesirable in certain contexts, /// and it's beneficial to lint for them as needed. /// - /// **Known problems:** Currently, you must write each function as a - /// fully-qualified path. This lint doesn't support aliases or reexported - /// names; be aware that many types in `std` are actually reexports. - /// - /// For example, if you want to disallow `Duration::as_secs`, your clippy.toml - /// configuration would look like - /// `disallowed-methods = ["core::time::Duration::as_secs"]` and not - /// `disallowed-methods = ["std::time::Duration::as_secs"]` as you might expect. + /// **Known problems:** None. /// /// **Example:** /// /// An example clippy.toml configuration: /// ```toml /// # clippy.toml - /// disallowed-methods = ["alloc::vec::Vec::leak", "std::time::Instant::now"] + /// disallowed-methods = ["std::vec::Vec::leak", "std::time::Instant::now"] /// ``` /// /// ```rust,ignore @@ -52,6 +45,7 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct DisallowedMethod { disallowed: FxHashSet<Vec<Symbol>>, + def_ids: FxHashSet<(DefId, Vec<Symbol>)>, } impl DisallowedMethod { @@ -61,6 +55,7 @@ impl DisallowedMethod { .iter() .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>()) .collect(), + def_ids: FxHashSet::default(), } } } @@ -68,10 +63,20 @@ impl DisallowedMethod { impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]); impl<'tcx> LateLintPass<'tcx> for DisallowedMethod { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + for path in &self.disallowed { + let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>(); + if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) + { + self.def_ids.insert((id, path.clone())); + } + } + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some(def_id) = fn_def_id(cx, expr) { - let func_path = cx.get_def_path(def_id); - if self.disallowed.contains(&func_path) { + if self.def_ids.iter().any(|(id, _)| def_id == *id) { + let func_path = cx.get_def_path(def_id); let func_path_string = func_path .into_iter() .map(Symbol::to_ident_string) diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs new file mode 100644 index 00000000000..12c525634c5 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -0,0 +1,112 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::ast; +use rustc_data_structures::fx::FxHashSet; +use rustc_lint::{EarlyContext, EarlyLintPass, Level}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use unicode_script::{Script, UnicodeScript}; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of unicode scripts other than those explicitly allowed + /// by the lint config. + /// + /// This lint doesn't take into account non-text scripts such as `Unknown` and `Linear_A`. + /// It also ignores the `Common` script type. + /// While configuring, be sure to use official script name [aliases] from + /// [the list of supported scripts][supported_scripts]. + /// + /// See also: [`non_ascii_idents`]. + /// + /// [aliases]: http://www.unicode.org/reports/tr24/tr24-31.html#Script_Value_Aliases + /// [supported_scripts]: https://www.unicode.org/iso15924/iso15924-codes.html + /// + /// **Why is this bad?** It may be not desired to have many different scripts for + /// identifiers in the codebase. + /// + /// Note that if you only want to allow plain English, you might want to use + /// built-in [`non_ascii_idents`] lint instead. + /// + /// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// // Assuming that `clippy.toml` contains the following line: + /// // allowed-locales = ["Latin", "Cyrillic"] + /// let counter = 10; // OK, latin is allowed. + /// let счётчик = 10; // OK, cyrillic is allowed. + /// let zähler = 10; // OK, it's still latin. + /// let カウンタ = 10; // Will spawn the lint. + /// ``` + pub DISALLOWED_SCRIPT_IDENTS, + restriction, + "usage of non-allowed Unicode scripts" +} + +#[derive(Clone, Debug)] +pub struct DisallowedScriptIdents { + whitelist: FxHashSet<Script>, +} + +impl DisallowedScriptIdents { + pub fn new(whitelist: &[String]) -> Self { + let whitelist = whitelist + .iter() + .map(String::as_str) + .filter_map(Script::from_full_name) + .collect(); + Self { whitelist } + } +} + +impl_lint_pass!(DisallowedScriptIdents => [DISALLOWED_SCRIPT_IDENTS]); + +impl EarlyLintPass for DisallowedScriptIdents { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { + // Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint: + // https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint/src/non_ascii_idents.rs + + let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).0 != Level::Allow; + if !check_disallowed_script_idents { + return; + } + + let symbols = cx.sess.parse_sess.symbol_gallery.symbols.lock(); + // Sort by `Span` so that error messages make sense with respect to the + // order of identifier locations in the code. + let mut symbols: Vec<_> = symbols.iter().collect(); + symbols.sort_unstable_by_key(|k| k.1); + + for (symbol, &span) in &symbols { + // Note: `symbol.as_str()` is an expensive operation, thus should not be called + // more than once for a single symbol. + let symbol_str = symbol.as_str(); + if symbol_str.is_ascii() { + continue; + } + + for c in symbol_str.chars() { + // We want to iterate through all the scripts associated with this character + // and check whether at least of one scripts is in the whitelist. + let forbidden_script = c + .script_extension() + .iter() + .find(|script| !self.whitelist.contains(script)); + if let Some(script) = forbidden_script { + span_lint( + cx, + DISALLOWED_SCRIPT_IDENTS, + span, + &format!( + "identifier `{}` has a Unicode script that is not allowed by configuration: {}", + symbol_str, + script.full_name() + ), + ); + // We don't want to spawn warning multiple times over a single identifier. + break; + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/disallowed_type.rs b/src/tools/clippy/clippy_lints/src/disallowed_type.rs new file mode 100644 index 00000000000..e4a88c6324e --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/disallowed_type.rs @@ -0,0 +1,126 @@ +use clippy_utils::diagnostics::span_lint; + +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::{ + def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, TraitBoundModifier, Ty, TyKind, UseKind, +}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{Span, Symbol}; + +declare_clippy_lint! { + /// **What it does:** Denies the configured types in clippy.toml. + /// + /// **Why is this bad?** Some types are undesirable in certain contexts. + /// + /// **Known problems:** None. + /// + /// N.B. There is no way to ban primitive types. + /// + /// **Example:** + /// + /// An example clippy.toml configuration: + /// ```toml + /// # clippy.toml + /// disallowed-methods = ["std::collections::BTreeMap"] + /// ``` + /// + /// ```rust,ignore + /// use std::collections::BTreeMap; + /// // or its use + /// let x = std::collections::BTreeMap::new(); + /// ``` + /// Use instead: + /// ```rust,ignore + /// // A similar type that is allowed by the config + /// use std::collections::HashMap; + /// ``` + pub DISALLOWED_TYPE, + nursery, + "use of a disallowed type" +} +#[derive(Clone, Debug)] +pub struct DisallowedType { + disallowed: FxHashSet<Vec<Symbol>>, + def_ids: FxHashSet<(DefId, Vec<Symbol>)>, +} + +impl DisallowedType { + pub fn new(disallowed: &FxHashSet<String>) -> Self { + Self { + disallowed: disallowed + .iter() + .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>()) + .collect(), + def_ids: FxHashSet::default(), + } + } +} + +impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]); + +impl<'tcx> LateLintPass<'tcx> for DisallowedType { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + for path in &self.disallowed { + let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>(); + if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) + { + self.def_ids.insert((id, path.clone())); + } + } + } + + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if_chain! { + if let ItemKind::Use(path, UseKind::Single) = &item.kind; + if let Res::Def(_, did) = path.res; + if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did); + then { + emit(cx, name, item.span,); + } + } + } + + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { + if_chain! { + if let TyKind::Path(path) = &ty.kind; + if let Some(did) = cx.qpath_res(path, ty.hir_id).opt_def_id(); + if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did); + then { + emit(cx, name, path.span()); + } + } + } + + fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) { + if_chain! { + if let Res::Def(_, did) = poly.trait_ref.path.res; + if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did); + then { + emit(cx, name, poly.trait_ref.path.span); + } + } + } + + // TODO: if non primitive const generics are a thing + // fn check_generic_arg(&mut self, cx: &LateContext<'tcx>, arg: &'tcx GenericArg<'tcx>) { + // match arg { + // GenericArg::Const(c) => {}, + // } + // } + // fn check_generic_param(&mut self, cx: &LateContext<'tcx>, param: &'tcx GenericParam<'tcx>) { + // match param.kind { + // GenericParamKind::Const { .. } => {}, + // } + // } +} + +fn emit(cx: &LateContext<'_>, name: &[Symbol], span: Span) { + let name = name.iter().map(|s| s.to_ident_string()).collect::<Vec<_>>().join("::"); + span_lint( + cx, + DISALLOWED_TYPE, + span, + &format!("`{}` is not allowed according to config", name), + ); +} diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index e67ec4e06c5..4e164d33a05 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -1,4 +1,5 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note}; +use clippy_utils::source::first_line_of_span; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty}; use if_chain::if_chain; @@ -37,7 +38,8 @@ declare_clippy_lint! { /// consider that. /// /// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks - /// for is limited, and there are still false positives. + /// for is limited, and there are still false positives. HTML elements and their + /// content are not linted. /// /// In addition, when writing documentation comments, including `[]` brackets /// inside a link text would trip the parser. Therfore, documenting link with @@ -469,11 +471,11 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize spans: &[(usize, Span)], ) -> DocHeaders { // true if a safety header was found - use pulldown_cmark::CodeBlockKind; use pulldown_cmark::Event::{ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, }; - use pulldown_cmark::Tag::{CodeBlock, Heading, Link}; + use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph}; + use pulldown_cmark::{CodeBlockKind, CowStr}; let mut headers = DocHeaders { safety: false, @@ -485,6 +487,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize let mut in_heading = false; let mut is_rust = false; let mut edition = None; + let mut ticks_unbalanced = false; + let mut text_to_check: Vec<(CowStr<'_>, Span)> = Vec::new(); + let mut paragraph_span = spans.get(0).expect("function isn't called if doc comment is empty").1; for (event, range) in events { match event { Start(CodeBlock(ref kind)) => { @@ -510,13 +515,42 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize }, Start(Link(_, url, _)) => in_link = Some(url), End(Link(..)) => in_link = None, - Start(Heading(_)) => in_heading = true, - End(Heading(_)) => in_heading = false, + Start(Heading(_) | Paragraph | Item) => { + if let Start(Heading(_)) = event { + in_heading = true; + } + ticks_unbalanced = false; + let (_, span) = get_current_span(spans, range.start); + paragraph_span = first_line_of_span(cx, span); + }, + End(Heading(_) | Paragraph | Item) => { + if let End(Heading(_)) = event { + in_heading = false; + } + if ticks_unbalanced { + span_lint_and_help( + cx, + DOC_MARKDOWN, + paragraph_span, + "backticks are unbalanced", + None, + "a backtick may be missing a pair", + ); + } else { + for (text, span) in text_to_check { + check_text(cx, valid_idents, &text, span); + } + } + text_to_check = Vec::new(); + }, Start(_tag) | End(_tag) => (), // We don't care about other tags Html(_html) => (), // HTML is weird, just ignore it SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (), FootnoteReference(text) | Text(text) => { - if Some(&text) == in_link.as_ref() { + let (begin, span) = get_current_span(spans, range.start); + paragraph_span = paragraph_span.with_hi(span.hi()); + ticks_unbalanced |= text.contains('`'); + if Some(&text) == in_link.as_ref() || ticks_unbalanced { // Probably a link of the form `<http://example.com>` // Which are represented as a link to "http://example.com" with // text "http://example.com" by pulldown-cmark @@ -525,11 +559,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize headers.safety |= in_heading && text.trim() == "Safety"; headers.errors |= in_heading && text.trim() == "Errors"; headers.panics |= in_heading && text.trim() == "Panics"; - let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) { - Ok(o) => o, - Err(e) => e - 1, - }; - let (begin, span) = spans[index]; if in_code { if is_rust { let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition()); @@ -538,8 +567,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize } else { // Adjust for the beginning of the current `Event` let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin)); - - check_text(cx, valid_idents, &text, span); + text_to_check.push((text, span)); } }, } @@ -547,6 +575,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize headers } +fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) { + let index = match spans.binary_search_by(|c| c.0.cmp(&idx)) { + Ok(o) => o, + Err(e) => e - 1, + }; + spans[index] +} + fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { fn has_needless_main(code: &str, edition: Edition) -> bool { rustc_driver::catch_fatal_errors(|| { 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 5fdf5bc9e9d..03a8b40df55 100644 --- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs +++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// let a = tmp + x; /// ``` pub EVAL_ORDER_DEPENDENCE, - complexity, + suspicious, "whether a variable read occurs before a write depends on sub-expression evaluation order" } diff --git a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs index b5ebe5f90ba..1e503cc795c 100644 --- a/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs +++ b/src/tools/clippy/clippy_lints/src/float_equality_without_abs.rs @@ -36,7 +36,7 @@ declare_clippy_lint! { /// } /// ``` pub FLOAT_EQUALITY_WITHOUT_ABS, - correctness, + suspicious, "float equality check without `.abs()`" } diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 3bd6a09d365..8aefb8d46f6 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// a =- 42; // confusing, should it be `a -= 42` or `a = -42`? /// ``` pub SUSPICIOUS_ASSIGNMENT_FORMATTING, - style, + suspicious, "suspicious formatting of `*=`, `-=` or `!=`" } @@ -44,7 +44,7 @@ declare_clippy_lint! { /// } /// ``` pub SUSPICIOUS_UNARY_OP_FORMATTING, - style, + suspicious, "suspicious formatting of unary `-` or `!` on the RHS of a BinOp" } @@ -80,7 +80,7 @@ declare_clippy_lint! { /// } /// ``` pub SUSPICIOUS_ELSE_FORMATTING, - style, + suspicious, "suspicious formatting of `else`" } diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs index 3707e792177..8e45fdfecc4 100644 --- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen { // LHS of subtraction is "x.len()" if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind; - if arg_lhs_path.ident.name == sym!(len); + if arg_lhs_path.ident.name == sym::len; if let Some(arg_lhs_struct) = lhs_args.get(0); // The two vectors referenced (x in x.get(...) and in x.len()) diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index f661f7ede82..5403d76ea30 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { } } -/// Checks if `Mutex::lock` is called in the `if let _ = expr. +/// Checks if `Mutex::lock` is called in the `if let` expr. pub struct OppVisitor<'a, 'tcx> { mutex_lock_called: bool, found_mutex: Option<&'tcx Expr<'tcx>>, diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 583514b22f9..d69187f6746 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if_chain! { - if item.ident.as_str() == "len"; + if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); if cx.access_levels.is_exported(item.hir_id()); @@ -189,8 +189,8 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { - fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: &str) -> bool { - item.ident.name.as_str() == name + fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool { + item.ident.name == name && if let AssocItemKind::Fn { has_self } = item.kind { has_self && { cx.tcx.fn_sig(item.id.def_id).inputs().skip_binder().len() == 1 } } else { @@ -207,7 +207,9 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } - if cx.access_levels.is_exported(visited_trait.hir_id()) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { + if cx.access_levels.is_exported(visited_trait.hir_id()) + && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) + { let mut current_and_super_traits = DefIdSet::default(); fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); @@ -401,7 +403,7 @@ fn check_len( return; } - if method_name.as_str() == "len" && args.len() == 1 && has_is_empty(cx, &args[0]) { + if method_name == sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index e7dd3952b3a..e0325738466 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -60,9 +60,9 @@ use rustc_session::Session; /// 4. The `description` that contains a short explanation on what's wrong with code where the /// lint is triggered. /// -/// Currently the categories `style`, `correctness`, `complexity` and `perf` are enabled by default. -/// As said in the README.md of this repository, if the lint level mapping changes, please update -/// README.md. +/// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are +/// enabled by default. As said in the README.md of this repository, if the lint level mapping +/// changes, please update README.md. /// /// # Example /// @@ -106,6 +106,11 @@ macro_rules! declare_clippy_lint { $(#[$attr])* pub clippy::$name, Deny, $description, report_in_external_macro: true } }; + { $(#[$attr:meta])* pub $name:tt, suspicious, $description:tt } => { + declare_tool_lint! { + $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true + } + }; { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => { declare_tool_lint! { $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true @@ -187,6 +192,8 @@ mod default_numeric_fallback; mod dereference; mod derive; mod disallowed_method; +mod disallowed_script_idents; +mod disallowed_type; mod doc; mod double_comparison; mod double_parens; @@ -254,7 +261,6 @@ mod manual_strip; mod manual_unwrap_or; mod map_clone; mod map_err_ignore; -mod map_identity; mod map_unit_fn; mod match_on_vec_items; mod matches; @@ -267,6 +273,7 @@ mod misc; mod misc_early; mod missing_const_for_fn; mod missing_doc; +mod missing_enforced_import_rename; mod missing_inline; mod modulo_arithmetic; mod multiple_crate_versions; @@ -293,6 +300,7 @@ mod no_effect; mod non_copy_const; mod non_expressive_names; mod non_octal_unix_permissions; +mod nonstandard_macro_braces; mod open_options; mod option_env_unwrap; mod option_if_let_else; @@ -483,11 +491,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ); 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", + "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", + "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` @@ -583,6 +591,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: derive::EXPL_IMPL_CLONE_ON_COPY, derive::UNSAFE_DERIVE_DESERIALIZE, disallowed_method::DISALLOWED_METHOD, + disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS, + disallowed_type::DISALLOWED_TYPE, doc::DOC_MARKDOWN, doc::MISSING_ERRORS_DOC, doc::MISSING_PANICS_DOC, @@ -705,7 +715,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: manual_unwrap_or::MANUAL_UNWRAP_OR, map_clone::MAP_CLONE, map_err_ignore::MAP_ERR_IGNORE, - map_identity::MAP_IDENTITY, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, match_on_vec_items::MATCH_ON_VEC_ITEMS, @@ -730,6 +739,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: mem_replace::MEM_REPLACE_OPTION_WITH_NONE, mem_replace::MEM_REPLACE_WITH_DEFAULT, mem_replace::MEM_REPLACE_WITH_UNINIT, + methods::APPEND_INSTEAD_OF_EXTEND, methods::BIND_INSTEAD_OF_MAP, methods::BYTES_NTH, methods::CHARS_LAST_CMP, @@ -765,6 +775,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: methods::MANUAL_STR_REPEAT, methods::MAP_COLLECT_RESULT_UNIT, methods::MAP_FLATTEN, + methods::MAP_IDENTITY, methods::MAP_UNWRAP_OR, methods::NEW_RET_NO_SELF, methods::OK_EXPECT, @@ -810,6 +821,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: misc_early::ZERO_PREFIXED_LITERAL, missing_const_for_fn::MISSING_CONST_FOR_FN, missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES, missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, modulo_arithmetic::MODULO_ARITHMETIC, multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, @@ -843,6 +855,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: non_expressive_names::MANY_SINGLE_CHAR_NAMES, non_expressive_names::SIMILAR_NAMES, non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS, + nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES, open_options::NONSENSICAL_OPEN_OPTIONS, option_env_unwrap::OPTION_ENV_UNWRAP, option_if_let_else::OPTION_IF_LET_ELSE, @@ -989,6 +1002,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(create_dir::CREATE_DIR), LintId::of(dbg_macro::DBG_MACRO), LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), + LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS), LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE), LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS), LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS), @@ -1013,6 +1027,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(misc::FLOAT_CMP_CONST), LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), + LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES), LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), LintId::of(modulo_arithmetic::MODULO_ARITHMETIC), LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN), @@ -1090,6 +1105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::CLONED_INSTEAD_OF_COPIED), LintId::of(methods::FILTER_MAP_NEXT), LintId::of(methods::FLAT_MAP_OPTION), + LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT), LintId::of(methods::IMPLICIT_CLONE), LintId::of(methods::INEFFICIENT_TO_STRING), LintId::of(methods::MAP_FLATTEN), @@ -1260,7 +1276,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(manual_strip::MANUAL_STRIP), LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), LintId::of(map_clone::MAP_CLONE), - LintId::of(map_identity::MAP_IDENTITY), LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), @@ -1276,6 +1291,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(methods::APPEND_INSTEAD_OF_EXTEND), LintId::of(methods::BIND_INSTEAD_OF_MAP), LintId::of(methods::BYTES_NTH), LintId::of(methods::CHARS_LAST_CMP), @@ -1286,7 +1302,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::FILTER_MAP_IDENTITY), LintId::of(methods::FILTER_NEXT), LintId::of(methods::FLAT_MAP_IDENTITY), - LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT), LintId::of(methods::INSPECT_FOR_EACH), LintId::of(methods::INTO_ITER_ON_REF), LintId::of(methods::ITERATOR_STEP_BY_ZERO), @@ -1301,6 +1316,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), LintId::of(methods::MANUAL_STR_REPEAT), LintId::of(methods::MAP_COLLECT_RESULT_UNIT), + LintId::of(methods::MAP_IDENTITY), LintId::of(methods::NEW_RET_NO_SELF), LintId::of(methods::OK_EXPECT), LintId::of(methods::OPTION_AS_REF_DEREF), @@ -1359,6 +1375,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), + LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES), LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), @@ -1447,7 +1464,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), LintId::of(assign_ops::ASSIGN_OP_PATTERN), - LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), @@ -1465,9 +1481,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(eq_op::OP_REF), LintId::of(eta_reduction::REDUNDANT_CLOSURE), LintId::of(float_literal::EXCESSIVE_PRECISION), - LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), - LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), - LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), LintId::of(from_over_into::FROM_OVER_INTO), LintId::of(from_str_radix_10::FROM_STR_RADIX_10), LintId::of(functions::DOUBLE_MUST_USE), @@ -1480,7 +1493,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(len_zero::LEN_ZERO), LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), - LintId::of(loops::EMPTY_LOOP), LintId::of(loops::FOR_KV_MAP), LintId::of(loops::NEEDLESS_RANGE_LOOP), LintId::of(loops::SAME_ITEM_PUSH), @@ -1501,7 +1513,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::BYTES_NTH), LintId::of(methods::CHARS_LAST_CMP), LintId::of(methods::CHARS_NEXT_CMP), - LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT), LintId::of(methods::INTO_ITER_ON_REF), LintId::of(methods::ITER_CLONED_COLLECT), LintId::of(methods::ITER_NEXT_SLICE), @@ -1535,6 +1546,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), + LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES), LintId::of(ptr::CMP_NULL), LintId::of(ptr::PTR_ARG), LintId::of(ptr_eq::PTR_EQ), @@ -1560,7 +1572,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ]); store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![ - LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(attrs::DEPRECATED_CFG_ATTR), LintId::of(booleans::NONMINIMAL_BOOL), LintId::of(casts::CHAR_LIT_AS_U8), @@ -1570,7 +1581,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(double_parens::DOUBLE_PARENS), LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), - LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), LintId::of(explicit_write::EXPLICIT_WRITE), LintId::of(format::USELESS_FORMAT), LintId::of(functions::TOO_MANY_ARGUMENTS), @@ -1581,12 +1591,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(lifetimes::NEEDLESS_LIFETIMES), LintId::of(loops::EXPLICIT_COUNTER_LOOP), LintId::of(loops::MANUAL_FLATTEN), - LintId::of(loops::MUT_RANGE_BOUND), LintId::of(loops::SINGLE_ELEMENT_LOOP), LintId::of(loops::WHILE_LET_LOOP), LintId::of(manual_strip::MANUAL_STRIP), LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), - LintId::of(map_identity::MAP_IDENTITY), LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), LintId::of(matches::MATCH_AS_REF), @@ -1601,11 +1609,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(methods::ITER_COUNT), LintId::of(methods::MANUAL_FILTER_MAP), LintId::of(methods::MANUAL_FIND_MAP), + LintId::of(methods::MAP_IDENTITY), LintId::of(methods::OPTION_AS_REF_DEREF), LintId::of(methods::OPTION_FILTER_MAP), LintId::of(methods::SEARCH_IS_SOME), LintId::of(methods::SKIP_WHILE_NEXT), - LintId::of(methods::SUSPICIOUS_MAP), LintId::of(methods::UNNECESSARY_FILTER_MAP), LintId::of(methods::USELESS_ASREF), LintId::of(misc::SHORT_CIRCUIT_STATEMENT), @@ -1674,7 +1682,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(eq_op::EQ_OP), LintId::of(erasing_op::ERASING_OP), - LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), LintId::of(formatting::POSSIBLE_MISSING_COMMA), LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), LintId::of(if_let_mutex::IF_LET_MUTEX), @@ -1684,7 +1691,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(let_underscore::LET_UNDERSCORE_LOCK), LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), LintId::of(loops::ITER_NEXT_LOOP), LintId::of(loops::NEVER_LOOP), LintId::of(loops::WHILE_IMMUTABLE_CONDITION), @@ -1699,7 +1705,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(misc::CMP_NAN), LintId::of(misc::FLOAT_CMP), LintId::of(misc::MODULO_ONE), - LintId::of(mut_key::MUTABLE_KEY_TYPE), LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), @@ -1710,8 +1715,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(self_assignment::SELF_ASSIGNMENT), LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), - LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), - LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), LintId::of(swap::ALMOST_SWAPPED), LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), @@ -1728,6 +1731,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), ]); + store.register_group(true, "clippy::suspicious", None, vec![ + LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), + LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), + LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), + LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), + LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), + LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), + LintId::of(loops::EMPTY_LOOP), + LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), + LintId::of(loops::MUT_RANGE_BOUND), + LintId::of(methods::SUSPICIOUS_MAP), + LintId::of(mut_key::MUTABLE_KEY_TYPE), + LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), + LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), + ]); + store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ LintId::of(entry::MAP_ENTRY), LintId::of(escape::BOXED_LOCAL), @@ -1735,6 +1755,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(loops::MANUAL_MEMCPY), LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(methods::APPEND_INSTEAD_OF_EXTEND), LintId::of(methods::EXPECT_FUN_CALL), LintId::of(methods::ITER_NTH), LintId::of(methods::MANUAL_STR_REPEAT), @@ -1761,6 +1782,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY), LintId::of(disallowed_method::DISALLOWED_METHOD), + LintId::of(disallowed_type::DISALLOWED_TYPE), LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM), LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS), LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS), @@ -2038,8 +2060,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || box non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold, }); + let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>(); + store.register_early_pass(move || box nonstandard_macro_braces::MacroBraces::new(¯o_matcher)); 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); @@ -2066,7 +2089,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: 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); - + let disallowed_types = conf.disallowed_types.iter().cloned().collect::<FxHashSet<_>>(); + store.register_late_pass(move || box disallowed_type::DisallowedType::new(&disallowed_types)); + let import_renames = conf.enforced_import_renames.clone(); + store.register_late_pass(move || box missing_enforced_import_rename::ImportRename::new(import_renames.clone())); + let scripts = conf.allowed_scripts.clone(); + store.register_early_pass(move || box disallowed_script_idents::DisallowedScriptIdents::new(&scripts)); } #[rustfmt::skip] diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index c91fe88757e..a98e2dc1372 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -118,7 +118,7 @@ fn build_manual_memcpy_suggestion<'tcx>( let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| { if_chain! { if let ExprKind::MethodCall(method, _, len_args, _) = end.kind; - if method.ident.name == sym!(len); + if method.ident.name == sym::len; if len_args.len() == 1; if let Some(arg) = len_args.get(0); if path_to_local(arg) == path_to_local(base); diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index a4bc3e6bd10..56a123b69c6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -199,7 +199,7 @@ declare_clippy_lint! { /// } /// ``` pub FOR_LOOPS_OVER_FALLIBLES, - correctness, + suspicious, "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`" } @@ -313,7 +313,7 @@ declare_clippy_lint! { /// loop {} /// ``` pub EMPTY_LOOP, - style, + suspicious, "empty `loop {}`, which should block or sleep" } @@ -401,7 +401,7 @@ declare_clippy_lint! { /// } /// ``` pub MUT_RANGE_BOUND, - complexity, + suspicious, "for loop over a range where one of the bounds is a mutable variable" } 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 eb82c9c27c3..51d7def137e 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs @@ -7,10 +7,10 @@ use clippy_utils::{is_trait_method, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, GenericArg, GenericArgs, HirId, Local, Pat, PatKind, QPath, StmtKind, Ty}; +use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, StmtKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::sym; use rustc_span::{MultiSpan, Span}; const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; @@ -24,10 +24,8 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont if let ExprKind::MethodCall(method, _, args, _) = expr.kind; if let ExprKind::MethodCall(chain_method, method0_span, _, _) = args[0].kind; if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator); - if let Some(generic_args) = chain_method.args; - if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); - if let Some(ty) = cx.typeck_results().node_type_opt(ty.hir_id); then { + let ty = cx.typeck_results().expr_ty(&args[0]); let mut applicability = Applicability::MachineApplicable; let is_empty_sugg = "next().is_none()".to_string(); let method_name = &*method.ident.name.as_str(); @@ -72,40 +70,25 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont } fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) { - fn get_hir_id<'tcx>(ty: Option<&Ty<'tcx>>, method_args: Option<&GenericArgs<'tcx>>) -> Option<HirId> { - if let Some(ty) = ty { - return Some(ty.hir_id); - } - - if let Some(generic_args) = method_args { - if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0) { - return Some(ty.hir_id); - } - } - - None - } if let ExprKind::Block(block, _) = expr.kind { for stmt in block.stmts { if_chain! { - if let StmtKind::Local( - Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. }, - init: Some(init_expr), ty, .. } - ) = stmt.kind; + if let StmtKind::Local(local) = stmt.kind; + if let PatKind::Binding(_, id, ..) = local.pat.kind; + if let Some(init_expr) = local.init; if let ExprKind::MethodCall(method_name, collect_span, &[ref iter_source], ..) = init_expr.kind; if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator); - if let Some(hir_id) = get_hir_id(*ty, method_name.args); - if let Some(ty) = cx.typeck_results().node_type_opt(hir_id); + let ty = cx.typeck_results().expr_ty(init_expr); if is_type_diagnostic_item(cx, ty, sym::vec_type) || is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || is_type_diagnostic_item(cx, ty, sym::BinaryHeap) || is_type_diagnostic_item(cx, ty, sym::LinkedList); - if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident); + if let Some(iter_calls) = detect_iter_and_into_iters(block, id); if let [iter_call] = &*iter_calls; then { let mut used_count_visitor = UsedCountVisitor { cx, - id: *pat_id, + id, count: 0, }; walk_block(&mut used_count_visitor, block); @@ -187,48 +170,40 @@ enum IterFunctionKind { struct IterFunctionVisitor { uses: Vec<IterFunction>, seen_other: bool, - target: Ident, + target: HirId, } impl<'tcx> Visitor<'tcx> for IterFunctionVisitor { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection - if_chain! { - if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind; - if let Some(Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. }) = args.get(0); - if let &[name] = &path.segments; - if name.ident == self.target; - then { - let len = sym!(len); - let is_empty = sym!(is_empty); - let contains = sym!(contains); - match method_name.ident.name { - sym::into_iter => self.uses.push( - IterFunction { func: IterFunctionKind::IntoIter, span: expr.span } - ), - name if name == len => self.uses.push( - IterFunction { func: IterFunctionKind::Len, span: expr.span } - ), - name if name == is_empty => self.uses.push( - IterFunction { func: IterFunctionKind::IsEmpty, span: expr.span } - ), - name if name == contains => self.uses.push( - IterFunction { func: IterFunctionKind::Contains(args[1].span), span: expr.span } - ), + if let ExprKind::MethodCall(method_name, _, [recv, args @ ..], _) = &expr.kind { + if path_to_local_id(recv, self.target) { + match &*method_name.ident.name.as_str() { + "into_iter" => self.uses.push(IterFunction { + func: IterFunctionKind::IntoIter, + span: expr.span, + }), + "len" => self.uses.push(IterFunction { + func: IterFunctionKind::Len, + span: expr.span, + }), + "is_empty" => self.uses.push(IterFunction { + func: IterFunctionKind::IsEmpty, + span: expr.span, + }), + "contains" => self.uses.push(IterFunction { + func: IterFunctionKind::Contains(args[0].span), + span: expr.span, + }), _ => self.seen_other = true, } - return + return; } } // Check if the collection is used for anything else - if_chain! { - if let Expr { kind: ExprKind::Path(QPath::Resolved(_, path)), .. } = expr; - if let &[name] = &path.segments; - if name.ident == self.target; - then { - self.seen_other = true; - } else { - walk_expr(self, expr); - } + if path_to_local_id(expr, self.target) { + self.seen_other = true; + } else { + walk_expr(self, expr); } } @@ -262,10 +237,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> { /// Detect the occurrences of calls to `iter` or `into_iter` for the /// given identifier -fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> { +fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, id: HirId) -> Option<Vec<IterFunction>> { let mut visitor = IterFunctionVisitor { uses: Vec::new(), - target: identifier, + target: id, seen_other: false, }; visitor.visit_block(block); diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 3065bcc3e6c..3810d0dcc05 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -192,7 +192,7 @@ fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { if_chain! { if let ExprKind::MethodCall(method, _, len_args, _) = expr.kind; if len_args.len() == 1; - if method.ident.name == sym!(len); + if method.ident.name == sym::len; if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind; if path.segments.len() == 1; if path.segments[0].ident.name == var; diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 63560047578..d57588716a5 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -1,7 +1,9 @@ use super::WHILE_LET_ON_ITERATOR; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use clippy_utils::{get_enclosing_loop, is_refutable, is_trait_method, match_def_path, paths, visitors::is_res_used}; +use clippy_utils::{ + get_enclosing_loop_or_closure, is_refutable, is_trait_method, match_def_path, paths, visitors::is_res_used, +}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}; @@ -315,9 +317,10 @@ fn needs_mutable_borrow(cx: &LateContext<'tcx>, iter_expr: &IterExpr, loop_expr: } } - if let Some(e) = get_enclosing_loop(cx.tcx, loop_expr) { - // The iterator expression will be used on the next iteration unless it is declared within the outer - // loop. + if let Some(e) = get_enclosing_loop_or_closure(cx.tcx, loop_expr) { + // The iterator expression will be used on the next iteration (for loops), or on the next call (for + // closures) unless it is declared within the enclosing expression. TODO: Check for closures + // used where an `FnOnce` type is expected. let local_id = match iter_expr.path { Res::Local(id) => id, _ => return true, diff --git a/src/tools/clippy/clippy_lints/src/manual_map.rs b/src/tools/clippy/clippy_lints/src/manual_map.rs index 0b873534f2c..97e4a983f32 100644 --- a/src/tools/clippy/clippy_lints/src/manual_map.rs +++ b/src/tools/clippy/clippy_lints/src/manual_map.rs @@ -3,19 +3,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable}; use clippy_utils::{ - can_move_expr_to_closure, in_constant, is_allowed, is_else_clause, is_lang_ctor, match_var, peel_hir_expr_refs, + can_move_expr_to_closure, in_constant, is_allowed, is_else_clause, is_lang_ctor, path_to_local_id, + peel_hir_expr_refs, }; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; -use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind}; +use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, MatchSource, Mutability, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{ - symbol::{sym, Ident}, - SyntaxContext, -}; +use rustc_span::{sym, SyntaxContext}; declare_clippy_lint! { /// **What it does:** Checks for usages of `match` which could be implemented using `map` @@ -141,13 +139,13 @@ impl LateLintPass<'_> for ManualMap { scrutinee_str.into() }; - let body_str = if let PatKind::Binding(annotation, _, some_binding, None) = some_pat.kind { - match can_pass_as_func(cx, some_binding, some_expr) { + let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind { + match can_pass_as_func(cx, id, some_expr) { Some(func) if func.span.ctxt() == some_expr.span.ctxt() => { snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() }, _ => { - if match_var(some_expr, some_binding.name) + if path_to_local_id(some_expr, id) && !is_allowed(cx, MATCH_AS_REF, expr.hir_id) && binding_ref.is_some() { @@ -199,10 +197,10 @@ impl LateLintPass<'_> for ManualMap { // Checks whether the expression could be passed as a function, or whether a closure is needed. // Returns the function to be passed to `map` if it exists. -fn can_pass_as_func(cx: &LateContext<'tcx>, binding: Ident, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { +fn can_pass_as_func(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { match expr.kind { ExprKind::Call(func, [arg]) - if match_var(arg, binding.name) && cx.typeck_results().expr_adjustments(arg).is_empty() => + if path_to_local_id(arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() => { Some(func) }, diff --git a/src/tools/clippy/clippy_lints/src/map_identity.rs b/src/tools/clippy/clippy_lints/src/map_identity.rs deleted file mode 100644 index 41cda23510e..00000000000 --- a/src/tools/clippy/clippy_lints/src/map_identity.rs +++ /dev/null @@ -1,126 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{is_adjusted, is_qpath_def_path, is_trait_method, match_var, paths, remove_blocks}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; - -declare_clippy_lint! { - /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function. - /// - /// **Why is this bad?** It can be written more concisely without the call to `map`. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// ```rust - /// let x = [1, 2, 3]; - /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect(); - /// ``` - /// Use instead: - /// ```rust - /// let x = [1, 2, 3]; - /// let y: Vec<_> = x.iter().map(|x| 2*x).collect(); - /// ``` - pub MAP_IDENTITY, - complexity, - "using iterator.map(|x| x)" -} - -declare_lint_pass!(MapIdentity => [MAP_IDENTITY]); - -impl<'tcx> LateLintPass<'tcx> for MapIdentity { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if expr.span.from_expansion() { - return; - } - - if_chain! { - if let Some([caller, func]) = get_map_argument(cx, expr); - if is_expr_identity_function(cx, func); - then { - span_lint_and_sugg( - cx, - MAP_IDENTITY, - expr.span.trim_start(caller.span).unwrap(), - "unnecessary map of the identity function", - "remove the call to `map`", - String::new(), - Applicability::MachineApplicable - ) - } - } - } -} - -/// Returns the arguments passed into map() if the expression is a method call to -/// map(). Otherwise, returns None. -fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> { - if_chain! { - if let ExprKind::MethodCall(method, _, args, _) = expr.kind; - if args.len() == 2 && method.ident.name == sym::map; - let caller_ty = cx.typeck_results().expr_ty(&args[0]); - if is_trait_method(cx, expr, sym::Iterator) - || is_type_diagnostic_item(cx, caller_ty, sym::result_type) - || is_type_diagnostic_item(cx, caller_ty, sym::option_type); - then { - Some(args) - } else { - None - } - } -} - -/// Checks if an expression represents the identity function -/// Only examines closures and `std::convert::identity` -fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)), - ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY), - _ => false, - } -} - -/// Checks if a function's body represents the identity function -/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| { -/// return x; }` -fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { - let params = func.params; - let body = remove_blocks(&func.value); - - // if there's less/more than one parameter, then it is not the identity function - if params.len() != 1 { - return false; - } - - match body.kind { - ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat), - ExprKind::Ret(Some(ret_val)) => match_expr_param(cx, ret_val, params[0].pat), - ExprKind::Block(block, _) => { - if_chain! { - if block.stmts.len() == 1; - if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = block.stmts[0].kind; - if let ExprKind::Ret(Some(ret_val)) = expr.kind; - then { - match_expr_param(cx, ret_val, params[0].pat) - } else { - false - } - } - }, - _ => false, - } -} - -/// Returns true iff an expression returns the same thing as a parameter's pattern -fn match_expr_param(cx: &LateContext<'_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool { - if let PatKind::Binding(_, _, ident, _) = pat.kind { - match_var(expr, ident.name) && !(cx.typeck_results().hir_owner == expr.hir_id.owner && is_adjusted(cx, expr)) - } else { - false - } -} diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index cd3e3b97928..f1e3492c4ec 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -992,9 +992,9 @@ impl CommonPrefixSearcher<'a> { } } -fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool { +fn is_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool { let attrs = cx.tcx.get_attrs(variant_def.def_id); - clippy_utils::attrs::is_doc_hidden(attrs) + clippy_utils::attrs::is_doc_hidden(attrs) || clippy_utils::attrs::is_unstable(attrs) } #[allow(clippy::too_many_lines)] @@ -1033,7 +1033,8 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) // Accumulate the variants which should be put in place of the wildcard because they're not // already covered. - let mut missing_variants: Vec<_> = adt_def.variants.iter().collect(); + let has_hidden = adt_def.variants.iter().any(|x| is_hidden(cx, x)); + let mut missing_variants: Vec<_> = adt_def.variants.iter().filter(|x| !is_hidden(cx, x)).collect(); let mut path_prefix = CommonPrefixSearcher::None; for arm in arms { @@ -1118,7 +1119,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) match missing_variants.as_slice() { [] => (), - [x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg( + [x] if !adt_def.is_variant_list_non_exhaustive() && !has_hidden => span_lint_and_sugg( cx, MATCH_WILDCARD_FOR_SINGLE_VARIANTS, wildcard_span, @@ -1129,7 +1130,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) ), variants => { let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect(); - let message = if adt_def.is_variant_list_non_exhaustive() { + let message = if adt_def.is_variant_list_non_exhaustive() || has_hidden { suggestions.push("_".into()); "wildcard matches known variants and will also match future added variants" } else { @@ -2266,7 +2267,8 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) { ), ); } else { - diag.span_help(i.pat.span, &format!("consider refactoring into `{} | {}`", lhs, rhs)); + diag.span_help(i.pat.span, &format!("consider refactoring into `{} | {}`", lhs, rhs,)) + .help("...or consider changing the match arm bodies"); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/append_instead_of_extend.rs b/src/tools/clippy/clippy_lints/src/methods/append_instead_of_extend.rs new file mode 100644 index 00000000000..e39a5a1efd1 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/append_instead_of_extend.rs @@ -0,0 +1,41 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, LangItem}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::APPEND_INSTEAD_OF_EXTEND; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { + let ty = cx.typeck_results().expr_ty(recv).peel_refs(); + if_chain! { + if is_type_diagnostic_item(cx, ty, sym::vec_type); + //check source object + if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind; + if src_method.ident.as_str() == "drain"; + if let src_ty = cx.typeck_results().expr_ty(drain_vec).peel_refs(); + if is_type_diagnostic_item(cx, src_ty, sym::vec_type); + //check drain range + if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs(); + if is_type_lang_item(cx, src_ty_range, LangItem::RangeFull); + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + APPEND_INSTEAD_OF_EXTEND, + expr.span, + "use of `extend` instead of `append` for adding the full range of a second vector", + "try this", + format!( + "{}.append(&mut {})", + snippet_with_applicability(cx, recv.span, "..", &mut applicability), + snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) + ), + applicability, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs index 403fe8d3546..d1b5e945dfd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{is_expr_path_def_path, is_trait_method, path_to_local_id, paths}; -use if_chain::if_chain; +use clippy_utils::{is_expr_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -9,32 +8,15 @@ use rustc_span::{source_map::Span, sym}; use super::FILTER_MAP_IDENTITY; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) { - if is_trait_method(cx, expr, sym::Iterator) { - let apply_lint = |message: &str| { - span_lint_and_sugg( - cx, - FILTER_MAP_IDENTITY, - filter_map_span.with_hi(expr.span.hi()), - message, - "try", - "flatten()".to_string(), - Applicability::MachineApplicable, - ); - }; - - if_chain! { - if let hir::ExprKind::Closure(_, _, body_id, _, _) = filter_map_arg.kind; - let body = cx.tcx.hir().body(body_id); - - if let hir::PatKind::Binding(_, binding_id, ..) = body.params[0].pat.kind; - if path_to_local_id(&body.value, binding_id); - then { - apply_lint("called `filter_map(|x| x)` on an `Iterator`"); - } - } - - if is_expr_path_def_path(cx, filter_map_arg, &paths::CONVERT_IDENTITY) { - apply_lint("called `filter_map(std::convert::identity)` on an `Iterator`"); - } + if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, filter_map_arg) { + span_lint_and_sugg( + cx, + FILTER_MAP_IDENTITY, + filter_map_span.with_hi(expr.span.hi()), + "use of `filter_map` with an identity function", + "try", + "flatten()".to_string(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs index 25f8434cb94..6f911d79d0b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{is_expr_path_def_path, is_trait_method, paths}; -use if_chain::if_chain; +use clippy_utils::{is_expr_identity_function, is_trait_method}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -15,36 +14,15 @@ pub(super) fn check<'tcx>( flat_map_arg: &'tcx hir::Expr<'_>, flat_map_span: Span, ) { - if is_trait_method(cx, expr, sym::Iterator) { - let apply_lint = |message: &str| { - span_lint_and_sugg( - cx, - FLAT_MAP_IDENTITY, - flat_map_span.with_hi(expr.span.hi()), - message, - "try", - "flatten()".to_string(), - Applicability::MachineApplicable, - ); - }; - - if_chain! { - if let hir::ExprKind::Closure(_, _, body_id, _, _) = flat_map_arg.kind; - let body = cx.tcx.hir().body(body_id); - - if let hir::PatKind::Binding(_, _, binding_ident, _) = body.params[0].pat.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = body.value.kind; - - if path.segments.len() == 1; - if path.segments[0].ident.name == binding_ident.name; - - then { - apply_lint("called `flat_map(|x| x)` on an `Iterator`"); - } - } - - if is_expr_path_def_path(cx, flat_map_arg, &paths::CONVERT_IDENTITY) { - apply_lint("called `flat_map(std::convert::identity)` on an `Iterator`"); - } + if is_trait_method(cx, expr, sym::Iterator) && is_expr_identity_function(cx, flat_map_arg) { + span_lint_and_sugg( + cx, + FLAT_MAP_IDENTITY, + flat_map_span.with_hi(expr.span.hi()), + "use of `flat_map` with an identity function", + "try", + "flatten()".to_string(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs new file mode 100644 index 00000000000..538a12566e3 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs @@ -0,0 +1,38 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_expr_identity_function, is_trait_method}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_span::{source_map::Span, sym}; + +use super::MAP_IDENTITY; + +pub(super) fn check( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + caller: &hir::Expr<'_>, + map_arg: &hir::Expr<'_>, + _map_span: Span, +) { + let caller_ty = cx.typeck_results().expr_ty(caller); + + if_chain! { + if is_trait_method(cx, expr, sym::Iterator) + || is_type_diagnostic_item(cx, caller_ty, sym::result_type) + || is_type_diagnostic_item(cx, caller_ty, sym::option_type); + if is_expr_identity_function(cx, map_arg); + if let Some(sugg_span) = expr.span.trim_start(caller.span); + then { + span_lint_and_sugg( + cx, + MAP_IDENTITY, + sugg_span, + "unnecessary map of the identity function", + "remove the call to `map`", + String::new(), + Applicability::MachineApplicable, + ) + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index c8ae972f18c..283fcf281df 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1,3 +1,4 @@ +mod append_instead_of_extend; mod bind_instead_of_map; mod bytes_nth; mod chars_cmp; @@ -35,6 +36,7 @@ mod manual_saturating_arithmetic; mod manual_str_repeat; mod map_collect_result_unit; mod map_flatten; +mod map_identity; mod map_unwrap_or; mod ok_expect; mod option_as_ref_deref; @@ -1032,6 +1034,30 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// **What it does:** Checks for occurrences where one vector gets extended instead of append + /// + /// **Why is this bad?** Using `append` instead of `extend` is more concise and faster + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let mut a = vec![1, 2, 3]; + /// let mut b = vec![4, 5, 6]; + /// + /// // Bad + /// a.extend(b.drain(..)); + /// + /// // Good + /// a.append(&mut b); + /// ``` + pub APPEND_INSTEAD_OF_EXTEND, + perf, + "using vec.append(&mut vec) to move the full range of a vecor to another" +} + +declare_clippy_lint! { /// **What it does:** Checks for the use of `.extend(s.chars())` where s is a /// `&str` or `String`. /// @@ -1222,7 +1248,7 @@ declare_clippy_lint! { /// let _ = (0..3).map(|x| x + 2).count(); /// ``` pub SUSPICIOUS_MAP, - complexity, + suspicious, "suspicious usage of map" } @@ -1504,7 +1530,7 @@ declare_clippy_lint! { /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` pub FROM_ITER_INSTEAD_OF_COLLECT, - style, + pedantic, "use `.collect()` instead of `::from_iter()`" } @@ -1562,6 +1588,29 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// **What it does:** Checks for instances of `map(f)` where `f` is the identity function. + /// + /// **Why is this bad?** It can be written more concisely without the call to `map`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// let x = [1, 2, 3]; + /// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect(); + /// ``` + /// Use instead: + /// ```rust + /// let x = [1, 2, 3]; + /// let y: Vec<_> = x.iter().map(|x| 2*x).collect(); + /// ``` + pub MAP_IDENTITY, + complexity, + "using iterator.map(|x| x)" +} + +declare_clippy_lint! { /// **What it does:** Checks for the use of `.bytes().nth()`. /// /// **Why is this bad?** `.as_bytes().get()` is more efficient and more @@ -1728,6 +1777,7 @@ impl_lint_pass!(Methods => [ FILTER_NEXT, SKIP_WHILE_NEXT, FILTER_MAP_IDENTITY, + MAP_IDENTITY, MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, @@ -1760,7 +1810,8 @@ impl_lint_pass!(Methods => [ INSPECT_FOR_EACH, IMPLICIT_CLONE, SUSPICIOUS_SPLITN, - MANUAL_STR_REPEAT + MANUAL_STR_REPEAT, + APPEND_INSTEAD_OF_EXTEND ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -1985,7 +2036,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Option<&RustcVersion>) { if let Some((name, [recv, args @ ..], span)) = method_call!(expr) { match (name, args) { - ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => { + ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => { zst_offset::check(cx, expr, recv); }, ("and_then", [arg]) => { @@ -2022,7 +2073,10 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv), _ => expect_used::check(cx, expr, recv), }, - ("extend", [arg]) => string_extend_chars::check(cx, expr, recv, arg), + ("extend", [arg]) => { + string_extend_chars::check(cx, expr, recv, arg); + append_instead_of_extend::check(cx, expr, recv, arg); + }, ("filter_map", [arg]) => { unnecessary_filter_map::check(cx, expr, arg); filter_map_identity::check(cx, expr, arg, span); @@ -2058,6 +2112,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio _ => {}, } } + map_identity::check(cx, expr, recv, m_arg, span); }, ("map_or", [def, map]) => option_map_or_none::check(cx, expr, recv, def, map), ("next", []) => { diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index 800172f4cf3..073c5570a88 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -87,7 +87,7 @@ pub(super) fn check<'tcx>( ]; if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind { - if path.ident.as_str() == "len" { + if path.ident.name == sym::len { let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); match ty.kind() { diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs new file mode 100644 index 00000000000..59565350f72 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -0,0 +1,102 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; + +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::Applicability; +use rustc_hir::{def::Res, def_id::DefId, Crate, Item, ItemKind, UseKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Symbol; + +use crate::utils::conf::Rename; + +declare_clippy_lint! { + /// **What it does:** Checks for imports that do not rename the item as specified + /// in the `enforce-import-renames` config option. + /// + /// **Why is this bad?** Consistency is important, if a project has defined import + /// renames they should be followed. More practically, some item names are too + /// vague outside of their defining scope this can enforce a more meaningful naming. + /// + /// **Known problems:** None + /// + /// **Example:** + /// + /// An example clippy.toml configuration: + /// ```toml + /// # clippy.toml + /// enforced-import-renames = [ { path = "serde_json::Value", rename = "JsonValue" }] + /// ``` + /// + /// ```rust,ignore + /// use serde_json::Value; + /// ``` + /// Use instead: + /// ```rust,ignore + /// use serde_json::Value as JsonValue; + /// ``` + pub MISSING_ENFORCED_IMPORT_RENAMES, + restriction, + "enforce import renames" +} + +pub struct ImportRename { + conf_renames: Vec<Rename>, + renames: FxHashMap<DefId, Symbol>, +} + +impl ImportRename { + pub fn new(conf_renames: Vec<Rename>) -> Self { + Self { + conf_renames, + renames: FxHashMap::default(), + } + } +} + +impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]); + +impl LateLintPass<'_> for ImportRename { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + for Rename { path, rename } in &self.conf_renames { + if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &path.split("::").collect::<Vec<_>>()) { + self.renames.insert(id, Symbol::intern(rename)); + } + } + } + + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if_chain! { + if let ItemKind::Use(path, UseKind::Single) = &item.kind; + if let Res::Def(_, id) = path.res; + if let Some(name) = self.renames.get(&id); + // Remove semicolon since it is not present for nested imports + let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';'); + if let Some(snip) = snippet_opt(cx, span_without_semi); + if let Some(import) = match snip.split_once(" as ") { + None => Some(snip.as_str()), + Some((import, rename)) => { + if rename.trim() == &*name.as_str() { + None + } else { + Some(import.trim()) + } + }, + }; + then { + span_lint_and_sugg( + cx, + MISSING_ENFORCED_IMPORT_RENAMES, + span_without_semi, + "this import should be renamed", + "try", + format!( + "{} as {}", + import, + name, + ), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 1786d5805d7..6c87136e5e1 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// } /// ``` pub MUTABLE_KEY_TYPE, - correctness, + suspicious, "Check for mutable `Map`/`Set` key type" } diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index b2206a82208..910b0536092 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -167,7 +167,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, BlockCheckMode::DefaultBlock => Some(vec![&**e]), // in case of compiler-inserted signaling blocks - _ => reduce_expression(cx, e), + BlockCheckMode::UnsafeBlock(_) => reduce_expression(cx, e), } }) } else { diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs new file mode 100644 index 00000000000..1adad5be6dd --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs @@ -0,0 +1,276 @@ +use std::{ + fmt, + hash::{Hash, Hasher}, +}; + +use clippy_utils::{diagnostics::span_lint_and_help, in_macro, is_direct_expn_of, source::snippet_opt}; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; +use serde::{de, Deserialize}; + +declare_clippy_lint! { + /// **What it does:** Checks that common macros are used with consistent bracing. + /// + /// **Why is this bad?** This is mostly a consistency lint although using () or [] + /// doesn't give you a semicolon in item position, which can be unexpected. + /// + /// **Known problems:** + /// None + /// + /// **Example:** + /// + /// ```rust + /// vec!{1, 2, 3}; + /// ``` + /// Use instead: + /// ```rust + /// vec![1, 2, 3]; + /// ``` + pub NONSTANDARD_MACRO_BRACES, + style, + "check consistent use of braces in macro" +} + +const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")]; + +/// The (name, (open brace, close brace), source snippet) +type MacroInfo<'a> = (&'a str, &'a (String, String), String); + +#[derive(Clone, Debug, Default)] +pub struct MacroBraces { + macro_braces: FxHashMap<String, (String, String)>, + done: FxHashSet<Span>, +} + +impl MacroBraces { + pub fn new(conf: &FxHashSet<MacroMatcher>) -> Self { + let macro_braces = macro_braces(conf.clone()); + Self { + macro_braces, + done: FxHashSet::default(), + } + } +} + +impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]); + +impl EarlyLintPass for MacroBraces { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + if let Some((name, braces, snip)) = is_offending_macro(cx, item.span, self) { + let span = item.span.ctxt().outer_expn_data().call_site; + emit_help(cx, snip, braces, name, span); + self.done.insert(span); + } + } + + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { + if let Some((name, braces, snip)) = is_offending_macro(cx, stmt.span, self) { + let span = stmt.span.ctxt().outer_expn_data().call_site; + emit_help(cx, snip, braces, name, span); + self.done.insert(span); + } + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { + if let Some((name, braces, snip)) = is_offending_macro(cx, expr.span, self) { + let span = expr.span.ctxt().outer_expn_data().call_site; + emit_help(cx, snip, braces, name, span); + self.done.insert(span); + } + } + + fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { + if let Some((name, braces, snip)) = is_offending_macro(cx, ty.span, self) { + let span = ty.span.ctxt().outer_expn_data().call_site; + emit_help(cx, snip, braces, name, span); + self.done.insert(span); + } + } +} + +fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, this: &'a MacroBraces) -> Option<MacroInfo<'a>> { + if_chain! { + if in_macro(span); + if let Some((name, braces)) = find_matching_macro(span, &this.macro_braces); + if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site); + let c = snip.replace(" ", ""); // make formatting consistent + if !c.starts_with(&format!("{}!{}", name, braces.0)); + if !this.done.contains(&span.ctxt().outer_expn_data().call_site); + then { + Some((name, braces, snip)) + } else { + None + } + } +} + +fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: &str, span: Span) { + let with_space = &format!("! {}", braces.0); + let without_space = &format!("!{}", braces.0); + let mut help = snip; + for b in BRACES.iter().filter(|b| b.0 != braces.0) { + help = help.replace(b.0, &braces.0).replace(b.1, &braces.1); + // Only `{` traditionally has space before the brace + if braces.0 != "{" && help.contains(with_space) { + help = help.replace(with_space, without_space); + } else if braces.0 == "{" && help.contains(without_space) { + help = help.replace(without_space, with_space); + } + } + span_lint_and_help( + cx, + NONSTANDARD_MACRO_BRACES, + span, + &format!("use of irregular braces for `{}!` macro", name), + Some(span), + &format!("consider writing `{}`", help), + ); +} + +fn find_matching_macro( + span: Span, + braces: &FxHashMap<String, (String, String)>, +) -> Option<(&String, &(String, String))> { + braces + .iter() + .find(|(macro_name, _)| is_direct_expn_of(span, macro_name).is_some()) +} + +fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> { + let mut braces = vec![ + macro_matcher!( + name: "print", + braces: ("(", ")"), + ), + macro_matcher!( + name: "println", + braces: ("(", ")"), + ), + macro_matcher!( + name: "eprint", + braces: ("(", ")"), + ), + macro_matcher!( + name: "eprintln", + braces: ("(", ")"), + ), + macro_matcher!( + name: "write", + braces: ("(", ")"), + ), + macro_matcher!( + name: "writeln", + braces: ("(", ")"), + ), + macro_matcher!( + name: "format", + braces: ("(", ")"), + ), + macro_matcher!( + name: "format_args", + braces: ("(", ")"), + ), + macro_matcher!( + name: "vec", + braces: ("[", "]"), + ), + ] + .into_iter() + .collect::<FxHashMap<_, _>>(); + // We want users items to override any existing items + for it in conf { + braces.insert(it.name, it.braces); + } + braces +} + +macro_rules! macro_matcher { + (name: $name:expr, braces: ($open:expr, $close:expr) $(,)?) => { + ($name.to_owned(), ($open.to_owned(), $close.to_owned())) + }; +} +pub(crate) use macro_matcher; + +#[derive(Clone, Debug)] +pub struct MacroMatcher { + name: String, + braces: (String, String), +} + +impl Hash for MacroMatcher { + fn hash<H: Hasher>(&self, state: &mut H) { + self.name.hash(state); + } +} + +impl PartialEq for MacroMatcher { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} +impl Eq for MacroMatcher {} + +impl<'de> Deserialize<'de> for MacroMatcher { + fn deserialize<D>(deser: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(field_identifier, rename_all = "lowercase")] + enum Field { + Name, + Brace, + } + struct MacVisitor; + impl<'de> de::Visitor<'de> for MacVisitor { + type Value = MacroMatcher; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("struct MacroMatcher") + } + + fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> + where + V: de::MapAccess<'de>, + { + let mut name = None; + let mut brace: Option<&str> = None; + while let Some(key) = map.next_key()? { + match key { + Field::Name => { + if name.is_some() { + return Err(de::Error::duplicate_field("name")); + } + name = Some(map.next_value()?); + }, + Field::Brace => { + if brace.is_some() { + return Err(de::Error::duplicate_field("brace")); + } + brace = Some(map.next_value()?); + }, + } + } + let name = name.ok_or_else(|| de::Error::missing_field("name"))?; + let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?; + Ok(MacroMatcher { + name, + braces: BRACES + .iter() + .find(|b| b.0 == brace) + .map(|(o, c)| ((*o).to_owned(), (*c).to_owned())) + .ok_or_else(|| { + de::Error::custom(&format!("expected one of `(`, `{{`, `[` found `{}`", brace)) + })?, + }) + } + } + + const FIELDS: &[&str] = &["name", "brace"]; + deser.deserialize_struct("MacroMatcher", FIELDS, MacVisitor) + } +} diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index ae5f0627fd6..b41c478c266 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -329,7 +329,7 @@ fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: if is_integer_const(cx, start, 0); // `.len()` call if let ExprKind::MethodCall(len_path, _, len_args, _) = end.kind; - if len_path.ident.name == sym!(len) && len_args.len() == 1; + if len_path.ident.name == sym::len && len_args.len() == 1; // `.iter()` and `.len()` called on same `Path` if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_args[0].kind; if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_args[0].kind; diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 7dafce60d5e..119ec21520f 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -132,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { } } - // `{ cloned = &arg; clone(move cloned); }` or `{ cloned = &arg; to_path_buf(cloned); }` + // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }` let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb)); let loc = mir::Location { 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 16e4d73851f..da3e30af35c 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 @@ -1,3 +1,4 @@ +use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_macro_callsite; use clippy_utils::{in_macro, sugg}; @@ -45,6 +46,7 @@ impl LateLintPass<'_> for SemicolonIfNothingReturned { if t_expr.is_unit(); if let snippet = snippet_with_macro_callsite(cx, expr.span, "}"); if !snippet.ends_with('}'); + if cx.sess().source_map().is_multiline(block.span); then { // filter out the desugared `for` loop if let ExprKind::DropTemps(..) = &expr.kind { diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 512abde11a6..2203ab57b10 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// } /// ``` pub SUSPICIOUS_ARITHMETIC_IMPL, - correctness, + suspicious, "suspicious use of operators in impl of arithmetic trait" } @@ -47,7 +47,7 @@ declare_clippy_lint! { /// } /// ``` pub SUSPICIOUS_OP_ASSIGN_IMPL, - correctness, + suspicious, "suspicious use of operators in impl of OpAssign trait" } diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 1b3c457b01a..07a4e294049 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -1,6 +1,6 @@ #![allow(clippy::wildcard_imports, clippy::enum_glob_use)] -use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_pat, eq_path, eq_maybe_qself}; +use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{meets_msrv, msrvs, over}; use rustc_ast::mut_visit::*; @@ -277,7 +277,8 @@ fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) ps1, start, alternatives, |k, ps1, idx| matches!( k, - TupleStruct(qself2, path2, ps2) if eq_maybe_qself(qself1, qself2) && eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx) + TupleStruct(qself2, path2, ps2) + if eq_maybe_qself(qself1, qself2) && eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx) ), |k| always_pat!(k, TupleStruct(_, _, ps) => ps), ), diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 254b104bdef..906ac10f461 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -1,23 +1,22 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; use clippy_utils::ty::same_type_and_consts; use clippy_utils::{in_macro, meets_msrv, msrvs}; use if_chain::if_chain; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{ self as hir, - def::{self, DefKind}, + def::{CtorOf, DefKind, Res}, def_id::LocalDefId, intravisit::{walk_ty, NestedVisitorMap, Visitor}, - Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment, - QPath, TyKind, + Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; -use rustc_middle::ty::{AssocKind, Ty}; +use rustc_middle::ty::AssocKind; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{BytePos, Span}; +use rustc_span::Span; use rustc_typeck::hir_ty_to_ty; declare_clippy_lint! { @@ -75,10 +74,9 @@ impl UseSelf { #[derive(Debug)] enum StackItem { Check { - hir_id: HirId, - impl_trait_ref_def_id: Option<LocalDefId>, - types_to_skip: Vec<HirId>, - types_to_lint: Vec<HirId>, + impl_id: LocalDefId, + in_body: u32, + types_to_skip: FxHashSet<HirId>, }, NoCheck, } @@ -88,60 +86,41 @@ impl_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; impl<'tcx> LateLintPass<'tcx> for UseSelf { - fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) { + if !is_item_interesting(item) { + // This does two things: + // 1) Reduce needless churn on `self.stack` + // 2) Don't push `StackItem::NoCheck` when entering `ItemKind::OpaqueTy`, + // in order to lint `foo() -> impl <..>` + return; + } // We push the self types of `impl`s on a stack here. Only the top type on the stack is // relevant for linting, since this is the self type of the `impl` we're currently in. To // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that // we're in an `impl` or nested item, that we don't want to lint - // - // NB: If you push something on the stack in this method, remember to also pop it in the - // `check_item_post` method. - match &item.kind { - ItemKind::Impl(Impl { - self_ty: hir_self_ty, - of_trait, - .. - }) => { - let should_check = if let TyKind::Path(QPath::Resolved(_, item_path)) = hir_self_ty.kind { - let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; - parameters.as_ref().map_or(true, |params| { - !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) - }) - } else { - false - }; - let impl_trait_ref_def_id = of_trait.as_ref().map(|_| cx.tcx.hir().local_def_id(item.hir_id())); - if should_check { - self.stack.push(StackItem::Check { - hir_id: hir_self_ty.hir_id, - impl_trait_ref_def_id, - types_to_lint: Vec::new(), - types_to_skip: Vec::new(), - }); - } else { - self.stack.push(StackItem::NoCheck); + let stack_item = if_chain! { + if let ItemKind::Impl(Impl { self_ty, .. }) = item.kind; + if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind; + let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; + if parameters.as_ref().map_or(true, |params| { + !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) + }); + then { + StackItem::Check { + impl_id: item.def_id, + in_body: 0, + types_to_skip: std::iter::once(self_ty.hir_id).collect(), } - }, - ItemKind::Static(..) - | ItemKind::Const(..) - | ItemKind::Fn(..) - | ItemKind::Enum(..) - | ItemKind::Struct(..) - | ItemKind::Union(..) - | ItemKind::Trait(..) => { - self.stack.push(StackItem::NoCheck); - }, - _ => (), - } + } else { + StackItem::NoCheck + } + }; + self.stack.push(stack_item); } fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { - use ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union}; - match item.kind { - Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => { - self.stack.pop(); - }, - _ => (), + if is_item_interesting(item) { + self.stack.pop(); } } @@ -151,11 +130,11 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if_chain! { if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind; if let Some(&mut StackItem::Check { - impl_trait_ref_def_id: Some(def_id), + impl_id, ref mut types_to_skip, .. }) = self.stack.last_mut(); - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(def_id); + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id); then { // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be // `Self`. @@ -203,142 +182,76 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) { + fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) { // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`. // However the `node_type()` method can *only* be called in bodies. - // - // This method implementation determines which types should get linted in a `Body` and - // which shouldn't, with a visitor. We could directly lint in the visitor, but then we - // could only allow this lint on item scope. And we would have to check if those types are - // already dealt with in `check_ty` anyway. - if let Some(StackItem::Check { - hir_id, - types_to_lint, - types_to_skip, - .. - }) = self.stack.last_mut() - { - let self_ty = ty_from_hir_id(cx, *hir_id); - - let mut visitor = LintTyCollector { - cx, - self_ty, - types_to_lint: vec![], - types_to_skip: vec![], - }; - visitor.visit_expr(&body.value); - types_to_lint.extend(visitor.types_to_lint); - types_to_skip.extend(visitor.types_to_skip); + if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() { + *in_body = in_body.saturating_add(1); } } - fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { - if in_macro(hir_ty.span) - || in_impl(cx, hir_ty) - || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) - { - return; + fn check_body_post(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) { + if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() { + *in_body = in_body.saturating_sub(1); } + } - let lint_dependend_on_expr_kind = if let Some(StackItem::Check { - hir_id, - types_to_lint, - types_to_skip, - .. - }) = self.stack.last() - { - if types_to_skip.contains(&hir_ty.hir_id) { - false - } else if types_to_lint.contains(&hir_ty.hir_id) { - true + fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + if_chain! { + if !in_macro(hir_ty.span); + if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS); + if let Some(&StackItem::Check { + impl_id, + in_body, + ref types_to_skip, + }) = self.stack.last(); + if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; + if !matches!(path.res, Res::SelfTy(..) | Res::Def(DefKind::TyParam, _)); + if !types_to_skip.contains(&hir_ty.hir_id); + let ty = if in_body > 0 { + cx.typeck_results().node_type(hir_ty.hir_id) } else { - let self_ty = ty_from_hir_id(cx, *hir_id); - should_lint_ty(hir_ty, hir_ty_to_ty(cx.tcx, hir_ty), self_ty) - } - } else { - false - }; - - if lint_dependend_on_expr_kind { - // FIXME: this span manipulation should not be necessary - // @flip1995 found an ast lowering issue in - // https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162 + hir_ty_to_ty(cx.tcx, hir_ty) + }; + if same_type_and_consts(ty, cx.tcx.type_of(impl_id)); let hir = cx.tcx.hir(); let id = hir.get_parent_node(hir_ty.hir_id); - - if !hir.opt_span(id).map_or(false, in_macro) { - match hir.find(id) { - Some(Node::Expr(Expr { - kind: ExprKind::Path(QPath::TypeRelative(_, segment)), - .. - })) => span_lint_until_last_segment(cx, hir_ty.span, segment), - _ => span_lint(cx, hir_ty.span), - } + if !hir.opt_span(id).map_or(false, in_macro); + then { + span_lint(cx, hir_ty.span); } } } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - fn expr_ty_matches(cx: &LateContext<'_>, expr: &Expr<'_>, self_ty: Ty<'_>) -> bool { - let def_id = expr.hir_id.owner; - if cx.tcx.has_typeck_results(def_id) { - cx.tcx.typeck(def_id).expr_ty_opt(expr) == Some(self_ty) - } else { - false - } - } - - if in_macro(expr.span) || !meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS) { - return; + if_chain! { + if !in_macro(expr.span); + if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS); + if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last(); + if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id); + then {} else { return; } } - - if let Some(StackItem::Check { hir_id, .. }) = self.stack.last() { - let self_ty = ty_from_hir_id(cx, *hir_id); - - match &expr.kind { - ExprKind::Struct(QPath::Resolved(_, path), ..) => { - if expr_ty_matches(cx, expr, self_ty) { - match path.res { - def::Res::SelfTy(..) => (), - def::Res::Def(DefKind::Variant, _) => span_lint_on_path_until_last_segment(cx, path), - _ => { - span_lint(cx, path.span); - }, - } - } - }, - // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) - ExprKind::Call(fun, _) => { - if let Expr { - kind: ExprKind::Path(ref qpath), - .. - } = fun - { - if expr_ty_matches(cx, expr, self_ty) { - let res = cx.qpath_res(qpath, fun.hir_id); - - if let def::Res::Def(DefKind::Ctor(ctor_of, _), ..) = res { - match ctor_of { - def::CtorOf::Variant => { - span_lint_on_qpath_resolved(cx, qpath, true); - }, - def::CtorOf::Struct => { - span_lint_on_qpath_resolved(cx, qpath, false); - }, - } - } + match expr.kind { + ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res { + Res::SelfTy(..) => (), + Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path), + _ => span_lint(cx, path.span), + }, + // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) + ExprKind::Call(fun, _) => { + if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind { + if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res { + match ctor_of { + CtorOf::Variant => lint_path_to_variant(cx, path), + CtorOf::Struct => span_lint(cx, path.span), } } - }, - // unit enum variants (`Enum::A`) - ExprKind::Path(qpath) => { - if expr_ty_matches(cx, expr, self_ty) { - span_lint_on_qpath_resolved(cx, qpath, true); - } - }, - _ => (), - } + } + }, + // unit enum variants (`Enum::A`) + ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path), + _ => (), } } @@ -364,35 +277,6 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { } } -struct LintTyCollector<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - self_ty: Ty<'tcx>, - types_to_lint: Vec<HirId>, - types_to_skip: Vec<HirId>, -} - -impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) { - if_chain! { - if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id); - if should_lint_ty(hir_ty, ty, self.self_ty); - then { - self.types_to_lint.push(hir_ty.hir_id); - } else { - self.types_to_skip.push(hir_ty.hir_id); - } - } - - walk_ty(self, hir_ty); - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { - NestedVisitorMap::None - } -} - fn span_lint(cx: &LateContext<'_>, span: Span) { span_lint_and_sugg( cx, @@ -405,66 +289,19 @@ fn span_lint(cx: &LateContext<'_>, span: Span) { ); } -#[allow(clippy::cast_possible_truncation)] -fn span_lint_until_last_segment(cx: &LateContext<'_>, span: Span, segment: &PathSegment<'_>) { - let sp = span.with_hi(segment.ident.span.lo()); - // remove the trailing :: - let span_without_last_segment = match snippet_opt(cx, sp) { - Some(snippet) => match snippet.rfind("::") { - Some(bidx) => sp.with_hi(sp.lo() + BytePos(bidx as u32)), - None => sp, - }, - None => sp, - }; - span_lint(cx, span_without_last_segment); -} - -fn span_lint_on_path_until_last_segment(cx: &LateContext<'_>, path: &Path<'_>) { - if path.segments.len() > 1 { - span_lint_until_last_segment(cx, path.span, path.segments.last().unwrap()); - } -} - -fn span_lint_on_qpath_resolved(cx: &LateContext<'_>, qpath: &QPath<'_>, until_last_segment: bool) { - if let QPath::Resolved(_, path) = qpath { - if until_last_segment { - span_lint_on_path_until_last_segment(cx, path); - } else { - span_lint(cx, path.span); - } - } -} - -fn ty_from_hir_id<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Ty<'tcx> { - if let Some(Node::Ty(hir_ty)) = cx.tcx.hir().find(hir_id) { - hir_ty_to_ty(cx.tcx, hir_ty) - } else { - unreachable!("This function should only be called with `HirId`s that are for sure `Node::Ty`") - } -} - -fn in_impl(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> bool { - let map = cx.tcx.hir(); - let parent = map.get_parent_node(hir_ty.hir_id); - if_chain! { - if let Some(Node::Item(item)) = map.find(parent); - if let ItemKind::Impl { .. } = item.kind; - then { - true - } else { - false - } +fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) { + if let [.., self_seg, _variant] = path.segments { + let span = path + .span + .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi()); + span_lint(cx, span); } } -fn should_lint_ty(hir_ty: &hir::Ty<'_>, ty: Ty<'_>, self_ty: Ty<'_>) -> bool { - if_chain! { - if same_type_and_consts(ty, self_ty); - if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; - then { - !matches!(path.res, def::Res::SelfTy(..)) - } else { - false - } - } +fn is_item_interesting(item: &Item<'_>) -> bool { + use rustc_hir::ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union}; + matches!( + item.kind, + Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) + ) } diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 2be99fb761b..c97f7e1626e 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } if_chain! { - if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into"; + if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && name.ident.name == sym::try_into; let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(&args[0]); if is_type_diagnostic_item(cx, a, sym::result_type); diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 0e33ae740d9..44d3d456342 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -8,6 +8,13 @@ use std::error::Error; use std::path::{Path, PathBuf}; use std::{env, fmt, fs, io}; +/// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. +#[derive(Clone, Debug, Deserialize)] +pub struct Rename { + pub path: String, + pub rename: String, +} + /// Conf with parse errors #[derive(Default)] pub struct TryConf { @@ -24,6 +31,9 @@ impl TryConf { } } +/// Note that the configuration parsing currently doesn't support documentation that will +/// that spans over several lines. This will be possible with the new implementation +/// See (rust-clippy#7172) macro_rules! define_Conf { ($( #[doc = $doc:literal] @@ -149,7 +159,7 @@ define_Conf! { "WebGL", "TensorFlow", "TrueType", - "iOS", "macOS", + "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase", @@ -182,20 +192,28 @@ define_Conf! { (vec_box_size_threshold: u64 = 4096), /// Lint: TYPE_REPETITION_IN_BOUNDS. The maximum number of bounds a trait can have to be linted (max_trait_bounds: u64 = 3), - /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bools a struct can have + /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bool fields a struct can have (max_struct_bools: u64 = 3), - /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have + /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bool parameters a function can have (max_fn_params_bools: u64 = 3), /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests). (warn_on_all_wildcard_imports: bool = false), /// Lint: DISALLOWED_METHOD. The list of disallowed methods, written as fully qualified paths. (disallowed_methods: Vec<String> = Vec::new()), + /// Lint: DISALLOWED_TYPE. The list of disallowed types, written as fully qualified paths. + (disallowed_types: Vec<String> = Vec::new()), /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators. (unreadable_literal_lint_fractions: bool = true), /// Lint: UPPER_CASE_ACRONYMS. Enables verbose mode. Triggers if there is more than one uppercase char next to each other (upper_case_acronyms_aggressive: bool = false), /// Lint: _CARGO_COMMON_METADATA. For internal testing only, ignores the current `publish` settings in the Cargo manifest. (cargo_ignore_publish: bool = false), + /// Lint: NONSTANDARD_MACRO_BRACES. Enforce the named macros always use the braces specified. <br> A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro is could be used with a full path two `MacroMatcher`s have to be added one with the full path `crate_name::macro_name` and one with just the macro name. + (standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()), + /// Lint: MISSING_ENFORCED_IMPORT_RENAMES. The list of imports to always rename, a fully qualified path followed by the rename. + (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()), + /// Lint: RESTRICTED_SCRIPTS. The list of unicode scripts allowed to be used in the scope. + (allowed_scripts: Vec<String> = vec!["Latin".to_string()]), } /// Search for the configuration file. 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 46af03663b8..e877af09e28 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 @@ -9,6 +9,7 @@ //! a simple mistake) use if_chain::if_chain; +use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{ self as hir, def::DefKind, intravisit, intravisit::Visitor, ExprKind, Item, ItemKind, Mutability, QPath, @@ -46,8 +47,9 @@ const DEPRECATED_LINT_GROUP_STR: &str = "deprecated"; const DEPRECATED_LINT_LEVEL: &str = "none"; /// This array holds Clippy's lint groups with their corresponding default lint level. The /// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`. -const DEFAULT_LINT_LEVELS: [(&str, &str); 8] = [ +const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[ ("correctness", "deny"), + ("suspicious", "warn"), ("restriction", "allow"), ("style", "warn"), ("pedantic", "allow"), @@ -485,16 +487,32 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St /// /// Would result in `Hello world!\n=^.^=\n` fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { - cx.tcx - .hir() - .attrs(item.hir_id()) - .iter() - .filter_map(|x| x.doc_str().map(|sym| sym.as_str().to_string())) - .reduce(|mut acc, sym| { - acc.push_str(&sym); - acc.push('\n'); - acc - }) + let attrs = cx.tcx.hir().attrs(item.hir_id()); + let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str); + let mut docs = String::from(&*lines.next()?.as_str()); + let mut in_code_block = false; + for line in lines { + docs.push('\n'); + let line = line.as_str(); + let line = &*line; + if let Some(info) = line.trim_start().strip_prefix("```") { + in_code_block = !in_code_block; + if in_code_block { + let lang = info + .trim() + .split(',') + // remove rustdoc directives + .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic")) + // if no language is present, fill in "rust" + .unwrap_or("rust"); + docs.push_str("```"); + docs.push_str(lang); + continue; + } + } + docs.push_str(line); + } + Some(docs) } fn get_lint_group_and_level_or_lint( diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 51c1117d206..520586b3a1f 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::in_macro; use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::{in_macro, is_test_module_or_function}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -106,7 +106,7 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if is_test_module_or_function(item) { + if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { @@ -183,8 +183,8 @@ impl LateLintPass<'_> for WildcardImports { } } - fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { - if is_test_module_or_function(item) { + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_sub(1); } } @@ -208,7 +208,3 @@ fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.name == kw::Super } - -fn is_test_module_or_function(item: &Item<'_>) -> bool { - matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") -} diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 93ed3b18400..6ede9011208 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.54" +version = "0.1.55" authors = ["The Rust Clippy Developers"] edition = "2018" publish = false diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 90c034bd02a..30c2260d15c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -47,9 +47,14 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool { | (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r), (Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)), (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), - (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)), + (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => { + eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)) + }, (Struct(lqself, lp, lfs, lr), Struct(rqself, rp, rfs, rr)) => { - lr == rr && eq_maybe_qself(lqself, rqself) &&eq_path(lp, rp) && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf)) + lr == rr + && eq_maybe_qself(lqself, rqself) + && eq_path(lp, rp) + && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf)) }, (Or(ls), Or(rs)) => unordered_over(ls, rs, |l, r| eq_pat(l, r)), (MacCall(l), MacCall(r)) => eq_mac_call(l, r), @@ -82,7 +87,7 @@ pub fn eq_maybe_qself(l: &Option<QSelf>, r: &Option<QSelf>) -> bool { match (l, r) { (Some(l), Some(r)) => eq_qself(l, r), (None, None) => true, - _ => false + _ => false, } } diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 0318c483959..c19b558cd8c 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -157,3 +157,8 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { .filter_map(ast::Attribute::meta_item_list) .any(|l| attr::list_contains_name(&l, sym::hidden)) } + +/// Return true if the attributes contain `#[unstable]` +pub fn is_unstable(attrs: &[ast::Attribute]) -> bool { + attrs.iter().any(|attr| attr.has_name(sym::unstable)) +} diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 0d7fdeeb920..15c27d1a996 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1,6 +1,6 @@ #![allow(clippy::float_cmp)] -use crate::{clip, sext, unsext}; +use crate::{clip, is_direct_expn_of, sext, unsext}; use if_chain::if_chain; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; @@ -230,7 +230,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { match e.kind { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)), ExprKind::Block(block, _) => self.block(block), - ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))), + ExprKind::Lit(ref lit) => { + if is_direct_expn_of(e.span, "cfg").is_some() { + None + } else { + Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))) + } + }, ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec), ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(value, _) => { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 769836aaf18..217a1f4dded 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -72,7 +72,7 @@ use rustc_hir::LangItem::{ResultErr, ResultOk}; use rustc_hir::{ def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path, - PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, + PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::exports::Export; @@ -326,16 +326,6 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) .map_or(false, |did| is_diag_trait_item(cx, did, diag_item)) } -/// 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, path)) = expr.kind { - if let [p] = path.segments { - return p.ident.name == var; - } - } - false -} - pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> { match *path { QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"), @@ -493,7 +483,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res { _ => return Res::Err, }; let tcx = cx.tcx; - let crates = tcx.crates(); + let crates = tcx.crates(()); let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate)); let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first)); let last = path @@ -707,16 +697,6 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> { } } -/// Gets the name of a `Pat`, if any. -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(p) | PatKind::Ref(p, _) => get_pat_name(&*p), - _ => None, - } -} - pub struct ContainsName { pub name: Symbol, pub result: bool, @@ -861,14 +841,16 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio }) } -/// Gets the loop enclosing the given expression, if any. -pub fn get_enclosing_loop(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> { +/// Gets the loop or closure enclosing the given expression, if any. +pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> { let map = tcx.hir(); for (_, node) in map.parent_iter(expr.hir_id) { match node { Node::Expr( - e @ Expr { - kind: ExprKind::Loop(..), + e + @ + Expr { + kind: ExprKind::Loop(..) | ExprKind::Closure(..), .. }, ) => return Some(e), @@ -1399,6 +1381,55 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some()) } +/// Checks if an expression represents the identity function +/// Only examines closures and `std::convert::identity` +pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + /// Checks if a function's body represents the identity function. Looks for bodies of the form: + /// * `|x| x` + /// * `|x| return x` + /// * `|x| { return x }` + /// * `|x| { return x; }` + fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { + let id = if_chain! { + if let [param] = func.params; + if let PatKind::Binding(_, id, _, _) = param.pat.kind; + then { + id + } else { + return false; + } + }; + + let mut expr = &func.value; + loop { + match expr.kind { + #[rustfmt::skip] + ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, ) + | ExprKind::Ret(Some(e)) => expr = e, + #[rustfmt::skip] + ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => { + if_chain! { + if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind; + if let ExprKind::Ret(Some(ret_val)) = e.kind; + then { + expr = ret_val; + } else { + return false; + } + } + }, + _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(), + } + } + } + + match expr.kind { + ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)), + ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY), + _ => false, + } +} + /// Gets the node where an expression is either used, or it's type is unified with another branch. pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> { let map = tcx.hir(); @@ -1654,6 +1685,19 @@ pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) { (e, count) } +/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is +/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed. +pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> { + loop { + match expr.kind { + ExprKind::AddrOf(_, _, e) => expr = e, + ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e, + _ => break, + } + } + expr +} + #[macro_export] macro_rules! unwrap_cargo_metadata { ($cx: ident, $lint: ident, $deps: expr) => {{ @@ -1683,3 +1727,15 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { } } } + +/// Checks whether item either has `test` attribute applied, or +/// is a module with `test` in its name. +pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { + if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) { + if tcx.has_attr(def_id.to_def_id(), sym::test) { + return true; + } + } + + matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") +} diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs index 791688cd194..8adb6915952 100644 --- a/src/tools/clippy/clippy_utils/src/ptr.rs +++ b/src/tools/clippy/clippy_utils/src/ptr.rs @@ -1,10 +1,10 @@ use crate::source::snippet; -use crate::{get_pat_name, match_var}; +use crate::{path_to_local_id, strip_pat_refs}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; +use rustc_hir::{Body, BodyId, Expr, ExprKind, HirId, PatKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use std::borrow::Cow; pub fn get_spans( @@ -14,10 +14,11 @@ pub fn get_spans( replacements: &[(&'static str, &'static str)], ) -> Option<Vec<(Span, Cow<'static, str>)>> { if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) { - get_binding_name(&body.params[idx]).map_or_else( - || Some(vec![]), - |name| extract_clone_suggestions(cx, name, replacements, body), - ) + if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind { + extract_clone_suggestions(cx, binding_id, replacements, body) + } else { + Some(vec![]) + } } else { Some(vec![]) } @@ -25,13 +26,13 @@ pub fn get_spans( fn extract_clone_suggestions<'tcx>( cx: &LateContext<'tcx>, - name: Symbol, + id: HirId, replace: &[(&'static str, &'static str)], body: &'tcx Body<'_>, ) -> Option<Vec<(Span, Cow<'static, str>)>> { let mut visitor = PtrCloneVisitor { cx, - name, + id, replace, spans: vec![], abort: false, @@ -42,7 +43,7 @@ fn extract_clone_suggestions<'tcx>( struct PtrCloneVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, - name: Symbol, + id: HirId, replace: &'a [(&'static str, &'static str)], spans: Vec<(Span, Cow<'static, str>)>, abort: bool, @@ -55,16 +56,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { if self.abort { return; } - if let ExprKind::MethodCall(seg, _, args, _) = expr.kind { - if args.len() == 1 && match_var(&args[0], self.name) { + if let ExprKind::MethodCall(seg, _, [recv], _) = expr.kind { + if path_to_local_id(recv, self.id) { if seg.ident.name.as_str() == "capacity" { self.abort = true; return; } for &(fn_name, suffix) in self.replace { if seg.ident.name.as_str() == fn_name { - self.spans - .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix)); + self.spans.push((expr.span, snippet(self.cx, recv.span, "_") + suffix)); return; } } @@ -77,7 +77,3 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { NestedVisitorMap::None } } - -fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> { - get_pat_name(arg.pat) -} diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index a92d3be5d3c..2808fc35e2a 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -128,7 +128,9 @@ pub fn implements_trait<'tcx>( return false; } let ty_params = cx.tcx.mk_substs(ty_params.iter()); - cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env)) + cx.tcx + .type_implements_trait((trait_id, ty, ty_params, cx.param_env)) + .must_apply_modulo_regions() } /// Checks whether this type implements `Drop`. diff --git a/src/tools/clippy/doc/basics.md b/src/tools/clippy/doc/basics.md index ed3a2fff83f..e98354358af 100644 --- a/src/tools/clippy/doc/basics.md +++ b/src/tools/clippy/doc/basics.md @@ -90,8 +90,10 @@ cargo dev fmt cargo dev update_lints # create a new lint and register it cargo dev new_lint +# automatically formatting all code before each commit +cargo dev setup git-hook # (experimental) Setup Clippy to work with IntelliJ-Rust -cargo dev ide_setup +cargo dev setup intellij ``` ## lintcheck diff --git a/src/tools/clippy/doc/common_tools_writing_lints.md b/src/tools/clippy/doc/common_tools_writing_lints.md index abac1227b4f..0a85f650011 100644 --- a/src/tools/clippy/doc/common_tools_writing_lints.md +++ b/src/tools/clippy/doc/common_tools_writing_lints.md @@ -6,7 +6,7 @@ You may need following tooltips to catch up with common operations. - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) - [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) - - [Checking if a type defines a method](#checking-if-a-type-defines-a-method) + - [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method) - [Dealing with macros](#dealing-with-macros) Useful Rustc dev guide links: diff --git a/src/tools/clippy/doc/release.md b/src/tools/clippy/doc/release.md index e0af9bf0625..afe3033c288 100644 --- a/src/tools/clippy/doc/release.md +++ b/src/tools/clippy/doc/release.md @@ -101,6 +101,21 @@ After this, the release should be available on the Clippy [release page]. [release page]: https://github.com/rust-lang/rust-clippy/releases +## Update the `stable` branch + +At this step you should have already checked out the commit of the `rust-1.XX.0` +tag. Updating the stable branch from here is as easy as: + +```bash +# Assuming the current directory corresponds to the Clippy repository and the +# commit of the just created rust-1.XX.0 tag is checked out. +$ git push upstream rust-1.XX.0:stable # `upstream` is the `rust-lang/rust-clippy` remote +``` + +_NOTE: Usually there are no stable backports for Clippy, so this update should +be possible without force pushing or anything like this. If there should have +happened a stable backport, make sure to re-merge those changes just as with the +`beta` branch._ ## Update `CHANGELOG.md` diff --git a/src/tools/clippy/lintcheck/README.md b/src/tools/clippy/lintcheck/README.md index a61070d8a80..8c169506e53 100644 --- a/src/tools/clippy/lintcheck/README.md +++ b/src/tools/clippy/lintcheck/README.md @@ -69,7 +69,7 @@ is checked. is explicitly specified in the options. ### Fix mode -You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `-Zunstable-options --fix` and +You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `--fix` and print a warning if Clippys suggestions fail to apply (if the resulting code does not build). This lets us spot bad suggestions or false positives automatically in some cases. diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs index f6a75595c98..7d2f3173fb0 100644 --- a/src/tools/clippy/lintcheck/src/main.rs +++ b/src/tools/clippy/lintcheck/src/main.rs @@ -260,14 +260,7 @@ impl Crate { let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir"); let mut args = if fix { - vec![ - "-Zunstable-options", - "--fix", - "-Zunstable-options", - "--allow-no-vcs", - "--", - "--cap-lints=warn", - ] + vec!["--fix", "--allow-no-vcs", "--", "--cap-lints=warn"] } else { vec!["--", "--message-format=json", "--", "--cap-lints=warn"] }; diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index e3863c46288..2d3c65c1d39 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-06-03" +channel = "nightly-2021-07-01" components = ["llvm-tools-preview", "rustc-dev", "rust-src"] diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index 7bb80b1196e..6bd4123ddeb 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -70,7 +70,6 @@ impl ClippyCmd { I: Iterator<Item = String>, { let mut cargo_subcommand = "check"; - let mut unstable_options = false; let mut args = vec![]; for arg in old_args.by_ref() { @@ -80,18 +79,12 @@ impl ClippyCmd { continue; }, "--" => break, - // Cover -Zunstable-options and -Z unstable-options - s if s.ends_with("unstable-options") => unstable_options = true, _ => {}, } args.push(arg); } - if cargo_subcommand == "fix" && !unstable_options { - panic!("Usage of `--fix` requires `-Z unstable-options`"); - } - let mut clippy_args: Vec<String> = old_args.collect(); if cargo_subcommand == "fix" && !clippy_args.iter().any(|arg| arg == "--no-deps") { clippy_args.push("--no-deps".into()); @@ -176,34 +169,23 @@ mod tests { use super::ClippyCmd; #[test] - #[should_panic] - fn fix_without_unstable() { + fn fix() { let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string); - ClippyCmd::new(args); - } - - #[test] - fn fix_unstable() { - let args = "cargo clippy --fix -Zunstable-options" - .split_whitespace() - .map(ToString::to_string); let cmd = ClippyCmd::new(args); assert_eq!("fix", cmd.cargo_subcommand); - assert!(cmd.args.iter().any(|arg| arg.ends_with("unstable-options"))); + assert!(!cmd.args.iter().any(|arg| arg.ends_with("unstable-options"))); } #[test] fn fix_implies_no_deps() { - let args = "cargo clippy --fix -Zunstable-options" - .split_whitespace() - .map(ToString::to_string); + let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string); let cmd = ClippyCmd::new(args); assert!(cmd.clippy_args.iter().any(|arg| arg == "--no-deps")); } #[test] fn no_deps_not_duplicated_with_fix() { - let args = "cargo clippy --fix -Zunstable-options -- --no-deps" + let args = "cargo clippy --fix -- --no-deps" .split_whitespace() .map(ToString::to_string); let cmd = ClippyCmd::new(args); diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 7d266a36bb6..caa19e39ccd 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -48,7 +48,24 @@ fn third_party_crates() -> String { && name.rsplit('.').next().map(|ext| ext.eq_ignore_ascii_case("rlib")) == Some(true) { if let Some(old) = crates.insert(dep, path.clone()) { - panic!("Found multiple rlibs for crate `{}`: `{:?}` and `{:?}", dep, old, path); + // Check which action should be done in order to remove compiled deps. + // If pre-installed version of compiler is used, `cargo clean` will do. + // Otherwise (for bootstrapped compiler), the dependencies directory + // must be removed manually. + let suggested_action = if std::env::var_os("RUSTC_BOOTSTRAP").is_some() { + "remove the stageN-tools directory" + } else { + "run `cargo clean`" + }; + + panic!( + "\n---------------------------------------------------\n\n \ + Found multiple rlibs for crate `{}`: `{:?}` and `{:?}`.\n \ + Probably, you need to {} before running tests again.\n \ + \nFor details on that error see https://github.com/rust-lang/rust-clippy/issues/7343 \ + \n---------------------------------------------------\n", + dep, old, path, suggested_action + ); } break; } diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml new file mode 100644 index 00000000000..05ba822874d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml @@ -0,0 +1,10 @@ +enforced-import-renames = [ + { path = "std::option::Option", rename = "Maybe" }, + { path = "std::process::Child", rename = "Kid" }, + { path = "std::process::exit", rename = "goodbye" }, + { path = "std::collections::BTreeMap", rename = "Map" }, + { path = "std::clone", rename = "foo" }, + { path = "std::thread::sleep", rename = "thread_sleep" }, + { path = "std::any::type_name", rename = "ident" }, + { path = "std::sync::Mutex", rename = "StdMutie" } +] diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs new file mode 100644 index 00000000000..f60058c8628 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs @@ -0,0 +1,16 @@ +#![warn(clippy::missing_enforced_import_renames)] + +use std::alloc as colla; +use std::option::Option as Maybe; +use std::process::{exit as wrong_exit, Child as Kid}; +use std::thread::sleep; +#[rustfmt::skip] +use std::{ + any::{type_name, Any}, + clone, + sync :: Mutex, +}; + +fn main() { + use std::collections::BTreeMap as OopsWrongRename; +} diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr new file mode 100644 index 00000000000..45de8fdffef --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr @@ -0,0 +1,40 @@ +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:5:20 + | +LL | use std::process::{exit as wrong_exit, Child as Kid}; + | ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye` + | + = note: `-D clippy::missing-enforced-import-renames` implied by `-D warnings` + +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:6:1 + | +LL | use std::thread::sleep; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::thread::sleep as thread_sleep` + +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:9:11 + | +LL | any::{type_name, Any}, + | ^^^^^^^^^ help: try: `type_name as ident` + +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:10:5 + | +LL | clone, + | ^^^^^ help: try: `clone as foo` + +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:11:5 + | +LL | sync :: Mutex, + | ^^^^^^^^^^^^^ help: try: `sync :: Mutex as StdMutie` + +error: this import should be renamed + --> $DIR/conf_missing_enforced_import_rename.rs:15:5 + | +LL | use std::collections::BTreeMap as OopsWrongRename; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::collections::BTreeMap as Map` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml new file mode 100644 index 00000000000..bced8948a02 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml @@ -0,0 +1,6 @@ +standard-macro-braces = [ + { name = "quote", brace = "{" }, + { name = "quote::quote", brace = "{" }, + { name = "eprint", brace = "[" }, + { name = "type_pos", brace = "[" }, +] diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs new file mode 100644 index 00000000000..4ae6864cbb0 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs @@ -0,0 +1,44 @@ +// #![warn(clippy::nonstandard_macro_braces)] + +extern crate quote; + +use quote::quote; + +#[rustfmt::skip] +macro_rules! test { + () => { + vec!{0, 0, 0} + }; +} + +#[rustfmt::skip] +macro_rules! test2 { + ($($arg:tt)*) => { + format_args!($($arg)*) + }; +} + +macro_rules! type_pos { + ($what:ty) => { + Vec<$what> + }; +} + +#[rustfmt::skip] +fn main() { + let _ = vec! {1, 2, 3}; + let _ = format!["ugh {} stop being such a good compiler", "hello"]; + let _ = quote!(let x = 1;); + let _ = quote::quote!(match match match); + let _ = test!(); + let _ = vec![1,2,3]; + + let _ = quote::quote! {true || false}; + let _ = vec! [0 ,0 ,0]; + let _ = format!("fds{}fds", 10); + let _ = test2!["{}{}{}", 1, 2, 3]; + + let _: type_pos!(usize) = vec![]; + + eprint!("test if user config overrides defaults"); +} diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr new file mode 100644 index 00000000000..7bcd1829524 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr @@ -0,0 +1,94 @@ +error: use of irregular braces for `vec!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:29:13 + | +LL | let _ = vec! {1, 2, 3}; + | ^^^^^^^^^^^^^^ + | + = note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings` +help: consider writing `vec![1, 2, 3]` + --> $DIR/conf_nonstandard_macro_braces.rs:29:13 + | +LL | let _ = vec! {1, 2, 3}; + | ^^^^^^^^^^^^^^ + +error: use of irregular braces for `format!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:30:13 + | +LL | let _ = format!["ugh {} stop being such a good compiler", "hello"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider writing `format!("ugh () stop being such a good compiler", "hello")` + --> $DIR/conf_nonstandard_macro_braces.rs:30:13 + | +LL | let _ = format!["ugh {} stop being such a good compiler", "hello"]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of irregular braces for `quote!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:31:13 + | +LL | let _ = quote!(let x = 1;); + | ^^^^^^^^^^^^^^^^^^ + | +help: consider writing `quote! {let x = 1;}` + --> $DIR/conf_nonstandard_macro_braces.rs:31:13 + | +LL | let _ = quote!(let x = 1;); + | ^^^^^^^^^^^^^^^^^^ + +error: use of irregular braces for `quote::quote!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:32:13 + | +LL | let _ = quote::quote!(match match match); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider writing `quote::quote! {match match match}` + --> $DIR/conf_nonstandard_macro_braces.rs:32:13 + | +LL | let _ = quote::quote!(match match match); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of irregular braces for `vec!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:10:9 + | +LL | vec!{0, 0, 0} + | ^^^^^^^^^^^^^ +... +LL | let _ = test!(); + | ------- in this macro invocation + | +help: consider writing `vec![0, 0, 0]` + --> $DIR/conf_nonstandard_macro_braces.rs:10:9 + | +LL | vec!{0, 0, 0} + | ^^^^^^^^^^^^^ +... +LL | let _ = test!(); + | ------- in this macro invocation + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: use of irregular braces for `type_pos!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:41:12 + | +LL | let _: type_pos!(usize) = vec![]; + | ^^^^^^^^^^^^^^^^ + | +help: consider writing `type_pos![usize]` + --> $DIR/conf_nonstandard_macro_braces.rs:41:12 + | +LL | let _: type_pos!(usize) = vec![]; + | ^^^^^^^^^^^^^^^^ + +error: use of irregular braces for `eprint!` macro + --> $DIR/conf_nonstandard_macro_braces.rs:43:5 + | +LL | eprint!("test if user config overrides defaults"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider writing `eprint!["test if user config overrides defaults"];` + --> $DIR/conf_nonstandard_macro_braces.rs:43:5 + | +LL | eprint!("test if user config overrides defaults"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_method/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_method/clippy.toml index c0df3b6e8af..a3245da6825 100644 --- a/src/tools/clippy/tests/ui-toml/toml_disallowed_method/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_method/clippy.toml @@ -1 +1,5 @@ -disallowed-methods = ["core::iter::traits::iterator::Iterator::sum", "regex::re_unicode::Regex::is_match", "regex::re_unicode::Regex::new"] +disallowed-methods = [ + "std::iter::Iterator::sum", + "regex::Regex::is_match", + "regex::Regex::new" +] diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml new file mode 100644 index 00000000000..2eff854c22c --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml @@ -0,0 +1,9 @@ +disallowed-types = [ + "std::collections::HashMap", + "std::sync::atomic::AtomicU32", + "syn::TypePath", + "proc_macro2::Ident", + "std::thread::Thread", + "std::time::Instant", + "std::io::Read", +] diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs new file mode 100644 index 00000000000..567afb5aec1 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs @@ -0,0 +1,35 @@ +#![warn(clippy::disallowed_type)] + +extern crate quote; +extern crate syn; + +use std::sync as foo; +use std::sync::atomic::AtomicU32; +use std::time::Instant as Sneaky; + +struct HashMap; + +fn bad_return_type() -> fn() -> Sneaky { + todo!() +} + +fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) { + todo!() +} + +fn trait_obj(_: &dyn std::io::Read) { + todo!() +} + +static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut()); + +#[allow(clippy::diverging_sub_expression)] +fn main() { + let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); + let _ = Sneaky::now(); + let _ = foo::atomic::AtomicU32::new(0); + static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); + let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default(); + let _ = syn::Ident::new("", todo!()); + let _ = HashMap; +} diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr new file mode 100644 index 00000000000..4e6fd91fba1 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr @@ -0,0 +1,88 @@ +error: `std::sync::atomic::AtomicU32` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:7:1 + | +LL | use std::sync::atomic::AtomicU32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::disallowed-type` implied by `-D warnings` + +error: `std::time::Instant` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:8:1 + | +LL | use std::time::Instant as Sneaky; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::time::Instant` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:12:33 + | +LL | fn bad_return_type() -> fn() -> Sneaky { + | ^^^^^^ + +error: `std::time::Instant` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:16:28 + | +LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) { + | ^^^^^^ + +error: `std::sync::atomic::AtomicU32` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:16:39 + | +LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::io::Read` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:20:22 + | +LL | fn trait_obj(_: &dyn std::io::Read) { + | ^^^^^^^^^^^^^ + +error: `std::collections::HashMap` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:28:48 + | +LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::collections::HashMap` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:28:12 + | +LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::time::Instant` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:29:13 + | +LL | let _ = Sneaky::now(); + | ^^^^^^ + +error: `std::sync::atomic::AtomicU32` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:30:13 + | +LL | let _ = foo::atomic::AtomicU32::new(0); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::sync::atomic::AtomicU32` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:31:17 + | +LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `std::sync::atomic::AtomicU32` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:31:48 + | +LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `syn::TypePath` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:32:43 + | +LL | let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default(); + | ^^^^^^^^^^^^^ + +error: `proc_macro2::Ident` is not allowed according to config + --> $DIR/conf_disallowed_type.rs:33:13 + | +LL | let _ = syn::Ident::new("", todo!()); + | ^^^^^^^^^^ + +error: aborting due to 14 previous errors + 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 a7be00426c4..e0029ebeb27 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 `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: 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`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/src/tools/clippy/tests/ui/append_instead_of_extend.fixed b/src/tools/clippy/tests/ui/append_instead_of_extend.fixed new file mode 100644 index 00000000000..283358333cd --- /dev/null +++ b/src/tools/clippy/tests/ui/append_instead_of_extend.fixed @@ -0,0 +1,55 @@ +// run-rustfix +#![warn(clippy::append_instead_of_extend)] +use std::collections::BinaryHeap; +fn main() { + //gets linted + let mut vec1 = vec![0u8; 1024]; + let mut vec2: std::vec::Vec<u8> = Vec::new(); + + vec2.append(&mut vec1); + + let mut vec3 = vec![0u8; 1024]; + let mut vec4: std::vec::Vec<u8> = Vec::new(); + + vec4.append(&mut vec3); + + let mut vec11: std::vec::Vec<u8> = Vec::new(); + + vec11.append(&mut return_vector()); + + //won't get linted it dosen't move the entire content of a vec into another + let mut test1 = vec![0u8, 10]; + let mut test2: std::vec::Vec<u8> = Vec::new(); + + test2.extend(test1.drain(4..10)); + + let mut vec3 = vec![0u8; 104]; + let mut vec7: std::vec::Vec<u8> = Vec::new(); + + vec3.append(&mut vec7); + + let mut vec5 = vec![0u8; 1024]; + let mut vec6: std::vec::Vec<u8> = Vec::new(); + + vec5.extend(vec6.drain(..4)); + + let mut vec9: std::vec::Vec<u8> = Vec::new(); + + return_vector().append(&mut vec9); + + //won't get linted because it is not a vec + + let mut heap = BinaryHeap::from(vec![1, 3]); + let mut heap2 = BinaryHeap::from(vec![]); + heap2.extend(heap.drain()) +} + +fn return_vector() -> Vec<u8> { + let mut new_vector = vec![]; + + for i in 1..10 { + new_vector.push(i) + } + + new_vector +} diff --git a/src/tools/clippy/tests/ui/append_instead_of_extend.rs b/src/tools/clippy/tests/ui/append_instead_of_extend.rs new file mode 100644 index 00000000000..abde5cdac5c --- /dev/null +++ b/src/tools/clippy/tests/ui/append_instead_of_extend.rs @@ -0,0 +1,55 @@ +// run-rustfix +#![warn(clippy::append_instead_of_extend)] +use std::collections::BinaryHeap; +fn main() { + //gets linted + let mut vec1 = vec![0u8; 1024]; + let mut vec2: std::vec::Vec<u8> = Vec::new(); + + vec2.extend(vec1.drain(..)); + + let mut vec3 = vec![0u8; 1024]; + let mut vec4: std::vec::Vec<u8> = Vec::new(); + + vec4.extend(vec3.drain(..)); + + let mut vec11: std::vec::Vec<u8> = Vec::new(); + + vec11.extend(return_vector().drain(..)); + + //won't get linted it dosen't move the entire content of a vec into another + let mut test1 = vec![0u8, 10]; + let mut test2: std::vec::Vec<u8> = Vec::new(); + + test2.extend(test1.drain(4..10)); + + let mut vec3 = vec![0u8; 104]; + let mut vec7: std::vec::Vec<u8> = Vec::new(); + + vec3.append(&mut vec7); + + let mut vec5 = vec![0u8; 1024]; + let mut vec6: std::vec::Vec<u8> = Vec::new(); + + vec5.extend(vec6.drain(..4)); + + let mut vec9: std::vec::Vec<u8> = Vec::new(); + + return_vector().append(&mut vec9); + + //won't get linted because it is not a vec + + let mut heap = BinaryHeap::from(vec![1, 3]); + let mut heap2 = BinaryHeap::from(vec![]); + heap2.extend(heap.drain()) +} + +fn return_vector() -> Vec<u8> { + let mut new_vector = vec![]; + + for i in 1..10 { + new_vector.push(i) + } + + new_vector +} diff --git a/src/tools/clippy/tests/ui/append_instead_of_extend.stderr b/src/tools/clippy/tests/ui/append_instead_of_extend.stderr new file mode 100644 index 00000000000..9d309d981de --- /dev/null +++ b/src/tools/clippy/tests/ui/append_instead_of_extend.stderr @@ -0,0 +1,22 @@ +error: use of `extend` instead of `append` for adding the full range of a second vector + --> $DIR/append_instead_of_extend.rs:9:5 + | +LL | vec2.extend(vec1.drain(..)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec2.append(&mut vec1)` + | + = note: `-D clippy::append-instead-of-extend` implied by `-D warnings` + +error: use of `extend` instead of `append` for adding the full range of a second vector + --> $DIR/append_instead_of_extend.rs:14:5 + | +LL | vec4.extend(vec3.drain(..)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec4.append(&mut vec3)` + +error: use of `extend` instead of `append` for adding the full range of a second vector + --> $DIR/append_instead_of_extend.rs:18:5 + | +LL | vec11.extend(return_vector().drain(..)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec11.append(&mut return_vector())` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.rs b/src/tools/clippy/tests/ui/assertions_on_constants.rs index e989de65404..6617ca183a8 100644 --- a/src/tools/clippy/tests/ui/assertions_on_constants.rs +++ b/src/tools/clippy/tests/ui/assertions_on_constants.rs @@ -28,4 +28,7 @@ fn main() { debug_assert!(false); // #3948 assert_const!(3); assert_const!(-1); + + // Don't lint on this: + assert!(cfg!(feature = "hey") || cfg!(not(feature = "asdf"))); } diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs index d4470d3f407..170955e726c 100644 --- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs +++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs @@ -106,3 +106,10 @@ macro_rules! field_reassign_with_default { } }; } + +#[macro_export] +macro_rules! default_numeric_fallback { + () => { + let x = 22; + }; +} diff --git a/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs b/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs new file mode 100644 index 00000000000..420232f9f8d --- /dev/null +++ b/src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs @@ -0,0 +1,8 @@ +// Stripped down version of the ErrorKind enum of std +#[non_exhaustive] +pub enum ErrorKind { + NotFound, + PermissionDenied, + #[doc(hidden)] + Uncategorized, +} diff --git a/src/tools/clippy/tests/ui/blacklisted_name.rs b/src/tools/clippy/tests/ui/blacklisted_name.rs index cb15bdd2f1b..57d7139fef5 100644 --- a/src/tools/clippy/tests/ui/blacklisted_name.rs +++ b/src/tools/clippy/tests/ui/blacklisted_name.rs @@ -43,3 +43,15 @@ fn issue_1647_ref_mut() { let ref mut baz = 0; if let Some(ref mut quux) = Some(42) {} } + +mod tests { + fn issue_7305() { + // `blackisted_name` lint should not be triggered inside of the test code. + let foo = 0; + + // Check that even in nested functions warning is still not triggere. + fn nested() { + let foo = 0; + } + } +} diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.rs b/src/tools/clippy/tests/ui/default_numeric_fallback.rs index 43468872db0..c0625fd1b75 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback.rs +++ b/src/tools/clippy/tests/ui/default_numeric_fallback.rs @@ -1,3 +1,5 @@ +// aux-build:macro_rules.rs + #![warn(clippy::default_numeric_fallback)] #![allow(unused)] #![allow(clippy::never_loop)] @@ -5,6 +7,9 @@ #![allow(clippy::unnecessary_operation)] #![allow(clippy::branches_sharing_code)] +#[macro_use] +extern crate macro_rules; + mod basic_expr { fn test() { // Should lint unsuffixed literals typed `i32`. @@ -133,4 +138,22 @@ mod method_calls { } } +mod in_macro { + macro_rules! internal_macro { + () => { + let x = 22; + }; + } + + // Should lint in internal macro. + fn internal() { + internal_macro!(); + } + + // Should NOT lint in external macro. + fn external() { + default_numeric_fallback!(); + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback.stderr index d1c4c8203dd..5862cd936ac 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback.stderr +++ b/src/tools/clippy/tests/ui/default_numeric_fallback.stderr @@ -1,5 +1,5 @@ error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:11:17 + --> $DIR/default_numeric_fallback.rs:16:17 | LL | let x = 22; | ^^ help: consider adding suffix: `22_i32` @@ -7,142 +7,153 @@ LL | let x = 22; = note: `-D clippy::default-numeric-fallback` implied by `-D warnings` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:12:18 + --> $DIR/default_numeric_fallback.rs:17:18 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:12:21 + --> $DIR/default_numeric_fallback.rs:17:21 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:12:24 + --> $DIR/default_numeric_fallback.rs:17:24 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:13:28 + --> $DIR/default_numeric_fallback.rs:18:28 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:13:31 + --> $DIR/default_numeric_fallback.rs:18:31 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:13:44 + --> $DIR/default_numeric_fallback.rs:18:44 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:13:47 + --> $DIR/default_numeric_fallback.rs:18:47 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `4_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:14:23 + --> $DIR/default_numeric_fallback.rs:19:23 | LL | let x = match 1 { | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:15:13 + --> $DIR/default_numeric_fallback.rs:20:13 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:15:18 + --> $DIR/default_numeric_fallback.rs:20:18 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:16:18 + --> $DIR/default_numeric_fallback.rs:21:18 | LL | _ => 2, | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:20:17 + --> $DIR/default_numeric_fallback.rs:25:17 | LL | let x = 0.12; | ^^^^ help: consider adding suffix: `0.12_f64` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:38:21 + --> $DIR/default_numeric_fallback.rs:43:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:46:21 + --> $DIR/default_numeric_fallback.rs:51:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:52:21 + --> $DIR/default_numeric_fallback.rs:57:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:64:9 + --> $DIR/default_numeric_fallback.rs:69:9 | LL | 1 | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:70:27 + --> $DIR/default_numeric_fallback.rs:75:27 | LL | let f = || -> _ { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:74:29 + --> $DIR/default_numeric_fallback.rs:79:29 | LL | let f = || -> i32 { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:88:21 + --> $DIR/default_numeric_fallback.rs:93:21 | LL | generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:91:32 + --> $DIR/default_numeric_fallback.rs:96:32 | LL | let x: _ = generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:109:28 + --> $DIR/default_numeric_fallback.rs:114:28 | LL | GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:112:36 + --> $DIR/default_numeric_fallback.rs:117:36 | LL | let _ = GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> $DIR/default_numeric_fallback.rs:132:23 + --> $DIR/default_numeric_fallback.rs:137:23 | LL | s.generic_arg(1); | ^ help: consider adding suffix: `1_i32` -error: aborting due to 24 previous errors +error: default numeric fallback might occur + --> $DIR/default_numeric_fallback.rs:144:21 + | +LL | let x = 22; + | ^^ help: consider adding suffix: `22_i32` +... +LL | internal_macro!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 25 previous errors diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index 03c9f438891..0af6b500115 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -84,13 +84,13 @@ error: lint `clippy::filter_map` has been removed: this lint has been replaced b LL | #[warn(clippy::filter_map)] | ^^^^^^^^^^^^^^^^^^ -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 +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 +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)] diff --git a/src/tools/clippy/tests/ui/disallowed_script_idents.rs b/src/tools/clippy/tests/ui/disallowed_script_idents.rs new file mode 100644 index 00000000000..cfdda35971f --- /dev/null +++ b/src/tools/clippy/tests/ui/disallowed_script_idents.rs @@ -0,0 +1,10 @@ +#![deny(clippy::disallowed_script_idents)] +#![allow(dead_code)] + +fn main() { + let counter = 10; // OK, latin is allowed. + let zähler = 10; // OK, it's still latin. + + let счётчик = 10; // Cyrillic is not allowed by default. + let カウンタ = 10; // Same for japanese. +} diff --git a/src/tools/clippy/tests/ui/disallowed_script_idents.stderr b/src/tools/clippy/tests/ui/disallowed_script_idents.stderr new file mode 100644 index 00000000000..cc84dc1d43c --- /dev/null +++ b/src/tools/clippy/tests/ui/disallowed_script_idents.stderr @@ -0,0 +1,20 @@ +error: identifier `счётчик` has a Unicode script that is not allowed by configuration: Cyrillic + --> $DIR/disallowed_script_idents.rs:8:9 + | +LL | let счётчик = 10; // Cyrillic is not allowed by default. + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/disallowed_script_idents.rs:1:9 + | +LL | #![deny(clippy::disallowed_script_idents)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: identifier `カウンタ` has a Unicode script that is not allowed by configuration: Katakana + --> $DIR/disallowed_script_idents.rs:9:9 + | +LL | let カウンタ = 10; // Same for japanese. + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/doc.rs b/src/tools/clippy/tests/ui/doc/doc.rs index c946a047f1b..8afef6b23d4 100644 --- a/src/tools/clippy/tests/ui/doc.rs +++ b/src/tools/clippy/tests/ui/doc/doc.rs @@ -64,7 +64,7 @@ fn test_units() { /// WebGL /// TensorFlow /// TrueType -/// iOS macOS +/// iOS macOS FreeBSD /// TeX LaTeX BibTeX BibLaTeX /// MinGW /// CamelCase (see also #2395) diff --git a/src/tools/clippy/tests/ui/doc.stderr b/src/tools/clippy/tests/ui/doc/doc.stderr index 7eab8a85f09..7eab8a85f09 100644 --- a/src/tools/clippy/tests/ui/doc.stderr +++ b/src/tools/clippy/tests/ui/doc/doc.stderr diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs new file mode 100644 index 00000000000..78e87bc6906 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs @@ -0,0 +1,36 @@ +//! This file tests for the `DOC_MARKDOWN` lint, specifically cases +//! where ticks are unbalanced (see issue #6753). + +#![allow(dead_code)] +#![warn(clippy::doc_markdown)] + +/// This is a doc comment with `unbalanced_tick marks and several words that +/// should be `encompassed_by` tick marks because they `contain_underscores`. +/// Because of the initial `unbalanced_tick` pair, the error message is +/// very `confusing_and_misleading`. +fn main() {} + +/// This paragraph has `unbalanced_tick marks and should stop_linting. +/// +/// This paragraph is fine and should_be linted normally. +/// +/// Double unbalanced backtick from ``here to here` should lint. +/// +/// Double balanced back ticks ``start end`` is fine. +fn multiple_paragraphs() {} + +/// ``` +/// // Unbalanced tick mark in code block shouldn't warn: +/// ` +/// ``` +fn in_code_block() {} + +/// # `Fine` +/// +/// ## not_fine +/// +/// ### `unbalanced +/// +/// - This `item has unbalanced tick marks +/// - This item needs backticks_here +fn other_markdown() {} diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr new file mode 100644 index 00000000000..45ca34e2a8c --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr @@ -0,0 +1,64 @@ +error: backticks are unbalanced + --> $DIR/unbalanced_ticks.rs:7:1 + | +LL | / /// This is a doc comment with `unbalanced_tick marks and several words that +LL | | /// should be `encompassed_by` tick marks because they `contain_underscores`. +LL | | /// Because of the initial `unbalanced_tick` pair, the error message is +LL | | /// very `confusing_and_misleading`. + | |____________________________________^ + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` + = help: a backtick may be missing a pair + +error: backticks are unbalanced + --> $DIR/unbalanced_ticks.rs:13:1 + | +LL | /// This paragraph has `unbalanced_tick marks and should stop_linting. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: a backtick may be missing a pair + +error: you should put `should_be` between ticks in the documentation + --> $DIR/unbalanced_ticks.rs:15:32 + | +LL | /// This paragraph is fine and should_be linted normally. + | ^^^^^^^^^ + +error: backticks are unbalanced + --> $DIR/unbalanced_ticks.rs:17:1 + | +LL | /// Double unbalanced backtick from ``here to here` should lint. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: a backtick may be missing a pair + +error: you should put `not_fine` between ticks in the documentation + --> $DIR/unbalanced_ticks.rs:30:8 + | +LL | /// ## not_fine + | ^^^^^^^^ + +error: backticks are unbalanced + --> $DIR/unbalanced_ticks.rs:32:1 + | +LL | /// ### `unbalanced + | ^^^^^^^^^^^^^^^^^^^ + | + = help: a backtick may be missing a pair + +error: backticks are unbalanced + --> $DIR/unbalanced_ticks.rs:34:1 + | +LL | /// - This `item has unbalanced tick marks + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: a backtick may be missing a pair + +error: you should put `backticks_here` between ticks in the documentation + --> $DIR/unbalanced_ticks.rs:35:23 + | +LL | /// - This item needs backticks_here + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs index 1368c5d7984..787053fb000 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs @@ -29,6 +29,21 @@ struct C { i: Vec<i32>, j: i64, } + +#[derive(Default)] +struct D { + a: Option<i32>, + b: Option<i32>, +} + +macro_rules! m { + ($key:ident: $value:tt) => {{ + let mut data = $crate::D::default(); + data.$key = Some($value); + data + }}; +} + /// Implements .next() that returns a different number each time. struct SideEffect(i32); @@ -143,6 +158,11 @@ fn main() { let mut a: WrapperMulti<i32, i64> = Default::default(); a.i = 42; + + // Don't lint in macros + m! { + a: 42 + }; } mod m { diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr index dd7c0360bb1..b56db08ec8a 100644 --- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr +++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr @@ -1,108 +1,108 @@ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:48:5 + --> $DIR/field_reassign_with_default.rs:63:5 | LL | a.i = 42; | ^^^^^^^^^ | = note: `-D clippy::field-reassign-with-default` implied by `-D warnings` note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:47:5 + --> $DIR/field_reassign_with_default.rs:62:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:88:5 + --> $DIR/field_reassign_with_default.rs:103:5 | LL | a.j = 43; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:87:5 + --> $DIR/field_reassign_with_default.rs:102:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:93:5 + --> $DIR/field_reassign_with_default.rs:108:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:92:5 + --> $DIR/field_reassign_with_default.rs:107:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:99:5 + --> $DIR/field_reassign_with_default.rs:114:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:98:5 + --> $DIR/field_reassign_with_default.rs:113:5 | LL | let mut a = A::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:109:5 + --> $DIR/field_reassign_with_default.rs:124:5 | LL | a.i = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:108:5 + --> $DIR/field_reassign_with_default.rs:123:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:113:5 + --> $DIR/field_reassign_with_default.rs:128:5 | LL | a.i = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:112:5 + --> $DIR/field_reassign_with_default.rs:127:5 | LL | let mut a: A = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:135:5 + --> $DIR/field_reassign_with_default.rs:150:5 | LL | a.i = vec![1]; | ^^^^^^^^^^^^^^ | note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:134:5 + --> $DIR/field_reassign_with_default.rs:149:5 | LL | let mut a: C = C::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:142:5 + --> $DIR/field_reassign_with_default.rs:157:5 | LL | a.i = true; | ^^^^^^^^^^^ | note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:141:5 + --> $DIR/field_reassign_with_default.rs:156:5 | LL | let mut a: Wrapper<bool> = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: field assignment outside of initializer for an instance created with Default::default() - --> $DIR/field_reassign_with_default.rs:145:5 + --> $DIR/field_reassign_with_default.rs:160:5 | LL | a.i = 42; | ^^^^^^^^^ | note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments - --> $DIR/field_reassign_with_default.rs:144:5 + --> $DIR/field_reassign_with_default.rs:159:5 | LL | let mut a: WrapperMulti<i32, i64> = Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/filter_map_identity.fixed b/src/tools/clippy/tests/ui/filter_map_identity.fixed index 23ce28d8e9b..a5860aa49b3 100644 --- a/src/tools/clippy/tests/ui/filter_map_identity.fixed +++ b/src/tools/clippy/tests/ui/filter_map_identity.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused_imports)] +#![allow(unused_imports, clippy::needless_return)] #![warn(clippy::filter_map_identity)] fn main() { @@ -13,4 +13,7 @@ fn main() { use std::convert::identity; let iterator = vec![Some(1), None, Some(2)].into_iter(); let _ = iterator.flatten(); + + let iterator = vec![Some(1), None, Some(2)].into_iter(); + let _ = iterator.flatten(); } diff --git a/src/tools/clippy/tests/ui/filter_map_identity.rs b/src/tools/clippy/tests/ui/filter_map_identity.rs index e698df13eea..7e998b9cdf7 100644 --- a/src/tools/clippy/tests/ui/filter_map_identity.rs +++ b/src/tools/clippy/tests/ui/filter_map_identity.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused_imports)] +#![allow(unused_imports, clippy::needless_return)] #![warn(clippy::filter_map_identity)] fn main() { @@ -13,4 +13,7 @@ fn main() { use std::convert::identity; let iterator = vec![Some(1), None, Some(2)].into_iter(); let _ = iterator.filter_map(identity); + + let iterator = vec![Some(1), None, Some(2)].into_iter(); + let _ = iterator.filter_map(|x| return x); } diff --git a/src/tools/clippy/tests/ui/filter_map_identity.stderr b/src/tools/clippy/tests/ui/filter_map_identity.stderr index 596a6320608..43c9fdca4fb 100644 --- a/src/tools/clippy/tests/ui/filter_map_identity.stderr +++ b/src/tools/clippy/tests/ui/filter_map_identity.stderr @@ -1,4 +1,4 @@ -error: called `filter_map(|x| x)` on an `Iterator` +error: use of `filter_map` with an identity function --> $DIR/filter_map_identity.rs:8:22 | LL | let _ = iterator.filter_map(|x| x); @@ -6,17 +6,23 @@ LL | let _ = iterator.filter_map(|x| x); | = note: `-D clippy::filter-map-identity` implied by `-D warnings` -error: called `filter_map(std::convert::identity)` on an `Iterator` +error: use of `filter_map` with an identity function --> $DIR/filter_map_identity.rs:11:22 | LL | let _ = iterator.filter_map(std::convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: called `filter_map(std::convert::identity)` on an `Iterator` +error: use of `filter_map` with an identity function --> $DIR/filter_map_identity.rs:15:22 | LL | let _ = iterator.filter_map(identity); | ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: aborting due to 3 previous errors +error: use of `filter_map` with an identity function + --> $DIR/filter_map_identity.rs:18:22 + | +LL | let _ = iterator.filter_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/flat_map_identity.fixed b/src/tools/clippy/tests/ui/flat_map_identity.fixed index dfe3bd47e13..1f4b880ef5b 100644 --- a/src/tools/clippy/tests/ui/flat_map_identity.fixed +++ b/src/tools/clippy/tests/ui/flat_map_identity.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused_imports)] +#![allow(unused_imports, clippy::needless_return)] #![warn(clippy::flat_map_identity)] use std::convert; @@ -11,4 +11,7 @@ fn main() { let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flatten(); + + let iterator = [[0, 1], [2, 3], [4, 5]].iter(); + let _ = iterator.flatten(); } diff --git a/src/tools/clippy/tests/ui/flat_map_identity.rs b/src/tools/clippy/tests/ui/flat_map_identity.rs index 393b9569255..de14a06d4e6 100644 --- a/src/tools/clippy/tests/ui/flat_map_identity.rs +++ b/src/tools/clippy/tests/ui/flat_map_identity.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused_imports)] +#![allow(unused_imports, clippy::needless_return)] #![warn(clippy::flat_map_identity)] use std::convert; @@ -11,4 +11,7 @@ fn main() { let iterator = [[0, 1], [2, 3], [4, 5]].iter(); let _ = iterator.flat_map(convert::identity); + + let iterator = [[0, 1], [2, 3], [4, 5]].iter(); + let _ = iterator.flat_map(|x| return x); } diff --git a/src/tools/clippy/tests/ui/flat_map_identity.stderr b/src/tools/clippy/tests/ui/flat_map_identity.stderr index e4686ae5a54..e776c9fdf51 100644 --- a/src/tools/clippy/tests/ui/flat_map_identity.stderr +++ b/src/tools/clippy/tests/ui/flat_map_identity.stderr @@ -1,4 +1,4 @@ -error: called `flat_map(|x| x)` on an `Iterator` +error: use of `flat_map` with an identity function --> $DIR/flat_map_identity.rs:10:22 | LL | let _ = iterator.flat_map(|x| x); @@ -6,11 +6,17 @@ LL | let _ = iterator.flat_map(|x| x); | = note: `-D clippy::flat-map-identity` implied by `-D warnings` -error: called `flat_map(std::convert::identity)` on an `Iterator` +error: use of `flat_map` with an identity function --> $DIR/flat_map_identity.rs:13:22 | LL | let _ = iterator.flat_map(convert::identity); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: aborting due to 2 previous errors +error: use of `flat_map` with an identity function + --> $DIR/flat_map_identity.rs:16:22 + | +LL | let _ = iterator.flat_map(|x| return x); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/match_same_arms.stderr b/src/tools/clippy/tests/ui/match_same_arms.stderr index 0549886a1e8..e48451acfe8 100644 --- a/src/tools/clippy/tests/ui/match_same_arms.stderr +++ b/src/tools/clippy/tests/ui/match_same_arms.stderr @@ -32,6 +32,7 @@ help: consider refactoring into `(1, .., 3) | (.., 3)` | LL | (1, .., 3) => 42, | ^^^^^^^^^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:24:15 @@ -49,6 +50,7 @@ help: consider refactoring into `42 | 51` | LL | 42 => 1, | ^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:26:15 @@ -66,6 +68,7 @@ help: consider refactoring into `41 | 52` | LL | 41 => 2, | ^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:32:14 @@ -83,6 +86,7 @@ help: consider refactoring into `1 | 2` | LL | 1 => 2, | ^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:33:14 @@ -100,6 +104,7 @@ help: consider refactoring into `1 | 3` | LL | 1 => 2, | ^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:33:14 @@ -117,6 +122,7 @@ help: consider refactoring into `2 | 3` | LL | 2 => 2, //~ ERROR 2nd matched arms have same body | ^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms.rs:50:55 @@ -134,6 +140,7 @@ help: consider refactoring into `CommandInfo::BuiltIn { name, .. } | CommandInfo | LL | CommandInfo::BuiltIn { name, .. } => name.to_string(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ...or consider changing the match arm bodies error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr index 430021a0f7f..e1ed12f9370 100644 --- a/src/tools/clippy/tests/ui/match_same_arms2.stderr +++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr @@ -53,6 +53,7 @@ help: consider refactoring into `42 | 51` | LL | 42 => foo(), | ^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms2.rs:40:17 @@ -70,6 +71,7 @@ help: consider refactoring into `Some(_) | None` | LL | Some(_) => 24, | ^^^^^^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms2.rs:62:28 @@ -87,6 +89,7 @@ help: consider refactoring into `(Some(a), None) | (None, Some(a))` | LL | (Some(a), None) => bar(a), | ^^^^^^^^^^^^^^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms2.rs:68:26 @@ -104,6 +107,7 @@ help: consider refactoring into `(Some(a), ..) | (.., Some(a))` | LL | (Some(a), ..) => bar(a), | ^^^^^^^^^^^^^ + = help: ...or consider changing the match arm bodies error: this `match` has identical arm bodies --> $DIR/match_same_arms2.rs:102:29 @@ -121,6 +125,7 @@ help: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^ + = help: ...or consider changing the match arm bodies = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` has identical arm bodies @@ -139,6 +144,7 @@ help: consider refactoring into `Ok(3) | Ok(_)` | LL | Ok(3) => println!("ok"), | ^^^^^ + = help: ...or consider changing the match arm bodies = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` has identical arm bodies @@ -163,6 +169,7 @@ help: consider refactoring into `0 | 1` | LL | 0 => { | ^ + = help: ...or consider changing the match arm bodies error: match expression looks like `matches!` macro --> $DIR/match_same_arms2.rs:162:16 diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed index 31b743f7a18..e675c183ea7 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed @@ -115,12 +115,19 @@ fn main() { pub enum Enum { A, B, + C, #[doc(hidden)] __Private, } match Enum::A { Enum::A => (), Enum::B => (), + Enum::C => (), + _ => (), + } + match Enum::A { + Enum::A => (), + Enum::B => (), _ => (), } } diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs index d19e6ab7eb2..38c3ffc00c7 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs @@ -115,12 +115,19 @@ fn main() { pub enum Enum { A, B, + C, #[doc(hidden)] __Private, } match Enum::A { Enum::A => (), Enum::B => (), + Enum::C => (), + _ => (), + } + match Enum::A { + Enum::A => (), + Enum::B => (), _ => (), } } diff --git a/src/tools/clippy/tests/ui/mut_key.stderr b/src/tools/clippy/tests/ui/mut_key.stderr index 8d6a259c7e3..a8460b06ca6 100644 --- a/src/tools/clippy/tests/ui/mut_key.stderr +++ b/src/tools/clippy/tests/ui/mut_key.stderr @@ -4,7 +4,7 @@ error: mutable key type LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<Key> { | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(clippy::mutable_key_type)]` on by default + = note: `-D clippy::mutable-key-type` implied by `-D warnings` error: mutable key type --> $DIR/mut_key.rs:27:72 diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs index 0abe2cca267..79ba7402f1f 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs @@ -17,6 +17,24 @@ fn basic101(x: i32) { y = x + 1 } +#[rustfmt::skip] +fn closure_error() { + let _d = || { + hello() + }; +} + +#[rustfmt::skip] +fn unsafe_checks_error() { + use std::mem::MaybeUninit; + use std::ptr; + + let mut s = MaybeUninit::<String>::uninit(); + let _d = || unsafe { + ptr::drop_in_place(s.as_mut_ptr()) + }; +} + // this is fine fn print_sum(a: i32, b: i32) { println!("{}", a + b); @@ -53,3 +71,29 @@ fn loop_test(x: i32) { println!("{}", ext); } } + +fn closure() { + let _d = || hello(); +} + +#[rustfmt::skip] +fn closure_block() { + let _d = || { hello() }; +} + +unsafe fn some_unsafe_op() {} +unsafe fn some_other_unsafe_fn() {} + +fn do_something() { + unsafe { some_unsafe_op() }; + + unsafe { some_other_unsafe_fn() }; +} + +fn unsafe_checks() { + use std::mem::MaybeUninit; + use std::ptr; + + let mut s = MaybeUninit::<String>::uninit(); + let _d = || unsafe { ptr::drop_in_place(s.as_mut_ptr()) }; +} diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr index b73f8967538..e88ebe2ad35 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr @@ -18,5 +18,17 @@ error: consider adding a `;` to the last statement for consistent formatting LL | y = x + 1 | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` -error: aborting due to 3 previous errors +error: consider adding a `;` to the last statement for consistent formatting + --> $DIR/semicolon_if_nothing_returned.rs:23:9 + | +LL | hello() + | ^^^^^^^ help: add a `;` here: `hello();` + +error: consider adding a `;` to the last statement for consistent formatting + --> $DIR/semicolon_if_nothing_returned.rs:34:9 + | +LL | ptr::drop_in_place(s.as_mut_ptr()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` + +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_arithmetic_impl.stderr b/src/tools/clippy/tests/ui/suspicious_arithmetic_impl.stderr index 388fc740082..63fc9ecb79a 100644 --- a/src/tools/clippy/tests/ui/suspicious_arithmetic_impl.stderr +++ b/src/tools/clippy/tests/ui/suspicious_arithmetic_impl.stderr @@ -12,7 +12,7 @@ error: suspicious use of binary operator in `AddAssign` impl LL | *self = *self - other; | ^ | - = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default + = note: `-D clippy::suspicious-op-assign-impl` implied by `-D warnings` error: suspicious use of binary operator in `MulAssign` impl --> $DIR/suspicious_arithmetic_impl.rs:32:16 diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed index 7fbce58a82f..bda0f2c47cd 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed @@ -1,7 +1,7 @@ // run-rustfix #![warn(clippy::unnecessary_cast)] -#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::nonstandard_macro_braces)] fn main() { // casting integer literal to float is unnecessary diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs index a71363ea4d2..f7a4f2a5988 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs @@ -1,7 +1,7 @@ // run-rustfix #![warn(clippy::unnecessary_cast)] -#![allow(clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::nonstandard_macro_braces)] fn main() { // casting integer literal to float is unnecessary diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed index 631da6fe066..e2c28542efc 100644 --- a/src/tools/clippy/tests/ui/use_self.fixed +++ b/src/tools/clippy/tests/ui/use_self.fixed @@ -492,3 +492,26 @@ mod issue7206 { } } } + +mod self_is_ty_param { + trait Trait { + type Type; + type Hi; + + fn test(); + } + + impl<I> Trait for I + where + I: Iterator, + I::Item: Trait, // changing this to Self would require <Self as Iterator> + { + type Type = I; + type Hi = I::Item; + + fn test() { + let _: I::Item; + let _: I; // this could lint, but is questionable + } + } +} diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs index 7a10d755faa..3cd99b9f5cd 100644 --- a/src/tools/clippy/tests/ui/use_self.rs +++ b/src/tools/clippy/tests/ui/use_self.rs @@ -279,7 +279,7 @@ mod generics { impl<T> Foo<T> { // `Self` is applicable here fn foo(value: T) -> Foo<T> { - Foo { value } + Foo::<T> { value } } // `Cannot` use `Self` as a return type as the generic types are different @@ -492,3 +492,26 @@ mod issue7206 { } } } + +mod self_is_ty_param { + trait Trait { + type Type; + type Hi; + + fn test(); + } + + impl<I> Trait for I + where + I: Iterator, + I::Item: Trait, // changing this to Self would require <Self as Iterator> + { + type Type = I; + type Hi = I::Item; + + fn test() { + let _: I::Item; + let _: I; // this could lint, but is questionable + } + } +} diff --git a/src/tools/clippy/tests/ui/use_self.stderr b/src/tools/clippy/tests/ui/use_self.stderr index cf6222c9b45..6ac26c9e5a9 100644 --- a/src/tools/clippy/tests/ui/use_self.stderr +++ b/src/tools/clippy/tests/ui/use_self.stderr @@ -153,8 +153,8 @@ LL | fn foo(value: T) -> Foo<T> { error: unnecessary structure name repetition --> $DIR/use_self.rs:282:13 | -LL | Foo { value } - | ^^^ help: use the applicable keyword: `Self` +LL | Foo::<T> { value } + | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:454:13 diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed index da35f2e5c1b..318f9c2dceb 100644 --- a/src/tools/clippy/tests/ui/vec.fixed +++ b/src/tools/clippy/tests/ui/vec.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(clippy::nonstandard_macro_braces)] #![warn(clippy::useless_vec)] #[derive(Debug)] diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs index e9ed83e5c5a..d7673ce3e64 100644 --- a/src/tools/clippy/tests/ui/vec.rs +++ b/src/tools/clippy/tests/ui/vec.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(clippy::nonstandard_macro_braces)] #![warn(clippy::useless_vec)] #[derive(Debug)] diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed index c3e2cf0c4a4..52e80ceee83 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed @@ -320,6 +320,20 @@ fn issue1924() { println!("iterator field {}", it.1); } +fn issue7249() { + let mut it = 0..10; + let mut x = || { + // Needs &mut, the closure can be called multiple times + for x in &mut it { + if x % 2 == 0 { + break; + } + } + }; + x(); + x(); +} + fn main() { let mut it = 0..20; for _ in it { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs index 1717006a449..5078a3c9028 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs @@ -320,6 +320,20 @@ fn issue1924() { println!("iterator field {}", it.1); } +fn issue7249() { + let mut it = 0..10; + let mut x = || { + // Needs &mut, the closure can be called multiple times + while let Some(x) = it.next() { + if x % 2 == 0 { + break; + } + } + }; + x(); + x(); +} + fn main() { let mut it = 0..20; while let Some(..) = it.next() { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr index eff559bef7e..cb0afeae15e 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr @@ -105,10 +105,16 @@ LL | while let Some(n) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in &mut it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:325:5 + --> $DIR/while_let_on_iterator.rs:327:9 + | +LL | while let Some(x) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:339:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed index 5ad27bb1450..3ee4ab48ac8 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed @@ -1,4 +1,5 @@ // run-rustfix +// aux-build:non-exhaustive-enum.rs #![deny(clippy::wildcard_enum_match_arm)] #![allow( @@ -11,7 +12,9 @@ clippy::diverging_sub_expression )] -use std::io::ErrorKind; +extern crate non_exhaustive_enum; + +use non_exhaustive_enum::ErrorKind; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Color { @@ -77,29 +80,25 @@ fn main() { let error_kind = ErrorKind::NotFound; match error_kind { ErrorKind::NotFound => {}, - ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _ => {}, + ErrorKind::PermissionDenied | _ => {}, } match error_kind { ErrorKind::NotFound => {}, ErrorKind::PermissionDenied => {}, - ErrorKind::ConnectionRefused => {}, - ErrorKind::ConnectionReset => {}, - ErrorKind::ConnectionAborted => {}, - ErrorKind::NotConnected => {}, - ErrorKind::AddrInUse => {}, - ErrorKind::AddrNotAvailable => {}, - ErrorKind::BrokenPipe => {}, - ErrorKind::AlreadyExists => {}, - ErrorKind::WouldBlock => {}, - ErrorKind::InvalidInput => {}, - ErrorKind::InvalidData => {}, - ErrorKind::TimedOut => {}, - ErrorKind::WriteZero => {}, - ErrorKind::Interrupted => {}, - ErrorKind::Other => {}, - ErrorKind::UnexpectedEof => {}, - ErrorKind::Unsupported => {}, - ErrorKind::OutOfMemory => {}, _ => {}, } + + { + #![allow(clippy::manual_non_exhaustive)] + pub enum Enum { + A, + B, + #[doc(hidden)] + __Private, + } + match Enum::A { + Enum::A => (), + Enum::B | _ => (), + } + } } diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs index adca0738bba..46886550453 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs @@ -1,4 +1,5 @@ // run-rustfix +// aux-build:non-exhaustive-enum.rs #![deny(clippy::wildcard_enum_match_arm)] #![allow( @@ -11,7 +12,9 @@ clippy::diverging_sub_expression )] -use std::io::ErrorKind; +extern crate non_exhaustive_enum; + +use non_exhaustive_enum::ErrorKind; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Color { @@ -82,24 +85,20 @@ fn main() { match error_kind { ErrorKind::NotFound => {}, ErrorKind::PermissionDenied => {}, - ErrorKind::ConnectionRefused => {}, - ErrorKind::ConnectionReset => {}, - ErrorKind::ConnectionAborted => {}, - ErrorKind::NotConnected => {}, - ErrorKind::AddrInUse => {}, - ErrorKind::AddrNotAvailable => {}, - ErrorKind::BrokenPipe => {}, - ErrorKind::AlreadyExists => {}, - ErrorKind::WouldBlock => {}, - ErrorKind::InvalidInput => {}, - ErrorKind::InvalidData => {}, - ErrorKind::TimedOut => {}, - ErrorKind::WriteZero => {}, - ErrorKind::Interrupted => {}, - ErrorKind::Other => {}, - ErrorKind::UnexpectedEof => {}, - ErrorKind::Unsupported => {}, - ErrorKind::OutOfMemory => {}, _ => {}, } + + { + #![allow(clippy::manual_non_exhaustive)] + pub enum Enum { + A, + B, + #[doc(hidden)] + __Private, + } + match Enum::A { + Enum::A => (), + _ => (), + } + } } diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr index 73f6a4a80c9..d63f2090353 100644 --- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr +++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr @@ -1,38 +1,44 @@ error: wildcard match will also match any future added variants - --> $DIR/wildcard_enum_match_arm.rs:39:9 + --> $DIR/wildcard_enum_match_arm.rs:42:9 | LL | _ => eprintln!("Not red"), | ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` | note: the lint level is defined here - --> $DIR/wildcard_enum_match_arm.rs:3:9 + --> $DIR/wildcard_enum_match_arm.rs:4:9 | LL | #![deny(clippy::wildcard_enum_match_arm)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wildcard match will also match any future added variants - --> $DIR/wildcard_enum_match_arm.rs:43:9 + --> $DIR/wildcard_enum_match_arm.rs:46:9 | LL | _not_red => eprintln!("Not red"), | ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan` error: wildcard match will also match any future added variants - --> $DIR/wildcard_enum_match_arm.rs:47:9 + --> $DIR/wildcard_enum_match_arm.rs:50:9 | LL | not_red => format!("{:?}", not_red), | ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan` error: wildcard match will also match any future added variants - --> $DIR/wildcard_enum_match_arm.rs:63:9 + --> $DIR/wildcard_enum_match_arm.rs:66:9 | LL | _ => "No red", | ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan` error: wildcard matches known variants and will also match future added variants - --> $DIR/wildcard_enum_match_arm.rs:80:9 + --> $DIR/wildcard_enum_match_arm.rs:83:9 | LL | _ => {}, - | ^ help: try this: `ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _` + | ^ help: try this: `ErrorKind::PermissionDenied | _` -error: aborting due to 5 previous errors +error: wildcard matches known variants and will also match future added variants + --> $DIR/wildcard_enum_match_arm.rs:101:13 + | +LL | _ => (), + | ^ help: try this: `Enum::B | _` + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/zero_offset.rs b/src/tools/clippy/tests/ui/zero_offset.rs index 2de904376ad..6c190a4c86c 100644 --- a/src/tools/clippy/tests/ui/zero_offset.rs +++ b/src/tools/clippy/tests/ui/zero_offset.rs @@ -1,12 +1,18 @@ fn main() { unsafe { - let x = &() as *const (); - x.offset(0); - x.wrapping_add(0); - x.sub(0); - x.wrapping_sub(0); + let m = &mut () as *mut (); + m.offset(0); + m.wrapping_add(0); + m.sub(0); + m.wrapping_sub(0); - let y = &1 as *const u8; - y.offset(0); + let c = &() as *const (); + c.offset(0); + c.wrapping_add(0); + c.sub(0); + c.wrapping_sub(0); + + let sized = &1 as *const i32; + sized.offset(0); } } diff --git a/src/tools/clippy/tests/ui/zero_offset.stderr b/src/tools/clippy/tests/ui/zero_offset.stderr index cfcd7de2b3d..b12c8e9a73c 100644 --- a/src/tools/clippy/tests/ui/zero_offset.stderr +++ b/src/tools/clippy/tests/ui/zero_offset.stderr @@ -1,9 +1,52 @@ -error[E0606]: casting `&i32` as `*const u8` is invalid - --> $DIR/zero_offset.rs:9:17 +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:4:9 | -LL | let y = &1 as *const u8; - | ^^^^^^^^^^^^^^^ +LL | m.offset(0); + | ^^^^^^^^^^^ + | + = note: `#[deny(clippy::zst_offset)]` on by default + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:5:9 + | +LL | m.wrapping_add(0); + | ^^^^^^^^^^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:6:9 + | +LL | m.sub(0); + | ^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:7:9 + | +LL | m.wrapping_sub(0); + | ^^^^^^^^^^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:10:9 + | +LL | c.offset(0); + | ^^^^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:11:9 + | +LL | c.wrapping_add(0); + | ^^^^^^^^^^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:12:9 + | +LL | c.sub(0); + | ^^^^^^^^ + +error: offset calculation on zero-sized value + --> $DIR/zero_offset.rs:13:9 + | +LL | c.wrapping_sub(0); + | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0606`. diff --git a/src/tools/clippy/util/etc/pre-commit.sh b/src/tools/clippy/util/etc/pre-commit.sh new file mode 100755 index 00000000000..528f8953b25 --- /dev/null +++ b/src/tools/clippy/util/etc/pre-commit.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# hide output +set -e + +# Update lints +cargo dev update_lints +git add clippy_lints/src/lib.rs + +# Formatting: +# Git will not automatically add the formatted code to the staged changes once +# fmt was executed. This collects all staged files rs files that are currently staged. +# They will later be added back. +# +# This was proudly stolen and adjusted from here: +# https://medium.com/@harshitbangar/automatic-code-formatting-with-git-66c3c5c26798 +files=$( (git diff --cached --name-only --diff-filter=ACMR | grep -Ei "\.rs$") || true) +if [ ! -z "${files}" ]; then + cargo dev fmt + git add $(echo "$files" | paste -s -d " " -) +fi diff --git a/src/tools/clippy/util/etc/vscode-tasks.json b/src/tools/clippy/util/etc/vscode-tasks.json new file mode 100644 index 00000000000..a4bb26b9f90 --- /dev/null +++ b/src/tools/clippy/util/etc/vscode-tasks.json @@ -0,0 +1,57 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "cargo check", + "type": "shell", + "command": "cargo check", + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true, + }, + }, + { + "label": "cargo dev fmt", + "type": "shell", + "command": "cargo dev fmt", + "problemMatcher": [], + "group": "none", + }, + { + "label": "cargo uitest", + "type": "shell", + "command": "cargo uitest", + "options": { + "env": { + "RUST_BACKTRACE": "1", + // This task will usually execute all UI tests inside `tests/ui` you can + // optionally uncomment the line below and only run a specific test. + // + // See: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md#testing + // + // "TESTNAME": "<TODO>", + }, + }, + "problemMatcher": [], + "group": { + "kind": "test", + "isDefault": true, + } + }, + { + "label": "cargo test", + "type": "shell", + "command": "cargo test", + "problemMatcher": [], + "group": "test", + }, + { + "label": "cargo dev bless", + "type": "shell", + "command": "cargo dev bless", + "problemMatcher": [], + "group": "none", + }, + ], +} diff --git a/src/tools/clippy/util/lintlib.py b/src/tools/clippy/util/lintlib.py index 5707cf0ce0f..9cefb2dbb19 100644 --- a/src/tools/clippy/util/lintlib.py +++ b/src/tools/clippy/util/lintlib.py @@ -12,13 +12,14 @@ Config = collections.namedtuple('Config', 'name ty doc default') lintname_re = re.compile(r'''pub\s+([A-Z_][A-Z_0-9]*)''') group_re = re.compile(r'''\s*([a-z_][a-z_0-9]+)''') -conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) +conf_re = re.compile(r'''define_Conf! {\n((?!\n})[\s\S])*\n}''', re.MULTILINE) confvar_re = re.compile( r'''/// Lint: ([\w,\s]+)\. (.*)\n\s*\(([^:]+):\s*([^\s=]+)\s*=\s*([^\.\)]+).*\),''', re.MULTILINE) comment_re = re.compile(r'''\s*/// ?(.*)''') lint_levels = { "correctness": 'Deny', + "suspicious": 'Warn', "style": 'Warn', "complexity": 'Warn', "perf": 'Warn', @@ -91,7 +92,7 @@ def parse_configs(path): contents = fp.read() match = re.search(conf_re, contents) - confvars = re.findall(confvar_re, match.group(1)) + confvars = re.findall(confvar_re, match.group(0)) for (lints, doc, name, ty, default) in confvars: for lint in lints.split(','): diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 764f2055277..68e28795347 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -903,9 +903,7 @@ pub fn make_test_description<R: Read>( ignore, should_panic, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: test::TestType::Unknown, } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 6a1faee1d8e..49731b2d7dc 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -778,6 +778,14 @@ impl<'test> TestCx<'test> { script_str.push_str("version\n"); // List CDB (and more) version info in test output script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug + // If a .js file exists next to the source file being tested, then this is a JavaScript + // debugging extension that needs to be loaded. + let mut js_extension = self.testpaths.file.clone(); + js_extension.set_extension("cdb.js"); + if js_extension.exists() { + script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy())); + } + // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); for line in &breakpoint_lines { @@ -2329,13 +2337,17 @@ impl<'test> TestCx<'test> { // useful flag. // // For now, though… - if let Some(rev) = self.revision { - let prefixes = format!("CHECK,{}", rev); - if self.config.llvm_version.unwrap_or(0) >= 130000 { - filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); - } else { - filecheck.args(&["--check-prefixes", &prefixes]); - } + let prefix_for_target = + if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" }; + let prefixes = if let Some(rev) = self.revision { + format!("CHECK,{},{}", prefix_for_target, rev) + } else { + format!("CHECK,{}", prefix_for_target) + }; + if self.config.llvm_version.unwrap_or(0) >= 130000 { + filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]); + } else { + filecheck.args(&["--check-prefixes", &prefixes]); } self.compose_and_run(filecheck, "", None, None) } diff --git a/src/tools/html-checker/Cargo.toml b/src/tools/html-checker/Cargo.toml new file mode 100644 index 00000000000..fe35df823b6 --- /dev/null +++ b/src/tools/html-checker/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "html-checker" +version = "0.1.0" +authors = ["Guillaume Gomez <guillaume1.gomez@gmail.com>"] +edition = "2018" + +[[bin]] +name = "html-checker" +path = "main.rs" + +[dependencies] +walkdir = "2" diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs new file mode 100644 index 00000000000..bf2830254e8 --- /dev/null +++ b/src/tools/html-checker/main.rs @@ -0,0 +1,93 @@ +use std::env; +use std::path::Path; +use std::process::{Command, Output}; + +fn check_html_file(file: &Path) -> usize { + let to_mute = &[ + // "disabled" on <link> or "autocomplete" on <select> emit this warning + "PROPRIETARY_ATTRIBUTE", + // It complains when multiple in the same page link to the same anchor for some reason... + "ANCHOR_NOT_UNIQUE", + // If a <span> contains only HTML elements and no text, it complains about it. + "TRIM_EMPTY_ELEMENT", + // FIXME: the three next warnings are about <pre> elements which are not supposed to + // contain HTML. The solution here would be to replace them with a <div> + "MISSING_ENDTAG_BEFORE", + "INSERTING_TAG", + "DISCARDING_UNEXPECTED", + ]; + let to_mute_s = to_mute.join(","); + let mut command = Command::new("tidy"); + command + .arg("-errors") + .arg("-quiet") + .arg("--mute-id") // this option is useful in case we want to mute more warnings + .arg("yes") + .arg("--mute") + .arg(&to_mute_s) + .arg(file); + + let Output { status, stderr, .. } = command.output().expect("failed to run tidy command"); + if status.success() { + 0 + } else { + let stderr = String::from_utf8(stderr).expect("String::from_utf8 failed..."); + if stderr.is_empty() && status.code() != Some(2) { + 0 + } else { + eprintln!( + "=> Errors for `{}` (error code: {}) <=", + file.display(), + status.code().unwrap_or(-1) + ); + eprintln!("{}", stderr); + stderr.lines().count() + } + } +} + +const DOCS_TO_CHECK: &[&str] = + &["alloc", "core", "proc_macro", "implementors", "src", "std", "test"]; + +// Returns the number of files read and the number of errors. +fn find_all_html_files(dir: &Path) -> (usize, usize) { + let mut files_read = 0; + let mut errors = 0; + + for entry in walkdir::WalkDir::new(dir).into_iter().filter_entry(|e| { + e.depth() != 1 + || e.file_name() + .to_str() + .map(|s| DOCS_TO_CHECK.into_iter().any(|d| *d == s)) + .unwrap_or(false) + }) { + let entry = entry.expect("failed to read file"); + if !entry.file_type().is_file() { + continue; + } + let entry = entry.path(); + if entry.extension().and_then(|s| s.to_str()) == Some("html") { + errors += check_html_file(&entry); + files_read += 1; + } + } + (files_read, errors) +} + +fn main() -> Result<(), String> { + let args = env::args().collect::<Vec<_>>(); + if args.len() != 2 { + return Err(format!("Usage: {} <doc folder>", args[0])); + } + + println!("Running HTML checker..."); + + let (files_read, errors) = find_all_html_files(&Path::new(&args[1])); + println!("Done! Read {} files...", files_read); + if errors > 0 { + Err(format!("HTML check failed: {} errors", errors)) + } else { + println!("No error found!"); + Ok(()) + } +} diff --git a/src/tools/miri b/src/tools/miri -Subproject 23f05fc603252b7906bd7e44208ab24038f8da1 +Subproject 05fdec916a3a9755c6ea603bab79cdb2f7c062b diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 4a4b26da54c..26d6081c881 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -78,7 +78,7 @@ syn = { version = "1", features = ['fold', 'full', 'extra-traits', 'visit', 'vis url = { version = "2.0", features = ['serde'] } [target.'cfg(not(windows))'.dependencies] -openssl = { version = "0.10.12", optional = true } +openssl = { version = "0.10.35", optional = true } [features] all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx'] diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index cde5d390cf2..ce8a45eea65 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] #![deny(rust_2018_idioms)] #![warn(unreachable_pub)] +#![recursion_limit = "256"] #[macro_use] extern crate derive_new; diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 58c32993cb6..e44d2bb7256 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" autobins = false [dependencies] -cargo_metadata = "0.11" +cargo_metadata = "0.12" regex = "1" lazy_static = "1" walkdir = "2" diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index a7e700b935e..338dfd11310 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -301,6 +301,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features let mut parts = line.split(','); let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) { Some("active") => Status::Unstable, + Some("incomplete") => Status::Unstable, Some("removed") => Status::Removed, Some("accepted") => Status::Stable, _ => return None, diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 3d5f39e8c90..15ed2f7a0a9 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -52,6 +52,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[ "// error-pattern", "// gdb", "// lldb", + "// cdb", "// normalize-stderr-test", ]; diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index f61295c8830..66d05d9f00e 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,8 +7,8 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 1371; -const ISSUES_ENTRY_LIMIT: usize = 2559; +const ROOT_ENTRY_LIMIT: usize = 1345; +const ISSUES_ENTRY_LIMIT: usize = 2530; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui")) diff --git a/triagebot.toml b/triagebot.toml index 4621adb2ba8..968b80414bc 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -4,7 +4,7 @@ allow-unauthenticated = [ "D-*", "requires-nightly", "regression-*", - "perf-regression", + "perf-*", # I-* without I-nominated "I-*", "!I-nominated", "AsyncAwait-OnDeck", |
