From 4ee18c94d4969a49b81b726260a093f3fd201070 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 22 Dec 2019 20:39:17 +0100 Subject: [PATCH 01/21] Clean up E0124 explanation --- src/librustc_error_codes/error_codes/E0124.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0124.md b/src/librustc_error_codes/error_codes/E0124.md index a7836526a7dd4..f08f7e9800551 100644 --- a/src/librustc_error_codes/error_codes/E0124.md +++ b/src/librustc_error_codes/error_codes/E0124.md @@ -1,5 +1,6 @@ -You declared two fields of a struct with the same name. Erroneous code -example: +A struct with two fields having the same name has been declared. + +Erroneous code example: ```compile_fail,E0124 struct Foo { From 1474d2a41a32f7f969c7d924ea917a1390ebe1c6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 22 Dec 2019 20:39:25 +0100 Subject: [PATCH 02/21] Clean up E0128 explanation --- src/librustc_error_codes/error_codes/E0128.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0128.md b/src/librustc_error_codes/error_codes/E0128.md index d0a4b32f9688e..6f8dfe3a73b9e 100644 --- a/src/librustc_error_codes/error_codes/E0128.md +++ b/src/librustc_error_codes/error_codes/E0128.md @@ -1,4 +1,5 @@ -Type parameter defaults can only use parameters that occur before them. +A type parameter with default value is using forward declared identifier. + Erroneous code example: ```compile_fail,E0128 @@ -7,11 +8,11 @@ struct Foo { field2: U, } // error: type parameters with a default cannot use forward declared -// identifiers +// identifiers ``` -Since type parameters are evaluated in-order, you may be able to fix this issue -by doing: +Type parameter defaults can only use parameters that occur before them. Since +type parameters are evaluated in-order, this issue could be fixed by doing: ``` struct Foo { From 101dd7bad9432730fa2f625ae43afcc2929457d4 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 05:13:46 +0900 Subject: [PATCH 03/21] Use `is_none` instead of `if let` --- src/librustc/traits/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b299fd6117e41..aabf1d625a8a8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2289,7 +2289,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = self.tcx.def_span(generator_did); // Do not ICE on closure typeck (#66868). - if let None = self.tcx.hir().as_local_hir_id(generator_did) { + if self.tcx.hir().as_local_hir_id(generator_did).is_none() { return false; } From 7c485ccfad968ba6fe226a59f9337adbc158dd6b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 07:35:18 +0900 Subject: [PATCH 04/21] Add test for issue-61747 --- src/test/ui/const-generics/issues/issue-61747.rs | 16 ++++++++++++++++ .../ui/const-generics/issues/issue-61747.stderr | 8 ++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-61747.rs create mode 100644 src/test/ui/const-generics/issues/issue-61747.stderr diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs new file mode 100644 index 0000000000000..cab87200b5022 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Const; + +impl Const<{C}> { + fn successor() -> Const<{C + 1}> { + Const + } +} + +fn main() { + Const::<1>::successor(); +} diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr new file mode 100644 index 0000000000000..ccf36a7f805ec --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61747.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + From 96253c2d15d5f9ed1e6e63a97ac5f705c8fc4421 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 07:36:02 +0900 Subject: [PATCH 05/21] Add test for issue-66205 --- src/test/ui/const-generics/issues/issue-66205.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-66205.rs diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs new file mode 100644 index 0000000000000..2e47b4d1882f2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-66205.rs @@ -0,0 +1,10 @@ +// check-pass + +#![allow(incomplete_features, dead_code, unconditional_recursion)] +#![feature(const_generics)] + +fn fact() { + fact::<{ N - 1 }>(); +} + +fn main() {} From 6ec3a63bb287d11849b2fc3546793437bbbbd865 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 07:36:30 +0900 Subject: [PATCH 06/21] Add test for issue-66270 --- .../issue-66270-pat-struct-parser-recovery.rs | 14 ++++++++++++++ .../issue-66270-pat-struct-parser-recovery.stderr | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs create mode 100644 src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs new file mode 100644 index 0000000000000..48a8e04829a0a --- /dev/null +++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.rs @@ -0,0 +1,14 @@ +// Regression test for #66270, fixed by #66246 + +struct Bug { + incorrect_field: 0, + //~^ ERROR expected type +} + +struct Empty {} + +fn main() { + let Bug { + any_field: Empty {}, + } = Bug {}; +} diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr new file mode 100644 index 0000000000000..fef0f3c0e06ef --- /dev/null +++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr @@ -0,0 +1,8 @@ +error: expected type, found `0` + --> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22 + | +LL | incorrect_field: 0, + | ^ expected type + +error: aborting due to previous error + From 256eec4ae0653e35cdd39261a2b59d69c91b1a71 Mon Sep 17 00:00:00 2001 From: Dylan DPC Date: Mon, 23 Dec 2019 12:55:33 +0530 Subject: [PATCH 07/21] Update E0124.md --- src/librustc_error_codes/error_codes/E0124.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0124.md b/src/librustc_error_codes/error_codes/E0124.md index f08f7e9800551..8af7cb819cfaf 100644 --- a/src/librustc_error_codes/error_codes/E0124.md +++ b/src/librustc_error_codes/error_codes/E0124.md @@ -1,4 +1,4 @@ -A struct with two fields having the same name has been declared. +A struct was declared with two fields having the same name. Erroneous code example: From 1485c168990b2dbb6e2858bc09af0254c1af9491 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Mon, 23 Dec 2019 21:05:02 +0800 Subject: [PATCH 08/21] Add long error code explanation message for E0627 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0627.md | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0627.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 9c1bec39b29e2..fbcc976bd491e 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -346,6 +346,7 @@ E0622: include_str!("./error_codes/E0622.md"), E0623: include_str!("./error_codes/E0623.md"), E0624: include_str!("./error_codes/E0624.md"), E0626: include_str!("./error_codes/E0626.md"), +E0627: include_str!("./error_codes/E0627.md"), E0631: include_str!("./error_codes/E0631.md"), E0633: include_str!("./error_codes/E0633.md"), E0635: include_str!("./error_codes/E0635.md"), @@ -574,7 +575,6 @@ E0745: include_str!("./error_codes/E0745.md"), // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0625, // thread-local statics cannot be accessed at compile-time - E0627, // yield statement outside of generator literal E0628, // generators cannot have explicit parameters E0629, // missing 'feature' (rustc_const_unstable) // rustc_const_unstable attribute must be paired with stable/unstable diff --git a/src/librustc_error_codes/error_codes/E0627.md b/src/librustc_error_codes/error_codes/E0627.md new file mode 100644 index 0000000000000..21358e1e567dc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0627.md @@ -0,0 +1,30 @@ +A yield expression was used outside of the generator literal. + +Erroneous code example: + +```compile_fail,E0627 +#![feature(generators, generator_trait)] + +fn fake_generator() -> &'static str { + yield 1; + return "foo" +} + +fn main() { + let mut generator = fake_generator; +} +``` + +The error occurs because keyword `yield` can only be used inside the generator +literal. This can be fixed by constructing the generator correctly. + +``` +#![feature(generators, generator_trait)] + +fn main() { + let mut generator = || { + yield 1; + return "foo" + }; +} +``` From 587d03bea89b2b551633aa561073ba97409a5dac Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Mon, 23 Dec 2019 21:07:13 +0800 Subject: [PATCH 09/21] Yield is an expression form, not a statement. --- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/path_utils.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- src/test/ui/feature-gates/feature-gate-generators.rs | 2 +- src/test/ui/feature-gates/feature-gate-generators.stderr | 5 +++-- src/test/ui/generator/yield-in-const.rs | 2 +- src/test/ui/generator/yield-in-const.stderr | 3 ++- src/test/ui/generator/yield-in-function.rs | 2 +- src/test/ui/generator/yield-in-function.stderr | 3 ++- src/test/ui/generator/yield-in-static.rs | 2 +- src/test/ui/generator/yield-in-static.stderr | 3 ++- 11 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4a6379e3bc155..0d136bd7d9cf9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1424,7 +1424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// Reports an error if this is a borrow of local data. - /// This is called for all Yield statements on movable generators + /// This is called for all Yield expressions on movable generators fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span) { debug!("check_for_local_borrow({:?})", borrow); diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index ea541bd93bc94..23b4799643a6c 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -131,7 +131,7 @@ pub(super) fn is_active<'tcx>( } /// Determines if a given borrow is borrowing local data -/// This is called for all Yield statements on movable generators +/// This is called for all Yield expressions on movable generators pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool { match place.base { PlaceBase::Static(_) => false, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 6ecf3ccd6e7ed..479536a1c8f01 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1775,7 +1775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess, expr.span, E0627, - "yield statement outside of generator literal" + "yield expression outside of generator literal" ) .emit(); } diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs index 382d891feed84..931fee1347126 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.rs +++ b/src/test/ui/feature-gates/feature-gate-generators.rs @@ -1,6 +1,6 @@ fn main() { yield true; //~ ERROR yield syntax is experimental - //~^ ERROR yield statement outside of generator literal + //~^ ERROR yield expression outside of generator literal } #[cfg(FALSE)] diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr index 24b814b410c9d..4adc21efc6a21 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.stderr +++ b/src/test/ui/feature-gates/feature-gate-generators.stderr @@ -25,7 +25,7 @@ LL | yield 0; = note: for more information, see https://github.com/rust-lang/rust/issues/43122 = help: add `#![feature(generators)]` to the crate attributes to enable -error[E0627]: yield statement outside of generator literal +error[E0627]: yield expression outside of generator literal --> $DIR/feature-gate-generators.rs:2:5 | LL | yield true; @@ -33,4 +33,5 @@ LL | yield true; error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0627, E0658. +For more information about an error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-in-const.rs b/src/test/ui/generator/yield-in-const.rs index f6f11b9cb13dd..fe5ca822ceca1 100644 --- a/src/test/ui/generator/yield-in-const.rs +++ b/src/test/ui/generator/yield-in-const.rs @@ -1,6 +1,6 @@ #![feature(generators)] const A: u8 = { yield 3u8; 3u8}; -//~^ ERROR yield statement outside +//~^ ERROR yield expression outside fn main() {} diff --git a/src/test/ui/generator/yield-in-const.stderr b/src/test/ui/generator/yield-in-const.stderr index 663bb70d7a07f..dcf4fe63e64bc 100644 --- a/src/test/ui/generator/yield-in-const.stderr +++ b/src/test/ui/generator/yield-in-const.stderr @@ -1,4 +1,4 @@ -error[E0627]: yield statement outside of generator literal +error[E0627]: yield expression outside of generator literal --> $DIR/yield-in-const.rs:3:17 | LL | const A: u8 = { yield 3u8; 3u8}; @@ -6,3 +6,4 @@ LL | const A: u8 = { yield 3u8; 3u8}; error: aborting due to previous error +For more information about this error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-in-function.rs b/src/test/ui/generator/yield-in-function.rs index b737d3b224035..29b811621de1e 100644 --- a/src/test/ui/generator/yield-in-function.rs +++ b/src/test/ui/generator/yield-in-function.rs @@ -1,4 +1,4 @@ #![feature(generators)] fn main() { yield; } -//~^ ERROR yield statement outside +//~^ ERROR yield expression outside diff --git a/src/test/ui/generator/yield-in-function.stderr b/src/test/ui/generator/yield-in-function.stderr index e12b0e6843e41..51cce198ca3b4 100644 --- a/src/test/ui/generator/yield-in-function.stderr +++ b/src/test/ui/generator/yield-in-function.stderr @@ -1,4 +1,4 @@ -error[E0627]: yield statement outside of generator literal +error[E0627]: yield expression outside of generator literal --> $DIR/yield-in-function.rs:3:13 | LL | fn main() { yield; } @@ -6,3 +6,4 @@ LL | fn main() { yield; } error: aborting due to previous error +For more information about this error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-in-static.rs b/src/test/ui/generator/yield-in-static.rs index 12c9ccea4cb78..d27fbb33ba10a 100644 --- a/src/test/ui/generator/yield-in-static.rs +++ b/src/test/ui/generator/yield-in-static.rs @@ -1,6 +1,6 @@ #![feature(generators)] static B: u8 = { yield 3u8; 3u8}; -//~^ ERROR yield statement outside +//~^ ERROR yield expression outside fn main() {} diff --git a/src/test/ui/generator/yield-in-static.stderr b/src/test/ui/generator/yield-in-static.stderr index 220520c3862ca..d867f3ad34528 100644 --- a/src/test/ui/generator/yield-in-static.stderr +++ b/src/test/ui/generator/yield-in-static.stderr @@ -1,4 +1,4 @@ -error[E0627]: yield statement outside of generator literal +error[E0627]: yield expression outside of generator literal --> $DIR/yield-in-static.rs:3:18 | LL | static B: u8 = { yield 3u8; 3u8}; @@ -6,3 +6,4 @@ LL | static B: u8 = { yield 3u8; 3u8}; error: aborting due to previous error +For more information about this error, try `rustc --explain E0627`. From 640e2884ad9d3c7bec74444bba922108e4347634 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 16 Dec 2019 15:23:26 +0100 Subject: [PATCH 10/21] Panic on mutable allocs in constants --- src/librustc_mir/interpret/intern.rs | 21 +++++++++++----- .../consts/miri_unleashed/mutable_const2.rs | 19 ++++++++++++++ .../miri_unleashed/mutable_const2.stderr | 25 +++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/miri_unleashed/mutable_const2.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_const2.stderr diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index c99f39977fe2e..5b19f879389f4 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -320,12 +320,19 @@ pub fn intern_const_alloc_recursive>( // We can't call the `intern_shallow` method here, as its logic is tailored to safe // references and a `leftover_allocations` set (where we only have a todo-list here). // So we hand-roll the interning logic here again. - if base_intern_mode != InternMode::Static { - // If it's not a static, it *must* be immutable. - // We cannot have mutable memory inside a constant. - // FIXME: ideally we would assert that they already are immutable, to double- - // check our static checks. - alloc.mutability = Mutability::Not; + match base_intern_mode { + InternMode::Static => {} + InternMode::Const | InternMode::ConstBase => { + // If it's not a static, it *must* be immutable. + // We cannot have mutable memory inside a constant. + // We use `delay_span_bug` here, because this can be reached in the presence + // of fancy transmutes. + if alloc.mutability == Mutability::Mut { + // For better errors later, mark the allocation as immutable + alloc.mutability = Mutability::Not; + ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant"); + } + } } let alloc = tcx.intern_const_alloc(alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); @@ -337,6 +344,8 @@ pub fn intern_const_alloc_recursive>( } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // dangling pointer throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) + } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() { + span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id); } } Ok(()) diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs new file mode 100644 index 0000000000000..97af1f2f993c3 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + +#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] +#![deny(const_err)] + +use std::cell::UnsafeCell; + +// make sure we do not just intern this as mutable +const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; +//~^ WARN: skipping const checks +//~| ERROR: mutable allocation in constant + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr new file mode 100644 index 0000000000000..3493b7c54c43b --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -0,0 +1,25 @@ +warning: skipping const checks + --> $DIR/mutable_const2.rs:15:38 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^ + +error: internal compiler error: mutable allocation in constant + --> $DIR/mutable_const2.rs:15:1 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc VERSION running on TARGET + +note: compiler flags: FLAGS + From ad6b9c79d63c3049f1ceb4a0ab0fa101c13de121 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 16 Dec 2019 15:23:42 +0100 Subject: [PATCH 11/21] Dynamically prevent constants from accessing statics --- src/librustc_mir/const_eval.rs | 52 +++++++++++---- src/librustc_mir/interpret/intern.rs | 1 - src/librustc_mir/interpret/machine.rs | 5 +- src/librustc_mir/interpret/memory.rs | 7 ++- src/librustc_mir/transform/const_prop.rs | 1 + src/test/ui/consts/const-points-to-static.rs | 12 ++++ .../ui/consts/const-points-to-static.stderr | 17 +++++ .../consts/const-prop-read-static-in-const.rs | 3 +- .../const-prop-read-static-in-const.stderr | 14 ++++- .../miri_unleashed/const_refers_to_static.rs | 38 +++++++++++ .../const_refers_to_static.stderr | 63 +++++++++++++++++++ src/test/ui/issues/issue-52060.rs | 1 + src/test/ui/issues/issue-52060.stderr | 11 +++- 13 files changed, 203 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/consts/const-points-to-static.rs create mode 100644 src/test/ui/consts/const-points-to-static.stderr create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static.rs create mode 100644 src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index a2f066bee08d1..3ea76fab6dd35 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -45,9 +45,15 @@ fn mk_eval_cx<'mir, 'tcx>( tcx: TyCtxt<'tcx>, span: Span, param_env: ty::ParamEnv<'tcx>, + can_access_statics: bool, ) -> CompileTimeEvalContext<'mir, 'tcx> { debug!("mk_eval_cx: {:?}", param_env); - InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default()) + InterpCx::new( + tcx.at(span), + param_env, + CompileTimeInterpreter::new(), + MemoryExtra { can_access_statics }, + ) } fn op_to_const<'tcx>( @@ -224,6 +230,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>, } +#[derive(Copy, Clone, Debug)] +pub struct MemoryExtra { + /// Whether this machine may read from statics + can_access_statics: bool, +} + impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { fn new() -> Self { CompileTimeInterpreter { @@ -311,7 +323,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type ExtraFnVal = !; type FrameExtra = (); - type MemoryExtra = (); + type MemoryExtra = MemoryExtra; type AllocExtra = (); type MemoryMap = FxHashMap, Allocation)>; @@ -473,7 +485,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, #[inline(always)] fn init_allocation_extra<'b>( - _memory_extra: &(), + _memory_extra: &MemoryExtra, _id: AllocId, alloc: Cow<'b, Allocation>, _kind: Option>, @@ -484,7 +496,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, #[inline(always)] fn tag_static_base_pointer( - _memory_extra: &(), + _memory_extra: &MemoryExtra, _id: AllocId, ) -> Self::PointerTag { () @@ -527,6 +539,19 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { Ok(()) } + + fn before_access_static( + memory_extra: &MemoryExtra, + _allocation: &Allocation, + ) -> InterpResult<'tcx> { + if memory_extra.can_access_statics { + Ok(()) + } else { + Err(ConstEvalError::NeedsRfc( + "constants accessing static items".to_string(), + ).into()) + } + } } /// Extracts a field of a (variant of a) const. @@ -540,7 +565,7 @@ pub fn const_field<'tcx>( value: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> { trace!("const_field: {:?}, {:?}", field, value); - let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); // get the operand again let op = ecx.eval_const_to_op(value, None).unwrap(); // downcast @@ -560,7 +585,7 @@ pub fn const_caller_location<'tcx>( (file, line, col): (Symbol, u32, u32), ) -> &'tcx ty::Const<'tcx> { trace!("const_caller_location: {}:{}:{}", file, line, col); - let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all()); + let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); let loc_ty = tcx.caller_location_ty(); let loc_place = ecx.alloc_caller_location(file, line, col); @@ -581,7 +606,7 @@ pub fn const_variant_index<'tcx>( val: &'tcx ty::Const<'tcx>, ) -> VariantIdx { trace!("const_variant_index: {:?}", val); - let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); let op = ecx.eval_const_to_op(val, None).unwrap(); ecx.read_discriminant(op).unwrap().1 } @@ -610,7 +635,9 @@ fn validate_and_turn_into_const<'tcx>( key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { let cid = key.value; - let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env); + let def_id = cid.instance.def.def_id(); + let is_static = tcx.is_static(def_id); + let ecx = mk_eval_cx(tcx, tcx.def_span(key.value.instance.def_id()), key.param_env, is_static); let val = (|| { let mplace = ecx.raw_const_to_mplace(constant)?; let mut ref_tracking = RefTracking::new(mplace); @@ -624,8 +651,7 @@ fn validate_and_turn_into_const<'tcx>( // Now that we validated, turn this into a proper constant. // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides // whether they become immediates. - let def_id = cid.instance.def.def_id(); - if tcx.is_static(def_id) || cid.promoted.is_some() { + if is_static || cid.promoted.is_some() { let ptr = mplace.ptr.to_ptr()?; Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(ConstValue::ByRef { @@ -732,12 +758,14 @@ pub fn const_eval_raw_provider<'tcx>( return Err(ErrorHandled::Reported); } + let is_static = tcx.is_static(def_id); + let span = tcx.def_span(cid.instance.def_id()); let mut ecx = InterpCx::new( tcx.at(span), key.param_env, CompileTimeInterpreter::new(), - Default::default() + MemoryExtra { can_access_statics: is_static }, ); let res = ecx.load_mir(cid.instance.def, cid.promoted); @@ -751,7 +779,7 @@ pub fn const_eval_raw_provider<'tcx>( }).map_err(|error| { let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors - if tcx.is_static(def_id) { + if is_static { // Ensure that if the above error was either `TooGeneric` or `Reported` // an error must be reported. let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 5b19f879389f4..1562a51831601 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -20,7 +20,6 @@ pub trait CompileTimeMachine<'mir, 'tcx> = Machine< PointerTag = (), ExtraFnVal = !, FrameExtra = (), - MemoryExtra = (), AllocExtra = (), MemoryMap = FxHashMap, Allocation)>, >; diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 32de01d92086e..e77ba9fa4cb0d 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -212,7 +212,10 @@ pub trait Machine<'mir, 'tcx>: Sized { } /// Called before a `StaticKind::Static` value is accessed. - fn before_access_static(_allocation: &Allocation) -> InterpResult<'tcx> { + fn before_access_static( + _memory_extra: &Self::MemoryExtra, + _allocation: &Allocation, + ) -> InterpResult<'tcx> { Ok(()) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0ba79e4bba239..71e6d3e8ca1fc 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -116,7 +116,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> // carefully copy only the reachable parts. impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M> where - M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = (), MemoryExtra = ()>, + M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = ()>, + M::MemoryExtra: Copy, M::MemoryMap: AllocMap, Allocation)>, { fn clone(&self) -> Self { @@ -124,7 +125,7 @@ where alloc_map: self.alloc_map.clone(), extra_fn_ptr_map: self.extra_fn_ptr_map.clone(), dead_alloc_map: self.dead_alloc_map.clone(), - extra: (), + extra: self.extra, tcx: self.tcx, } } @@ -455,7 +456,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let id = raw_const.alloc_id; let allocation = tcx.alloc_map.lock().unwrap_memory(id); - M::before_access_static(allocation)?; + M::before_access_static(memory_extra, allocation)?; Cow::Borrowed(allocation) } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index c36cdc9832391..a6b30ab5e68cf 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -224,6 +224,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { } fn before_access_static( + _memory_extra: &(), allocation: &Allocation, ) -> InterpResult<'tcx> { // if the static allocation is mutable or if it has relocations (it may be legal to mutate diff --git a/src/test/ui/consts/const-points-to-static.rs b/src/test/ui/consts/const-points-to-static.rs new file mode 100644 index 0000000000000..b998b7a97be4e --- /dev/null +++ b/src/test/ui/consts/const-points-to-static.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +#![allow(dead_code)] + +const TEST: &u8 = &MY_STATIC; +//~^ skipping const checks +//~| it is undefined behavior to use this value + +static MY_STATIC: u8 = 4; + +fn main() { +} diff --git a/src/test/ui/consts/const-points-to-static.stderr b/src/test/ui/consts/const-points-to-static.stderr new file mode 100644 index 0000000000000..5ebd643b39db8 --- /dev/null +++ b/src/test/ui/consts/const-points-to-static.stderr @@ -0,0 +1,17 @@ +warning: skipping const checks + --> $DIR/const-points-to-static.rs:5:20 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-points-to-static.rs:5:1 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "constants accessing static items" needs an rfc before being allowed inside constants + | + = 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. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-prop-read-static-in-const.rs b/src/test/ui/consts/const-prop-read-static-in-const.rs index 7504fd525955a..14ec064e4ceef 100644 --- a/src/test/ui/consts/const-prop-read-static-in-const.rs +++ b/src/test/ui/consts/const-prop-read-static-in-const.rs @@ -1,9 +1,8 @@ // compile-flags: -Zunleash-the-miri-inside-of-you -// run-pass #![allow(dead_code)] -const TEST: u8 = MY_STATIC; +const TEST: u8 = MY_STATIC; //~ ERROR any use of this value will cause an error //~^ skipping const checks static MY_STATIC: u8 = 4; diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr index bbd5b12ed7dfc..993cf455aba32 100644 --- a/src/test/ui/consts/const-prop-read-static-in-const.stderr +++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr @@ -1,6 +1,18 @@ warning: skipping const checks - --> $DIR/const-prop-read-static-in-const.rs:6:18 + --> $DIR/const-prop-read-static-in-const.rs:5:18 | LL | const TEST: u8 = MY_STATIC; | ^^^^^^^^^ +error: any use of this value will cause an error + --> $DIR/const-prop-read-static-in-const.rs:5:18 + | +LL | const TEST: u8 = MY_STATIC; + | -----------------^^^^^^^^^- + | | + | "constants accessing static items" needs an rfc before being allowed inside constants + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs new file mode 100644 index 0000000000000..58eac59ba384d --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -0,0 +1,38 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![allow(const_err)] + +#![feature(const_raw_ptr_deref)] + +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +const BOO: &usize = { //~ ERROR undefined behavior to use this value + static FOO: AtomicUsize = AtomicUsize::new(0); + unsafe { &*(&FOO as *const _ as *const usize) } + //~^ WARN skipping const checks +}; + +const FOO: usize = { + static FOO: AtomicUsize = AtomicUsize::new(0); + FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error + //~^ WARN skipping const checks + //~| WARN skipping const checks +}; + +const BAR: usize = { + static FOO: AtomicUsize = AtomicUsize::new(0); + unsafe { *(&FOO as *const _ as *const usize) } // FIXME: this should error + //~^ WARN skipping const checks +}; + +static mut MUTABLE: u32 = 0; +const BAD: u32 = unsafe { MUTABLE }; // FIXME: this should error +//~^ WARN skipping const checks + +// ok some day perhaps +const BOO_OK: &usize = { //~ ERROR it is undefined behavior to use this value + static FOO: usize = 0; + &FOO + //~^ WARN skipping const checks +}; +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr new file mode 100644 index 0000000000000..044a5232e5a24 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -0,0 +1,63 @@ +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:11:18 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:17:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error + | ^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:17:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:24:17 + | +LL | unsafe { *(&FOO as *const _ as *const usize) } // FIXME: this should error + | ^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:29:27 + | +LL | const BAD: u32 = unsafe { MUTABLE }; // FIXME: this should error + | ^^^^^^^ + +warning: skipping const checks + --> $DIR/const_refers_to_static.rs:35:6 + | +LL | &FOO + | ^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:9:1 + | +LL | / const BOO: &usize = { +LL | | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | | unsafe { &*(&FOO as *const _ as *const usize) } +LL | | +LL | | }; + | |__^ "constants accessing static items" needs an rfc before being allowed inside constants + | + = 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. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:33:1 + | +LL | / const BOO_OK: &usize = { +LL | | static FOO: usize = 0; +LL | | &FOO +LL | | +LL | | }; + | |__^ "constants accessing static items" needs an rfc before being allowed inside constants + | + = 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. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs index 13b914c0331d1..fed08902c8b9d 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/issues/issue-52060.rs @@ -3,5 +3,6 @@ static A: &'static [u32] = &[1]; static B: [u32; 1] = [0; A.len()]; //~^ ERROR [E0013] +//~| ERROR evaluation of constant value failed fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 2f90f7f9e035b..0b54b31abec9c 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -4,6 +4,13 @@ error[E0013]: constants cannot refer to statics, use a constant instead LL | static B: [u32; 1] = [0; A.len()]; | ^ -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/issue-52060.rs:4:26 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^ "constants accessing static items" needs an rfc before being allowed inside constants + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0013`. +Some errors have detailed explanations: E0013, E0080. +For more information about an error, try `rustc --explain E0013`. From 2022fac4df5830a1a346f0174f189cc2894f7229 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 22 Dec 2019 21:40:00 +0100 Subject: [PATCH 12/21] Constants reading or referencing statics is illegal and some uses of it will be illegal forever (e.g. mutable or interior mutable statics) --- src/librustc_mir/const_eval.rs | 7 ++++--- src/test/ui/consts/const-points-to-static.stderr | 2 +- src/test/ui/consts/const-prop-read-static-in-const.stderr | 2 +- .../ui/consts/miri_unleashed/const_refers_to_static.stderr | 4 ++-- src/test/ui/issues/issue-52060.stderr | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 3ea76fab6dd35..4fa4e87e0ffb1 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -182,6 +182,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( #[derive(Clone, Debug)] pub enum ConstEvalError { NeedsRfc(String), + ConstAccessesStatic, } impl<'tcx> Into> for ConstEvalError { @@ -201,6 +202,7 @@ impl fmt::Display for ConstEvalError { msg ) } + ConstAccessesStatic => write!(f, "constant accesses static"), } } } @@ -210,6 +212,7 @@ impl Error for ConstEvalError { use self::ConstEvalError::*; match *self { NeedsRfc(_) => "this feature needs an rfc before being allowed inside constants", + ConstAccessesStatic => "constant accesses static", } } @@ -547,9 +550,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, if memory_extra.can_access_statics { Ok(()) } else { - Err(ConstEvalError::NeedsRfc( - "constants accessing static items".to_string(), - ).into()) + Err(ConstEvalError::ConstAccessesStatic.into()) } } } diff --git a/src/test/ui/consts/const-points-to-static.stderr b/src/test/ui/consts/const-points-to-static.stderr index 5ebd643b39db8..8949358e29333 100644 --- a/src/test/ui/consts/const-points-to-static.stderr +++ b/src/test/ui/consts/const-points-to-static.stderr @@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:5:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "constants accessing static items" needs an rfc before being allowed inside constants + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static | = 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. diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr index 993cf455aba32..bfaa0f934ade2 100644 --- a/src/test/ui/consts/const-prop-read-static-in-const.stderr +++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr @@ -10,7 +10,7 @@ error: any use of this value will cause an error LL | const TEST: u8 = MY_STATIC; | -----------------^^^^^^^^^- | | - | "constants accessing static items" needs an rfc before being allowed inside constants + | constant accesses static | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 044a5232e5a24..7a8c9d44e5a0b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -42,7 +42,7 @@ LL | | static FOO: AtomicUsize = AtomicUsize::new(0); LL | | unsafe { &*(&FOO as *const _ as *const usize) } LL | | LL | | }; - | |__^ "constants accessing static items" needs an rfc before being allowed inside constants + | |__^ constant accesses static | = 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. @@ -54,7 +54,7 @@ LL | | static FOO: usize = 0; LL | | &FOO LL | | LL | | }; - | |__^ "constants accessing static items" needs an rfc before being allowed inside constants + | |__^ constant accesses static | = 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. diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 0b54b31abec9c..c69145c1fe833 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -8,7 +8,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-52060.rs:4:26 | LL | static B: [u32; 1] = [0; A.len()]; - | ^ "constants accessing static items" needs an rfc before being allowed inside constants + | ^ constant accesses static error: aborting due to 2 previous errors From e56a86162ceeb285c48132a103a6559f4d406ba7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 22 Dec 2019 21:42:50 +0100 Subject: [PATCH 13/21] Show `const_err` lints --- .../miri_unleashed/const_refers_to_static.rs | 8 ++-- .../const_refers_to_static.stderr | 45 +++++++++++++++++-- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs index 58eac59ba384d..55f3f1c848855 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -1,5 +1,5 @@ // compile-flags: -Zunleash-the-miri-inside-of-you -#![allow(const_err)] +#![warn(const_err)] #![feature(const_raw_ptr_deref)] @@ -14,19 +14,19 @@ const BOO: &usize = { //~ ERROR undefined behavior to use this value const FOO: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); - FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error + FOO.fetch_add(1, Ordering::Relaxed) //~ WARN any use of this value will cause an error //~^ WARN skipping const checks //~| WARN skipping const checks }; const BAR: usize = { static FOO: AtomicUsize = AtomicUsize::new(0); - unsafe { *(&FOO as *const _ as *const usize) } // FIXME: this should error + unsafe { *(&FOO as *const _ as *const usize) } //~ WARN any use of this value will cause an err //~^ WARN skipping const checks }; static mut MUTABLE: u32 = 0; -const BAD: u32 = unsafe { MUTABLE }; // FIXME: this should error +const BAD: u32 = unsafe { MUTABLE }; //~ WARN any use of this value will cause an error //~^ WARN skipping const checks // ok some day perhaps diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 7a8c9d44e5a0b..6ae88558d7003 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -7,25 +7,25 @@ LL | unsafe { &*(&FOO as *const _ as *const usize) } warning: skipping const checks --> $DIR/const_refers_to_static.rs:17:5 | -LL | FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error +LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^ warning: skipping const checks --> $DIR/const_refers_to_static.rs:17:5 | -LL | FOO.fetch_add(1, Ordering::Relaxed) // FIXME: this should error +LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: skipping const checks --> $DIR/const_refers_to_static.rs:24:17 | -LL | unsafe { *(&FOO as *const _ as *const usize) } // FIXME: this should error +LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^ warning: skipping const checks --> $DIR/const_refers_to_static.rs:29:27 | -LL | const BAD: u32 = unsafe { MUTABLE }; // FIXME: this should error +LL | const BAD: u32 = unsafe { MUTABLE }; | ^^^^^^^ warning: skipping const checks @@ -46,6 +46,43 @@ 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. +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static.rs:17:5 + | +LL | / const FOO: usize = { +LL | | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | | FOO.fetch_add(1, Ordering::Relaxed) + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `std::sync::atomic::AtomicUsize::fetch_add` +LL | | +LL | | +LL | | }; + | |__- + | +note: lint level defined here + --> $DIR/const_refers_to_static.rs:2:9 + | +LL | #![warn(const_err)] + | ^^^^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static.rs:24:14 + | +LL | / const BAR: usize = { +LL | | static FOO: AtomicUsize = AtomicUsize::new(0); +LL | | unsafe { *(&FOO as *const _ as *const usize) } + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static +LL | | +LL | | }; + | |__- + +warning: any use of this value will cause an error + --> $DIR/const_refers_to_static.rs:29:27 + | +LL | const BAD: u32 = unsafe { MUTABLE }; + | --------------------------^^^^^^^--- + | | + | constant accesses static + error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static.rs:33:1 | From 89250b97f578d75df33cb049d1cba2640fbc46d9 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Dec 2019 14:50:34 +0100 Subject: [PATCH 14/21] Update src/librustc_mir/interpret/intern.rs Co-Authored-By: Ralf Jung --- src/librustc_mir/interpret/intern.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 1562a51831601..b3231ece63683 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -327,7 +327,7 @@ pub fn intern_const_alloc_recursive>( // We use `delay_span_bug` here, because this can be reached in the presence // of fancy transmutes. if alloc.mutability == Mutability::Mut { - // For better errors later, mark the allocation as immutable + // For better errors later, mark the allocation as immutable (on top of the delayed ICE). alloc.mutability = Mutability::Not; ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant"); } From 75bdd95d4e3b9d80d536aed963676d3e8af691a5 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Dec 2019 15:22:36 +0100 Subject: [PATCH 15/21] Tidy --- src/librustc_mir/interpret/intern.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index b3231ece63683..b53741e9e43ff 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -327,7 +327,8 @@ pub fn intern_const_alloc_recursive>( // We use `delay_span_bug` here, because this can be reached in the presence // of fancy transmutes. if alloc.mutability == Mutability::Mut { - // For better errors later, mark the allocation as immutable (on top of the delayed ICE). + // For better errors later, mark the allocation as immutable + // (on top of the delayed ICE). alloc.mutability = Mutability::Not; ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant"); } From 24f3dcfdc741aaab0f1e56127455143912bc9203 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Mon, 23 Dec 2019 09:47:28 -0600 Subject: [PATCH 16/21] remove `description` from `Error` impls in docs --- src/libstd/error.rs | 32 ++++---------------------------- src/libstd/io/error.rs | 4 +--- 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index d4c4cb9c3b997..f62c05c444115 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -91,10 +91,6 @@ pub trait Error: Debug + Display { /// } /// /// impl Error for SuperError { - /// fn description(&self) -> &str { - /// "I'm the superhero of errors" - /// } - /// /// fn cause(&self) -> Option<&dyn Error> { /// Some(&self.side) /// } @@ -109,11 +105,7 @@ pub trait Error: Debug + Display { /// } /// } /// - /// impl Error for SuperErrorSideKick { - /// fn description(&self) -> &str { - /// "I'm SuperError side kick" - /// } - /// } + /// impl Error for SuperErrorSideKick {} /// /// fn get_super_error() -> Result<(), SuperError> { /// Err(SuperError { side: SuperErrorSideKick }) @@ -156,10 +148,6 @@ pub trait Error: Debug + Display { /// } /// /// impl Error for SuperError { - /// fn description(&self) -> &str { - /// "I'm the superhero of errors" - /// } - /// /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// Some(&self.side) /// } @@ -174,11 +162,7 @@ pub trait Error: Debug + Display { /// } /// } /// - /// impl Error for SuperErrorSideKick { - /// fn description(&self) -> &str { - /// "I'm SuperError side kick" - /// } - /// } + /// impl Error for SuperErrorSideKick {} /// /// fn get_super_error() -> Result<(), SuperError> { /// Err(SuperError { side: SuperErrorSideKick }) @@ -251,11 +235,7 @@ impl<'a, E: Error + 'a> From for Box { /// } /// } /// - /// impl Error for AnError { - /// fn description(&self) -> &str { - /// "Description of an error" - /// } - /// } + /// impl Error for AnError {} /// /// let an_error = AnError; /// assert!(0 == mem::size_of_val(&an_error)); @@ -290,11 +270,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box &str { - /// "Description of an error" - /// } - /// } + /// impl Error for AnError {} /// /// unsafe impl Send for AnError {} /// diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index c20bd3097b27d..efe839d1302fe 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -402,9 +402,7 @@ impl Error { /// } /// } /// - /// impl error::Error for MyError { - /// fn description(&self) -> &str { &self.v } - /// } + /// impl error::Error for MyError {} /// /// impl Display for MyError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { From 1f2fa939a5536eeff86c0ea6b7ebde538a582ad4 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 07:37:16 +0900 Subject: [PATCH 17/21] Add test for issue-67424 --- .../generic-associated-types/issue-67424.rs | 13 ++++++++++++ .../issue-67424.stderr | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/ui/generic-associated-types/issue-67424.rs create mode 100644 src/test/ui/generic-associated-types/issue-67424.stderr diff --git a/src/test/ui/generic-associated-types/issue-67424.rs b/src/test/ui/generic-associated-types/issue-67424.rs new file mode 100644 index 0000000000000..9b616b8abc2ee --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.rs @@ -0,0 +1,13 @@ +// Fixed by #67160 + +trait Trait1 { + type A; +} + +trait Trait2 { + type Type1: Trait1; + //~^ ERROR: generic associated types are unstable + //~| ERROR: type-generic associated types are not yet implemented +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-67424.stderr b/src/test/ui/generic-associated-types/issue-67424.stderr new file mode 100644 index 0000000000000..59ff8ac0a3a70 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-67424.stderr @@ -0,0 +1,20 @@ +error[E0658]: generic associated types are unstable + --> $DIR/issue-67424.rs:8:5 + | +LL | type Type1: Trait1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44265 + = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable + +error: type-generic associated types are not yet implemented + --> $DIR/issue-67424.rs:8:5 + | +LL | type Type1: Trait1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44265 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From d918319bed23b418a98720688a3f59904aada978 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 23 Dec 2019 08:24:11 +0900 Subject: [PATCH 18/21] Apply suggestion from Centril Co-Authored-By: Mazdak Farrokhzad --- src/test/ui/const-generics/issues/issue-61747.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs index cab87200b5022..64674bb894e1f 100644 --- a/src/test/ui/const-generics/issues/issue-61747.rs +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -12,5 +12,5 @@ impl Const<{C}> { } fn main() { - Const::<1>::successor(); + let _x: Const::<2> = Const::<1>::successor(); } From 87fea048714913ae21581446a015a3c98ebc9d53 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Dec 2019 17:48:22 +0100 Subject: [PATCH 19/21] Bless tests --- src/test/ui/consts/miri_unleashed/mutable_const2.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index 3493b7c54c43b..2b4e23cd46e81 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:349:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic From cefeb663666de29b42a4c233bee14793712613ae Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Mon, 23 Dec 2019 23:31:39 +0000 Subject: [PATCH 20/21] Use the chocolatey CDN directly to avoid the flaky API --- src/ci/scripts/install-msys2.sh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh index 3a78ef209e4e5..9e899ba9d8947 100755 --- a/src/ci/scripts/install-msys2.sh +++ b/src/ci/scripts/install-msys2.sh @@ -12,10 +12,14 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isWindows; then - for RETRY_COUNT in 1 2 3 4 5 6 7 8 9 10; do - choco install msys2 \ - --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress \ - && mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" \ - && ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" && break - done + # Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey + curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \ + msys2.nupkg + curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \ + chocolatey-core.extension.nupkg + choco install -s . msys2 \ + --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress + rm msys2.nupkg chocolatey-core.extension.nupkg + mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" + ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" fi From df4d490038c37e441065890fa27ed2ce0bdf83e6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 23 Dec 2019 15:40:20 -0500 Subject: [PATCH 21/21] Minimize unsafety in encode_utf8 Use slice patterns to avoid having to skip bounds checking --- src/libcore/char/methods.rs | 59 ++++++++++++++++++------------------- src/libcore/lib.rs | 1 + 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index bb6d6db57d214..fe5d16862a6a6 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -434,36 +434,35 @@ impl char { #[inline] pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { let code = self as u32; - // SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops - unsafe { - let len = if code < MAX_ONE_B && !dst.is_empty() { - *dst.get_unchecked_mut(0) = code as u8; - 1 - } else if code < MAX_TWO_B && dst.len() >= 2 { - *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT; - 2 - } else if code < MAX_THREE_B && dst.len() >= 3 { - *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT; - 3 - } else if dst.len() >= 4 { - *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT; - 4 - } else { - panic!( - "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", - from_u32_unchecked(code).len_utf8(), - code, - dst.len(), - ) - }; - from_utf8_unchecked_mut(dst.get_unchecked_mut(..len)) - } + let len = self.len_utf8(); + match (len, &mut dst[..]) { + (1, [a, ..]) => { + *a = code as u8; + } + (2, [a, b, ..]) => { + *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + *b = (code & 0x3F) as u8 | TAG_CONT; + } + (3, [a, b, c, ..]) => { + *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *c = (code & 0x3F) as u8 | TAG_CONT; + } + (4, [a, b, c, d, ..]) => { + *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; + *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *d = (code & 0x3F) as u8 | TAG_CONT; + } + _ => panic!( + "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", + len, + code, + dst.len(), + ), + }; + // SAFETY: We just wrote UTF-8 content in, so converting to str is fine. + unsafe { from_utf8_unchecked_mut(&mut dst[..len]) } } /// Encodes this character as UTF-16 into the provided `u16` buffer, diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d12aebb87b975..7d11dd2800fd4 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -129,6 +129,7 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] +#![feature(slice_patterns)] #[prelude_import] #[allow(unused)]