From 4404a4e365fb7090585e23f9d54110f214888f39 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 02:22:02 +0000 Subject: [PATCH 01/14] updating the feature-gate listing and do not require the feature-gate to use the feature --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/active.rs | 2 -- compiler/rustc_feature/src/builtin_attrs.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 88edaec916972..edcbead731f68 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -70,6 +70,8 @@ declare_features! ( (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Enables `#[cfg(panic = "...")]` config key. + (accepted, cfg_panic, "1.60.0", Some(77443), None), /// Allows `cfg(target_feature = "...")`. (accepted, cfg_target_feature, "1.27.0", Some(29717), None), /// Allows `cfg(target_has_atomic = "...")`. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index fab22e4e6cf32..e14b9a0ad709f 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -303,8 +303,6 @@ declare_features! ( (active, c_variadic, "1.34.0", Some(44930), None), /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), - /// Enables `#[cfg(panic = "...")]` config key. - (active, cfg_panic, "1.49.0", Some(77443), None), /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (active, cfg_sanitize, "1.41.0", Some(39699), None), /// Allows `cfg(target_abi = "...")`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 69ce21d231f27..cbc8aa8463a32 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -33,7 +33,6 @@ const GATED_CFGS: &[GatedCfg] = &[ ), (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), - (sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. From 5e6be7df942e984d3d5388eb04d2a40d49fb8473 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 17:14:58 +0000 Subject: [PATCH 02/14] replace feature expression (cfg_panic) in lib and remove expression from tests Rebase commit --- library/core/tests/lib.rs | 2 +- src/test/ui/cfg/cfg-panic-abort.rs | 2 +- src/test/ui/cfg/cfg-panic.rs | 2 +- src/test/ui/fmt/format-args-capture.rs | 1 - src/test/ui/issues/issue-68696-catch-during-unwind.rs | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 1c512471c95cb..d439a8d7de4f9 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -6,7 +6,7 @@ #![feature(bool_to_option)] #![feature(box_syntax)] #![feature(cell_update)] -#![feature(cfg_panic)] +#![cfg_attr(bootstrap,feature(cfg_panic))] #![cfg_attr(bootstrap, feature(cfg_target_has_atomic))] #![feature(const_assume)] #![feature(const_black_box)] diff --git a/src/test/ui/cfg/cfg-panic-abort.rs b/src/test/ui/cfg/cfg-panic-abort.rs index 9b88eff12ed38..3853b598a7a79 100644 --- a/src/test/ui/cfg/cfg-panic-abort.rs +++ b/src/test/ui/cfg/cfg-panic-abort.rs @@ -1,7 +1,7 @@ // build-pass // compile-flags: -C panic=abort // no-prefer-dynamic -#![feature(cfg_panic)] + #[cfg(panic = "unwind")] pub fn bad() -> i32 { } diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs index d2113e4f5ecc6..fb3e5059c8199 100644 --- a/src/test/ui/cfg/cfg-panic.rs +++ b/src/test/ui/cfg/cfg-panic.rs @@ -4,7 +4,7 @@ // ignore-emscripten no panic_unwind implementation // ignore-wasm32 no panic_unwind implementation // ignore-wasm64 no panic_unwind implementation -#![feature(cfg_panic)] + #[cfg(panic = "abort")] pub fn bad() -> i32 { } diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index d31d2a6c33657..560352b5cb958 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(cfg_panic)] fn main() { named_argument_takes_precedence_to_captured(); diff --git a/src/test/ui/issues/issue-68696-catch-during-unwind.rs b/src/test/ui/issues/issue-68696-catch-during-unwind.rs index f25a78f59cd20..2b12a62d0eb25 100644 --- a/src/test/ui/issues/issue-68696-catch-during-unwind.rs +++ b/src/test/ui/issues/issue-68696-catch-during-unwind.rs @@ -4,7 +4,6 @@ // entering the catch_unwind. // // run-pass -#![feature(cfg_panic)] use std::panic::catch_unwind; From 962094b449df39e22179846e551683f917981448 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 18:34:10 +0000 Subject: [PATCH 03/14] Rebase --- .../feature-gates/feature-gate-cfg-panic.rs | 11 ---------- .../feature-gate-cfg-panic.stderr | 21 ------------------- 2 files changed, 32 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-cfg-panic.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-cfg-panic.stderr diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs b/src/test/ui/feature-gates/feature-gate-cfg-panic.rs deleted file mode 100644 index 1508374d94266..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(panic = "unwind")] -//~^ ERROR `cfg(panic)` is experimental and subject to change -fn foo() -> bool { true } -#[cfg(not(panic = "unwind"))] -//~^ ERROR `cfg(panic)` is experimental and subject to change -fn foo() -> bool { false } - - -fn main() { - assert!(foo()); -} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr deleted file mode 100644 index ea5cd54fa90f0..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: `cfg(panic)` is experimental and subject to change - --> $DIR/feature-gate-cfg-panic.rs:1:7 - | -LL | #[cfg(panic = "unwind")] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #77443 for more information - = help: add `#![feature(cfg_panic)]` to the crate attributes to enable - -error[E0658]: `cfg(panic)` is experimental and subject to change - --> $DIR/feature-gate-cfg-panic.rs:4:11 - | -LL | #[cfg(not(panic = "unwind"))] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #77443 for more information - = help: add `#![feature(cfg_panic)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. From 46ec73ac3af3948af873e5157a5d807ff1a7ee73 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 18:36:31 +0000 Subject: [PATCH 04/14] remove reference of cfg-panic from the unstable book --- .../src/language-features/cfg-panic.md | 38 ------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/cfg-panic.md diff --git a/src/doc/unstable-book/src/language-features/cfg-panic.md b/src/doc/unstable-book/src/language-features/cfg-panic.md deleted file mode 100644 index f5b73128ad6c2..0000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-panic.md +++ /dev/null @@ -1,38 +0,0 @@ -# `cfg_panic` - -The tracking issue for this feature is: [#77443] - -[#77443]: https://github.com/rust-lang/rust/issues/77443 - ------------------------- - -The `cfg_panic` feature makes it possible to execute different code -depending on the panic strategy. - -Possible values at the moment are `"unwind"` or `"abort"`, although -it is possible that new panic strategies may be added to Rust in the -future. - -## Examples - -```rust -#![feature(cfg_panic)] - -#[cfg(panic = "unwind")] -fn a() { - // ... -} - -#[cfg(not(panic = "unwind"))] -fn a() { - // ... -} - -fn b() { - if cfg!(panic = "abort") { - // ... - } else { - // ... - } -} -``` From d018a8b6248a15e871c2220296c1fa639d6267c6 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 19:55:55 +0000 Subject: [PATCH 05/14] remove mention of cfg_panic from library tests --- library/core/tests/array.rs | 3 --- library/core/tests/iter/adapters/zip.rs | 1 - library/core/tests/mem.rs | 2 -- 3 files changed, 6 deletions(-) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index a778779c0fd88..ee8435e6d6c6f 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -392,7 +392,6 @@ fn array_try_from_fn() { assert_eq!(another_array, Err(SomeError::Foo)); } -#[cfg(not(panic = "abort"))] #[test] fn array_try_from_fn_drops_inserted_elements_on_err() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -416,7 +415,6 @@ fn array_try_from_fn_drops_inserted_elements_on_err() { assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } -#[cfg(not(panic = "abort"))] #[test] fn array_try_from_fn_drops_inserted_elements_on_panic() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -440,7 +438,6 @@ fn array_try_from_fn_drops_inserted_elements_on_panic() { assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } -#[cfg(not(panic = "abort"))] // https://stackoverflow.com/a/59211505 fn catch_unwind_silent(f: F) -> std::thread::Result where diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs index 585cfbb90e40c..58563e2061ca3 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -233,7 +233,6 @@ fn test_zip_trusted_random_access_composition() { } #[test] -#[cfg(panic = "unwind")] fn test_zip_trusted_random_access_next_back_drop() { use std::panic::catch_unwind; use std::panic::AssertUnwindSafe; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 3b13dc0832fa4..f878017c97798 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -1,6 +1,5 @@ use core::mem::*; -#[cfg(panic = "unwind")] use std::rc::Rc; #[test] @@ -190,7 +189,6 @@ fn uninit_write_slice_cloned_panic_gt() { } #[test] -#[cfg(panic = "unwind")] fn uninit_write_slice_cloned_mid_panic() { use std::panic; From a889079b29ee8204ea4cf19842bc759e676a2937 Mon Sep 17 00:00:00 2001 From: Charisee Date: Fri, 4 Feb 2022 21:55:22 +0000 Subject: [PATCH 06/14] add cfg_panic bootstrap --- library/core/tests/array.rs | 3 +++ library/core/tests/iter/adapters/zip.rs | 1 + library/core/tests/mem.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index ee8435e6d6c6f..a778779c0fd88 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -392,6 +392,7 @@ fn array_try_from_fn() { assert_eq!(another_array, Err(SomeError::Foo)); } +#[cfg(not(panic = "abort"))] #[test] fn array_try_from_fn_drops_inserted_elements_on_err() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -415,6 +416,7 @@ fn array_try_from_fn_drops_inserted_elements_on_err() { assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } +#[cfg(not(panic = "abort"))] #[test] fn array_try_from_fn_drops_inserted_elements_on_panic() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -438,6 +440,7 @@ fn array_try_from_fn_drops_inserted_elements_on_panic() { assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } +#[cfg(not(panic = "abort"))] // https://stackoverflow.com/a/59211505 fn catch_unwind_silent(f: F) -> std::thread::Result where diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs index 58563e2061ca3..585cfbb90e40c 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -233,6 +233,7 @@ fn test_zip_trusted_random_access_composition() { } #[test] +#[cfg(panic = "unwind")] fn test_zip_trusted_random_access_next_back_drop() { use std::panic::catch_unwind; use std::panic::AssertUnwindSafe; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index f878017c97798..3b13dc0832fa4 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -1,5 +1,6 @@ use core::mem::*; +#[cfg(panic = "unwind")] use std::rc::Rc; #[test] @@ -189,6 +190,7 @@ fn uninit_write_slice_cloned_panic_gt() { } #[test] +#[cfg(panic = "unwind")] fn uninit_write_slice_cloned_mid_panic() { use std::panic; From dbeab9c532080a52f5cc86fbb4ca679581b866fd Mon Sep 17 00:00:00 2001 From: Charisee Date: Thu, 10 Feb 2022 22:30:51 +0000 Subject: [PATCH 07/14] added space --- library/core/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index d439a8d7de4f9..cc628aa746346 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -6,7 +6,7 @@ #![feature(bool_to_option)] #![feature(box_syntax)] #![feature(cell_update)] -#![cfg_attr(bootstrap,feature(cfg_panic))] +#![cfg_attr(bootstrap, feature(cfg_panic))] #![cfg_attr(bootstrap, feature(cfg_target_has_atomic))] #![feature(const_assume)] #![feature(const_black_box)] From ae158224acb8a85efce18cd358a445d18c6c6389 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 13 Feb 2022 01:25:54 +0000 Subject: [PATCH 08/14] rustdoc-json: buffer output --- src/librustdoc/json/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index f9e9fe0d3cf20..52980e07b8ca3 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -8,6 +8,7 @@ mod conversions; use std::cell::RefCell; use std::fs::{create_dir_all, File}; +use std::io::{BufWriter, Write}; use std::path::PathBuf; use std::rc::Rc; @@ -213,7 +214,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let mut index = (*self.index).clone().into_inner(); index.extend(self.get_trait_items()); // This needs to be the default HashMap for compatibility with the public interface for - // rustdoc-json + // rustdoc-json-types #[allow(rustc::default_hash_types)] let output = types::Crate { root: types::Id(String::from("0:0")), @@ -263,8 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let mut p = out_dir; p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); p.set_extension("json"); - let file = try_err!(File::create(&p), p); - serde_json::ser::to_writer(&file, &output).unwrap(); + let mut file = BufWriter::new(try_err!(File::create(&p), p)); + serde_json::ser::to_writer(&mut file, &output).unwrap(); + try_err!(file.flush(), p); + Ok(()) } From 11ec2a47a43ceba5506165e0db5fc8355bff4073 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 13 Oct 2021 21:31:18 +0200 Subject: [PATCH 09/14] extract Res to `generics_of` def_id conversion --- compiler/rustc_middle/src/ty/util.rs | 33 +++++++++++++++- compiler/rustc_typeck/src/collect/type_of.rs | 40 +++----------------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c2a4cea2b1ae6..92d9cb2fc1b2b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -17,7 +17,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def::DefKind; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_query_system::ich::NodeIdHashingMode; @@ -146,6 +146,37 @@ impl<'tcx> TyCtxt<'tcx> { hasher.finish() } + pub fn res_generics_def_id(self, res: Res) -> Option { + match res { + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => { + Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap()) + } + Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { + Some(self.parent(def_id).unwrap()) + } + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => Some(def_id), + Res::Err => None, + _ => None, + } + } + pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { if let ty::Adt(def, substs) = *ty.kind() { for field in def.all_fields() { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 90555b213c1ca..65aa49971cb77 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,7 +1,6 @@ use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; -use rustc_hir::def::CtorOf; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; @@ -9,7 +8,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -198,38 +197,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); - let generics = match res { - Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx - .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()), - Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { - tcx.generics_of(tcx.parent(def_id).unwrap()) - } - // Other `DefKind`s don't have generics and would ICE when calling - // `generics_of`. - Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::OpaqueTy - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Fn - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::Impl, - def_id, - ) => tcx.generics_of(def_id), - Res::Err => { - tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); - return None; - } - _ => { - // If the user tries to specify generics on a type that does not take them, - // e.g. `usize`, we may hit this branch, in which case we treat it as if - // no arguments have been passed. An error should already have been emitted. + let generics = match tcx.res_generics_def_id(res) { + Some(def_id) => tcx.generics_of(def_id), + None => { tcx.sess.delay_span_bug( tcx.def_span(def_id), &format!("unexpected anon const res {:?} in path: {:?}", res, path), From 1b7c3bcef9dc88e65c4914887071e432436a0b04 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Feb 2022 14:13:02 +0100 Subject: [PATCH 10/14] allow special behavior when printing const infer --- .../infer/error_reporting/need_type_info.rs | 30 +++++++++++++----- compiler/rustc_middle/src/ty/print/pretty.rs | 31 ++++++++++++++----- .../const-generics/defaults/doesnt_infer.rs | 2 +- .../defaults/doesnt_infer.stderr | 2 +- .../generic_arg_infer/issue-91614.rs | 2 +- .../generic_arg_infer/issue-91614.stderr | 2 +- 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index aba5666b58cd7..4ea8241072ebe 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -497,16 +497,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); - let mut inner = self.inner.borrow_mut(); - let ty_vars = inner.type_variables(); - let getter = move |ty_vid| { - let var_origin = ty_vars.var_origin(ty_vid); - if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind { + let ty_getter = move |ty_vid| { + if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = + self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind + { + Some(name.to_string()) + } else { + None + } + }; + printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); + let const_getter = move |ct_vid| { + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = self + .inner + .borrow_mut() + .const_unification_table() + .probe_value(ct_vid) + .origin + .kind + { return Some(name.to_string()); + } else { + None } - None }; - printer.name_resolver = Some(Box::new(&getter)); + printer.const_infer_name_resolver = Some(Box::new(const_getter)); + let _ = if let ty::FnDef(..) = ty.kind() { // We don't want the regular output for `fn`s because it includes its path in // invalid pseudo-syntax, we want the `fn`-pointer output instead. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 893df1a009cfc..94bbb711cfe38 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -606,7 +606,7 @@ pub trait PrettyPrinter<'tcx>: ty::Infer(infer_ty) => { let verbose = self.tcx().sess.verbose(); if let ty::TyVar(ty_vid) = infer_ty { - if let Some(name) = self.infer_ty_name(ty_vid) { + if let Some(name) = self.ty_infer_name(ty_vid) { p!(write("{}", name)) } else { if verbose { @@ -1015,7 +1015,11 @@ pub trait PrettyPrinter<'tcx>: } } - fn infer_ty_name(&self, _: ty::TyVid) -> Option { + fn ty_infer_name(&self, _: ty::TyVid) -> Option { + None + } + + fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option { None } @@ -1203,7 +1207,14 @@ pub trait PrettyPrinter<'tcx>: } } } - ty::ConstKind::Infer(..) => print_underscore!(), + ty::ConstKind::Infer(infer_ct) => { + match infer_ct { + ty::InferConst::Var(ct_vid) + if let Some(name) = self.const_infer_name(ct_vid) => + p!(write("{}", name)), + _ => print_underscore!(), + } + } ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(value) => { return self.pretty_print_const_value(value, ct.ty(), print_ty); @@ -1551,7 +1562,8 @@ pub struct FmtPrinterData<'a, 'tcx, F> { pub region_highlight_mode: RegionHighlightMode<'tcx>, - pub name_resolver: Option Option>>, + pub ty_infer_name_resolver: Option Option + 'a>>, + pub const_infer_name_resolver: Option) -> Option + 'a>>, } impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> { @@ -1580,7 +1592,8 @@ impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> { binder_depth: 0, printed_type_count: 0, region_highlight_mode: RegionHighlightMode::new(tcx), - name_resolver: None, + ty_infer_name_resolver: None, + const_infer_name_resolver: None, })) } } @@ -1835,8 +1848,12 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { - fn infer_ty_name(&self, id: ty::TyVid) -> Option { - self.0.name_resolver.as_ref().and_then(|func| func(id)) + fn ty_infer_name(&self, id: ty::TyVid) -> Option { + self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id)) + } + + fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option { + self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } fn print_value_path( diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.rs b/src/test/ui/const-generics/defaults/doesnt_infer.rs index cd533b57bc31f..9c59e672d8e4c 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.rs +++ b/src/test/ui/const-generics/defaults/doesnt_infer.rs @@ -9,5 +9,5 @@ impl Foo { fn main() { let foo = Foo::<1>::foo(); let foo = Foo::foo(); - //~^ error: type annotations needed for `Foo<{_: u32}>` + //~^ error: type annotations needed for `Foo` } diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 1551e81ea7577..cccf433e32864 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Foo<{_: u32}>` +error[E0282]: type annotations needed for `Foo` --> $DIR/doesnt_infer.rs:11:15 | LL | let foo = Foo::foo(); diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs index 413cc1539248a..b45e2cbc7372b 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs @@ -4,5 +4,5 @@ use std::simd::Mask; fn main() { let y = Mask::<_, _>::splat(false); - //~^ error: type annotations needed for `Mask<_, {_: usize}>` + //~^ ERROR: type annotations needed for } diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr index 71a5ff79280fd..347cd2364b266 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed for `Mask<_, {_: usize}>` +error[E0283]: type annotations needed for `Mask<_, LANES>` --> $DIR/issue-91614.rs:6:13 | LL | let y = Mask::<_, _>::splat(false); From f41722a2ad1b941c73c77133ba2c87f83d10620d Mon Sep 17 00:00:00 2001 From: pierwill Date: Mon, 14 Feb 2022 16:04:21 -0600 Subject: [PATCH 11/14] Use a `Field` in `ConstraintCategory::ClosureUpvar` --- .../src/diagnostics/region_errors.rs | 22 ++++++++++++++----- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +--- compiler/rustc_middle/src/mir/query.rs | 4 ++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index ca1e77ff8fdc0..e6a323d676e14 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::{ error_reporting::nice_region_error::NiceRegionError, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, }; +use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, RegionVid, Ty}; @@ -421,17 +422,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, message); - // FIXME(project-rfc-2229#48): This should store a captured_place not a hir id - if let ReturnConstraint::ClosureUpvar(upvar) = kind { + if let ReturnConstraint::ClosureUpvar(upvar_field) = kind { let def_id = match self.regioncx.universal_regions().defining_ty { DefiningTy::Closure(def_id, _) => def_id, ty => bug!("unexpected DefiningTy {:?}", ty), }; - let upvar_def_span = self.infcx.tcx.hir().span(upvar); - let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span; - diag.span_label(upvar_def_span, "variable defined here"); - diag.span_label(upvar_span, "variable captured here"); + let captured_place = &self.upvars[upvar_field.index()].place; + let defined_hir = match captured_place.place.base { + PlaceBase::Local(hirid) => Some(hirid), + PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id), + _ => None, + }; + + if defined_hir.is_some() { + let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap(); + let upvar_def_span = self.infcx.tcx.hir().span(defined_hir.unwrap()); + let upvar_span = upvars_map.get(&defined_hir.unwrap()).unwrap().span; + diag.span_label(upvar_def_span, "variable defined here"); + diag.span_label(upvar_span, "variable captured here"); + } } if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 46924f50d2e1b..a58240900969e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2530,9 +2530,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body, ); let category = if let Some(field) = field { - let var_hir_id = self.borrowck_context.upvars[field.index()].place.get_root_variable(); - // FIXME(project-rfc-2229#8): Use Place for better diagnostics - ConstraintCategory::ClosureUpvar(var_hir_id) + ConstraintCategory::ClosureUpvar(field) } else { ConstraintCategory::Boring }; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 5c616425957df..fbd5a2d08a5dc 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -341,7 +341,7 @@ pub enum ConstraintCategory { /// like `Foo { field: my_val }`) Usage, OpaqueType, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), /// A constraint from a user-written predicate /// with the provided span, written on the item @@ -363,7 +363,7 @@ pub enum ConstraintCategory { #[derive(TyEncodable, TyDecodable, HashStable)] pub enum ReturnConstraint { Normal, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), } /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing From 897c8d0ab9d3cb2cf1c112f31c6ac3e93d9884bc Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sun, 13 Feb 2022 15:04:11 -0800 Subject: [PATCH 12/14] Add debug asserts to validate NUL terminator in c strings Signed-off-by: Alex Saveau --- library/std/src/ffi/c_str.rs | 41 +++++++++++++++++++++--------- library/std/src/ffi/c_str/tests.rs | 8 ------ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index c3f024026efad..b52cc97504a24 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -382,7 +382,7 @@ impl CString { let bytes: Vec = self.into(); match memchr::memchr(0, &bytes) { Some(i) => Err(NulError(i, bytes)), - None => Ok(unsafe { CString::from_vec_unchecked(bytes) }), + None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }), } } } @@ -405,7 +405,7 @@ impl CString { // This allows better optimizations if lto enabled. match memchr::memchr(0, bytes) { Some(i) => Err(NulError(i, buffer)), - None => Ok(unsafe { CString::from_vec_unchecked(buffer) }), + None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }), } } @@ -451,10 +451,15 @@ impl CString { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { + pub unsafe fn from_vec_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).is_none()); + unsafe { Self::_from_vec_unchecked(v) } + } + + unsafe fn _from_vec_unchecked(mut v: Vec) -> Self { v.reserve_exact(1); v.push(0); - CString { inner: v.into_boxed_slice() } + Self { inner: v.into_boxed_slice() } } /// Retakes ownership of a `CString` that was transferred to C via @@ -578,7 +583,7 @@ impl CString { pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { error: e.utf8_error(), - inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) }, + inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, }) } @@ -735,6 +740,11 @@ impl CString { #[must_use] #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len()); + unsafe { Self::_from_vec_with_nul_unchecked(v) } + } + + unsafe fn _from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } @@ -778,7 +788,7 @@ impl CString { Some(nul_pos) if nul_pos + 1 == v.len() => { // SAFETY: We know there is only one nul byte, at the end // of the vec. - Ok(unsafe { Self::from_vec_with_nul_unchecked(v) }) + Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) }) } Some(nul_pos) => Err(FromVecWithNulError { error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), @@ -811,7 +821,7 @@ impl ops::Deref for CString { #[inline] fn deref(&self) -> &CStr { - unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } + unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } } @@ -922,7 +932,7 @@ impl From> for CString { }; // SAFETY: `v` cannot contain null bytes, given the type-level // invariant of `NonZeroU8`. - CString::from_vec_unchecked(v) + Self::_from_vec_unchecked(v) } } } @@ -1215,7 +1225,7 @@ impl CStr { unsafe { let len = sys::strlen(ptr); let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) } } @@ -1258,7 +1268,7 @@ impl CStr { Some(nul_pos) if nul_pos + 1 == bytes.len() => { // SAFETY: We know there is only one nul byte, at the end // of the byte slice. - Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) + Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) }) } Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), None => Err(FromBytesWithNulError::not_nul_terminated()), @@ -1287,12 +1297,19 @@ impl CStr { #[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { + // We're in a const fn, so this is the best we can do + debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); + unsafe { Self::_from_bytes_with_nul_unchecked(bytes) } + } + + #[inline] + const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self { // SAFETY: Casting to CStr is safe because its internal representation // is a [u8] too (safe only inside std). // Dereferencing the obtained pointer is safe because it comes from a // reference. Making a reference is then safe because its lifetime // is bound by the lifetime of the given `bytes`. - unsafe { &*(bytes as *const [u8] as *const CStr) } + unsafe { &*(bytes as *const [u8] as *const Self) } } /// Returns the inner pointer to this C string. @@ -1555,7 +1572,7 @@ impl ops::Index> for CStr { // byte, since otherwise we could get an empty string that doesn't end // in a null. if index.start < bytes.len() { - unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } + unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) } } else { panic!( "index out of bounds: the len is {} but the index is {}", diff --git a/library/std/src/ffi/c_str/tests.rs b/library/std/src/ffi/c_str/tests.rs index 4f7ba9ad43756..00ba5460821ff 100644 --- a/library/std/src/ffi/c_str/tests.rs +++ b/library/std/src/ffi/c_str/tests.rs @@ -32,14 +32,6 @@ fn build_with_zero2() { assert!(CString::new(vec![0]).is_err()); } -#[test] -fn build_with_zero3() { - unsafe { - let s = CString::from_vec_unchecked(vec![0]); - assert_eq!(s.as_bytes(), b"\0"); - } -} - #[test] fn formatted() { let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap(); From 8cd9dfad1e2f24e52e022bdad52f23286af8c571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 17 Feb 2022 00:00:00 +0000 Subject: [PATCH 13/14] Fix ScalarInt to char conversion to avoid panic for invalid Unicode scalar values --- compiler/rustc_middle/src/ty/consts/int.rs | 18 +++++-- .../invalid_constant.main.ConstProp.diff | 48 ++++++++++++------- .../mir-opt/const_prop/invalid_constant.rs | 8 +++- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index de45e1bb851ac..ca1db2fd55141 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -294,12 +294,22 @@ impl From for ScalarInt { } } +/// Error returned when a conversion from ScalarInt to char fails. +#[derive(Debug)] +pub struct CharTryFromScalarInt; + impl TryFrom for char { - type Error = Size; + type Error = CharTryFromScalarInt; + #[inline] - fn try_from(int: ScalarInt) -> Result { - int.to_bits(Size::from_bytes(std::mem::size_of::())) - .map(|u| char::from_u32(u.try_into().unwrap()).unwrap()) + fn try_from(int: ScalarInt) -> Result { + let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::())) else { + return Err(CharTryFromScalarInt); + }; + match char::from_u32(bits.try_into().unwrap()) { + Some(c) => Ok(c), + None => Err(CharTryFromScalarInt), + } } } diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index ee6c3b5f36fd4..1b53318806f4d 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -5,39 +5,53 @@ let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11 let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12 let mut _2: std::option::Option>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11 - scope 1 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12 - debug x => _2; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - let mut _3: isize; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - scope 2 { - debug y => _4; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + let _3: main::Union; // in scope 0 at $DIR/invalid_constant.rs:22:9: 22:22 + scope 1 { + debug _invalid_char => _3; // in scope 1 at $DIR/invalid_constant.rs:22:9: 22:22 + } + scope 2 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12 + debug x => _2; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + let mut _4: isize; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + let _5: std::option::Option<()>; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + scope 3 { + debug y => _5; // in scope 3 at $DIR/invalid_constant.rs:16:5: 16:12 } } bb0: { discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11 -- _3 = discriminant(_2); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -- switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -+ _3 = const 0_isize; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 +- _4 = discriminant(_2); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 +- switchInt(move _4) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 ++ _4 = const 0_isize; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 ++ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 } bb1: { - nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2 - return; // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2 +- _3 = const { Union { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58 ++ _3 = const main::Union { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58 + // ty::Const + // + ty: main::Union +- // + val: Unevaluated(main::{constant#0}, [main::Union], None) ++ // + val: Value(Scalar(0x00110001)) + // mir::Constant + // + span: $DIR/invalid_constant.rs:22:25: 22:58 +- // + literal: Const { ty: main::Union, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ invalid_constant[726d]::main::{constant#0}), const_param_did: None }, substs: [main::Union], promoted: None }) } ++ // + literal: Const { ty: main::Union, val: Value(Scalar(0x00110001)) } + nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 23:2 + return; // scope 0 at $DIR/invalid_constant.rs:23:2: 23:2 } bb2: { -- _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -- _1 = _4; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 -+ _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 +- _5 = ((_2 as Some).0: std::option::Option<()>); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 +- _1 = _5; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12 ++ _5 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + // ty::Const + // + ty: std::option::Option<()> + // + val: Value(Scalar(0x02)) + // mir::Constant + // + span: $DIR/invalid_constant.rs:16:5: 16:12 + // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) } -+ _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 ++ _1 = const Scalar(0x02): Option::<()>; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12 + // ty::Const + // + ty: std::option::Option<()> + // + val: Value(Scalar(0x02)) @@ -48,7 +62,7 @@ } bb3: { - discriminant(_1) = 0; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 + discriminant(_1) = 0; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21 } } diff --git a/src/test/mir-opt/const_prop/invalid_constant.rs b/src/test/mir-opt/const_prop/invalid_constant.rs index 1eb6f37df5968..4aca90900199e 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.rs +++ b/src/test/mir-opt/const_prop/invalid_constant.rs @@ -2,7 +2,7 @@ // by constant propagation. Regression test for issue #93688. // // compile-flags: -Copt-level=0 -Zinline-mir - +#![feature(inline_const)] #[inline(always)] pub fn f(x: Option>) -> Option<()> { match x { @@ -14,4 +14,10 @@ pub fn f(x: Option>) -> Option<()> { // EMIT_MIR invalid_constant.main.ConstProp.diff fn main() { f(None); + + union Union { + int: u32, + chr: char, + } + let _invalid_char = const { Union { int: 0x110001 } }; } From a677e6084049ff4cb2e338d7e33dc034846cdb29 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 14 Jan 2022 20:28:04 +0100 Subject: [PATCH 14/14] Collections: improve the documentation of drain members --- library/alloc/src/collections/binary_heap.rs | 16 ++++++++++----- .../alloc/src/collections/vec_deque/mod.rs | 20 +++++++++++-------- library/alloc/src/string.rs | 17 +++++++++++----- library/alloc/src/vec/mod.rs | 19 +++++++++++------- library/std/src/collections/hash/map.rs | 4 ++++ library/std/src/collections/hash/set.rs | 7 ++++++- 6 files changed, 57 insertions(+), 26 deletions(-) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 56a4700181199..e18cd8cd46427 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -746,9 +746,12 @@ impl BinaryHeap { self.rebuild_tail(start); } - /// Returns an iterator which retrieves elements in heap order. - /// The retrieved elements are removed from the original heap. - /// The remaining elements will be removed on drop in heap order. + /// Clears the binary heap, returning an iterator over the removed elements + /// in heap order. If the iterator is dropped before being fully consumed, + /// it drops the remaining elements in heap order. + /// + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. /// /// Note: /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. @@ -1158,9 +1161,12 @@ impl BinaryHeap { self.len() == 0 } - /// Clears the binary heap, returning an iterator over the removed elements. + /// Clears the binary heap, returning an iterator over the removed elements + /// in arbitrary order. If the iterator is dropped before being fully + /// consumed, it drops the remaining elements in arbitrary order. /// - /// The elements are removed in arbitrary order. + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. /// /// # Examples /// diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 763175fc0451f..7139a0fb94d76 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1215,21 +1215,25 @@ impl VecDeque { unsafe { IterMut::new(ring, tail, head, PhantomData) } } - /// Creates a draining iterator that removes the specified range in the - /// deque and yields the removed items. + /// Removes the specified range from the deque in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// The returned iterator keeps a mutable borrow on the queue to optimize + /// its implementation. /// - /// Note 2: It is unspecified how many elements are removed from the deque, - /// if the `Drain` value is not dropped, but the borrow it holds expires - /// (e.g., due to `mem::forget`). /// /// # Panics /// /// Panics if the starting point is greater than the end point or if /// the end point is greater than the length of the deque. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the deque may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// /// # Examples /// /// ``` @@ -1240,7 +1244,7 @@ impl VecDeque { /// assert_eq!(drained, [3]); /// assert_eq!(deque, [1, 2]); /// - /// // A full range clears all contents + /// // A full range clears all contents, like `clear()` does /// deque.drain(..); /// assert!(deque.is_empty()); /// ``` diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 7c0faf0659a2c..716bb4983a651 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1628,17 +1628,24 @@ impl String { self.vec.clear() } - /// Creates a draining iterator that removes the specified range in the `String` - /// and yields the removed `chars`. + /// Removes the specified range from the string in bulk, returning all + /// removed characters as an iterator. /// - /// Note: The element range is removed even if the iterator is not - /// consumed until the end. + /// The returned iterator keeps a mutable borrow on the string to optimize + /// its implementation. /// /// # Panics /// /// Panics if the starting point or end point do not lie on a [`char`] /// boundary, or if they're out of bounds. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`core::mem::forget`], for example), the string may still contain a copy + /// of any drained characters, or may have lost characters arbitrarily, + /// including characters outside the range. + /// /// # Examples /// /// Basic usage: @@ -1652,7 +1659,7 @@ impl String { /// assert_eq!(t, "α is alpha, "); /// assert_eq!(s, "β is beta"); /// - /// // A full range clears the string + /// // A full range clears the string, like `clear()` does /// s.drain(..); /// assert_eq!(s, ""); /// ``` diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3dc3eee4133b6..c29aa0fec5b87 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1799,19 +1799,24 @@ impl Vec { self.len += count; } - /// Creates a draining iterator that removes the specified range in the vector - /// and yields the removed items. + /// Removes the specified range from the vector in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. /// - /// When the iterator **is** dropped, all elements in the range are removed - /// from the vector, even if the iterator was not fully consumed. If the - /// iterator **is not** dropped (with [`mem::forget`] for example), it is - /// unspecified how many elements are removed. + /// The returned iterator keeps a mutable borrow on the vector to optimize + /// its implementation. /// /// # Panics /// /// Panics if the starting point is greater than the end point or if /// the end point is greater than the length of the vector. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the vector may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// /// # Examples /// /// ``` @@ -1820,7 +1825,7 @@ impl Vec { /// assert_eq!(v, &[1]); /// assert_eq!(u, &[2, 3]); /// - /// // A full range clears the vector + /// // A full range clears the vector, like `clear()` does /// v.drain(..); /// assert_eq!(v, &[]); /// ``` diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9e61defc31e97..c9d91d2c03bf5 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -547,6 +547,10 @@ impl HashMap { /// Clears the map, returning all key-value pairs as an iterator. Keeps the /// allocated memory for reuse. /// + /// If the returned iterator is dropped before being fully consumed, it + /// drops the remaining key-value pairs. The returned iterator keeps a + /// mutable borrow on the vector to optimize its implementation. + /// /// # Examples /// /// ``` diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index d1450987e7374..200667ae39069 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -227,7 +227,12 @@ impl HashSet { self.base.is_empty() } - /// Clears the set, returning all elements in an iterator. + /// Clears the set, returning all elements as an iterator. Keeps the + /// allocated memory for reuse. + /// + /// If the returned iterator is dropped before being fully consumed, it + /// drops the remaining elements. The returned iterator keeps a mutable + /// borrow on the vector to optimize its implementation. /// /// # Examples ///