From 3ae2d21c12a1fbe909f72a96b012d7092c5419e4 Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 9 Apr 2020 11:03:57 +0300 Subject: [PATCH 01/15] simplify `vec!` macro Simplify `vec!` macro by replacing 2 following branches: - `($($x:expr),*) => (...)` - `($($x:expr,)*) => (...)` with one: - `($($x:expr),* $(,)?) => (...)` --- src/liballoc/macros.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 4bc0c3a079d5c..4a613b92ce8c8 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -42,10 +42,9 @@ macro_rules! vec { ($elem:expr; $n:expr) => ( $crate::vec::from_elem($elem, $n) ); - ($($x:expr),*) => ( + ($($x:expr),* $(,)?) => ( <[_]>::into_vec(box [$($x),*]) ); - ($($x:expr,)*) => ($crate::vec![$($x),*]) } // HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is From d69c66811184707dfdb293673e58ce6121e3714f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 9 Apr 2020 11:32:43 +0200 Subject: [PATCH 02/15] tighten CTFE safety net for accesses to globals --- src/librustc_mir/const_eval/machine.rs | 31 +++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index e926347147894..3d0c5ffae5210 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -350,15 +350,30 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { static_def_id: Option, is_write: bool, ) -> InterpResult<'tcx> { - if is_write && allocation.mutability == Mutability::Not { - Err(err_ub!(WriteToReadOnly(alloc_id)).into()) - } else if is_write { - Err(ConstEvalErrKind::ModifiedGlobal.into()) - } else if memory_extra.can_access_statics || static_def_id.is_none() { - // `static_def_id.is_none()` indicates this is not a static, but a const or so. - Ok(()) + if is_write { + // Write access. These are never allowed, but we give a targeted error message. + if allocation.mutability == Mutability::Not { + Err(err_ub!(WriteToReadOnly(alloc_id)).into()) + } else { + Err(ConstEvalErrKind::ModifiedGlobal.into()) + } } else { - Err(ConstEvalErrKind::ConstAccessesStatic.into()) + // Read access. These are usually allowed, with some exceptions. + if memory_extra.can_access_statics { + // This is allowed to read from anything. + Ok(()) + } else if allocation.mutability == Mutability::Mut || static_def_id.is_some() { + // This is a potentially dangerous read. + // We *must* error on any access to a mutable global here, as the content of + // this allocation may be different now and at run-time, so if we permit reading + // now we might return the wrong value. + // We conservatively also reject all statics here, but that could be relaxed + // in the future. + Err(ConstEvalErrKind::ConstAccessesStatic.into()) + } else { + // Immutable global, this read is fine. + Ok(()) + } } } } From a1f7e9a7250aea6f415fd62e88bbcb848baf73ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 10 Apr 2020 11:28:51 +0200 Subject: [PATCH 03/15] assert that only statics can possibly be mutable --- src/librustc_mir/const_eval/machine.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 3d0c5ffae5210..3ddff6ea8ca4c 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -360,18 +360,18 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { } else { // Read access. These are usually allowed, with some exceptions. if memory_extra.can_access_statics { - // This is allowed to read from anything. + // Machine configuration allows us read from anything (e.g., `static` initializer). Ok(()) - } else if allocation.mutability == Mutability::Mut || static_def_id.is_some() { - // This is a potentially dangerous read. - // We *must* error on any access to a mutable global here, as the content of - // this allocation may be different now and at run-time, so if we permit reading - // now we might return the wrong value. - // We conservatively also reject all statics here, but that could be relaxed - // in the future. + } else if static_def_id.is_some() { + // Machine configuration does not allow us to read statics + // (e.g., `const` initializer). Err(ConstEvalErrKind::ConstAccessesStatic.into()) } else { // Immutable global, this read is fine. + // But make sure we never accept a read from something mutable, that would be + // unsound. The reason is that as the content of this allocation may be different + // now and at run-time, so if we permit reading now we might return the wrong value. + assert_eq!(allocation.mutability, Mutability::Not); Ok(()) } } From 54b5d30f2981736156e75d49e39632875dad5f73 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Fri, 10 Apr 2020 21:15:10 +0200 Subject: [PATCH 04/15] fix target & runtool args order --- src/librustdoc/test.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 7841d5eef58a8..fbbe172afb81f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -263,7 +263,12 @@ fn run_test( if no_run && !compile_fail { compiler.arg("--emit=metadata"); } - compiler.arg("--target").arg(target.to_string()); + compiler.arg("--target").arg(match target { + TargetTriple::TargetTriple(s) => s, + TargetTriple::TargetPath(path) => { + path.to_str().expect("target path must be valid unicode").to_string() + } + }); compiler.arg("-"); compiler.stdin(Stdio::piped()); @@ -312,8 +317,8 @@ fn run_test( if let Some(tool) = runtool { cmd = Command::new(tool); - cmd.arg(output_file); cmd.args(runtool_args); + cmd.arg(output_file); } else { cmd = Command::new(output_file); } From 2c23bd491445c56d2f5e8b22df572dbf9944ee62 Mon Sep 17 00:00:00 2001 From: Waffle Date: Tue, 14 Apr 2020 10:27:55 +0300 Subject: [PATCH 05/15] make `vec![,]` uncompilable Fix regression introduced in commit #3ae2d21 --- src/liballoc/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 4a613b92ce8c8..e163a166b498f 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -42,8 +42,8 @@ macro_rules! vec { ($elem:expr; $n:expr) => ( $crate::vec::from_elem($elem, $n) ); - ($($x:expr),* $(,)?) => ( - <[_]>::into_vec(box [$($x),*]) + ($($x:expr),+ $(,)?) => ( + <[_]>::into_vec(box [$($x),+]) ); } From a0d4c743ab7333af236e985d4e076cdc85249cf9 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 12 Apr 2020 22:01:15 -0400 Subject: [PATCH 06/15] Remove unused single_step flag This appears to have never been used ever since its introduction in 61c7569d4 -- the plugin discussed on the PR introducing that commit, 34811, never materialized. It's also simple to readd in the current scheme, but given that macro expansion is already quite complicated, additional useless state seems good to remove while we're not using it. --- src/librustc_expand/expand.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 51208906c2f2d..7473c890c5ab9 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -507,9 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { expanded_fragments.push(Vec::new()); } expanded_fragments[depth - 1].push((expn_id, expanded_fragment)); - if !self.cx.ecfg.single_step { - invocations.extend(new_invocations.into_iter().rev()); - } + invocations.extend(new_invocations.into_iter().rev()); } self.cx.current_expansion = orig_expansion_data; @@ -1819,7 +1817,6 @@ pub struct ExpansionConfig<'feat> { pub recursion_limit: usize, pub trace_mac: bool, pub should_test: bool, // If false, strip `#[test]` nodes - pub single_step: bool, pub keep_macs: bool, } @@ -1831,7 +1828,6 @@ impl<'feat> ExpansionConfig<'feat> { recursion_limit: 1024, trace_mac: false, should_test: false, - single_step: false, keep_macs: false, } } From 408dc369804d53254aea6409c35eea43e6e460b1 Mon Sep 17 00:00:00 2001 From: mi_sawa Date: Tue, 14 Apr 2020 23:51:03 +0900 Subject: [PATCH 07/15] Tighten time complexity on the doc --- src/liballoc/slice.rs | 2 +- src/libcore/slice/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 4ae7532d992b9..4171185c9701a 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -254,7 +254,7 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e., does not reorder equal elements) and `O(m n log(m n))` + /// This sort is stable (i.e., does not reorder equal elements) and `O(m n log n)` /// worst-case, where the key function is `O(m)`. /// /// For expensive key functions (e.g. functions that are not simple property accesses or diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 66aad3246183f..4d333fbf8ed97 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1697,7 +1697,7 @@ impl [T] { /// elements. /// /// This sort is unstable (i.e., may reorder equal elements), in-place - /// (i.e., does not allocate), and `O(m n log(m n))` worst-case, where the key function is + /// (i.e., does not allocate), and `O(m n log n)` worst-case, where the key function is /// `O(m)`. /// /// # Current implementation From 31eff9af3fd819061d3a573ba3b93e0cc3bfeec3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 14 Apr 2020 08:54:05 -0700 Subject: [PATCH 08/15] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index c8841f2841a2d..f5db319e0b19c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit c8841f2841a2d26124319ddadd1b6a245f9a1856 +Subproject commit f5db319e0b19c22964398d56bc63103d669e1bba diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 37f9e68484111..8204c1d123472 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 37f9e6848411188a1062ead1bd8ebe4b8aa16899 +Subproject commit 8204c1d123472cd17f0c1c5c77300ae802eb0271 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index d22a9c487c780..668fb07b6160b 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit d22a9c487c78095afc4584f1d9b4ec43529d713c +Subproject commit 668fb07b6160b9c468f598e839c1e044db65de30 diff --git a/src/doc/reference b/src/doc/reference index 89dd146154474..3ce94caed4cf9 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 89dd146154474559536d5d4049a03831c501deea +Subproject commit 3ce94caed4cf967106c51ae86be5e098f7875f11 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index a6638463efc76..c106d1683c3a2 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit a6638463efc7631bc0e8dc67ccd256d4e1b61f1a +Subproject commit c106d1683c3a2b0960f0f0fb01728cbb19807332 From 2765f426da76fd7b7b9bd377de7f92dd181387c0 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 14 Apr 2020 17:29:26 +0200 Subject: [PATCH 09/15] cleanup `is_expr_delims_necessary` --- src/librustc_lint/unused.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index aa7c87e9f7bd2..3e1e9cc70aa11 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -384,7 +384,7 @@ trait UnusedDelimLint { fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { followed_by_block && match inner.kind { - ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true, + ExprKind::Ret(_) | ExprKind::Break(..) => true, _ => parser::contains_exterior_struct_lit(&inner), } } From 81a3cd7278f6117401b6b441485154e6ecf2f8c9 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 14 Apr 2020 17:45:00 +0200 Subject: [PATCH 10/15] allow try as scrutinee, e.g. `match try ...` --- src/librustc_parse/parser/expr.rs | 8 ++-- src/test/ui/try-block/try-block-in-match.rs | 6 ++- .../ui/try-block/try-block-in-match.stderr | 10 ----- src/test/ui/try-block/try-block-in-while.rs | 3 +- .../ui/try-block/try-block-in-while.stderr | 9 ++-- .../ui/try-block/try-block-unused-delims.rs | 28 ++++++++++++ .../try-block/try-block-unused-delims.stderr | 44 +++++++++++++++++++ 7 files changed, 88 insertions(+), 20 deletions(-) delete mode 100644 src/test/ui/try-block/try-block-in-match.stderr create mode 100644 src/test/ui/try-block/try-block-unused-delims.rs create mode 100644 src/test/ui/try-block/try-block-unused-delims.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index cbff99f8da612..4e3c5fa63de2c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1846,11 +1846,9 @@ impl<'a> Parser<'a> { } fn is_try_block(&self) -> bool { - self.token.is_keyword(kw::Try) && - self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && - self.token.uninterpolated_span().rust_2018() && - // Prevent `while try {} {}`, `if try {} {} else {}`, etc. - !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) + self.token.is_keyword(kw::Try) + && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) + && self.token.uninterpolated_span().rust_2018() } /// Parses an `async move? {...}` expression. diff --git a/src/test/ui/try-block/try-block-in-match.rs b/src/test/ui/try-block/try-block-in-match.rs index bce0d0340b658..cd0b967e79d07 100644 --- a/src/test/ui/try-block/try-block-in-match.rs +++ b/src/test/ui/try-block/try-block-in-match.rs @@ -1,7 +1,11 @@ +// run-pass // compile-flags: --edition 2018 #![feature(try_blocks)] fn main() { - match try { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `try` + match try { } { + Err(()) => (), + Ok(()) => (), + } } diff --git a/src/test/ui/try-block/try-block-in-match.stderr b/src/test/ui/try-block/try-block-in-match.stderr deleted file mode 100644 index 936e0fe19bafe..0000000000000 --- a/src/test/ui/try-block/try-block-in-match.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: expected expression, found reserved keyword `try` - --> $DIR/try-block-in-match.rs:6:11 - | -LL | match try { false } { _ => {} } - | ----- ^^^ expected expression - | | - | while parsing this match expression - -error: aborting due to previous error - diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs index 98af796dd3780..33d2723651929 100644 --- a/src/test/ui/try-block/try-block-in-while.rs +++ b/src/test/ui/try-block/try-block-in-while.rs @@ -3,5 +3,6 @@ #![feature(try_blocks)] fn main() { - while try { false } {} //~ ERROR expected expression, found reserved keyword `try` + while try { false } {} + //~^ ERROR the trait bound `bool: std::ops::Try` is not satisfied } diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index 026df15eb877a..ac41ddfd8c042 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,8 +1,11 @@ -error: expected expression, found reserved keyword `try` - --> $DIR/try-block-in-while.rs:6:11 +error[E0277]: the trait bound `bool: std::ops::Try` is not satisfied + --> $DIR/try-block-in-while.rs:6:15 | LL | while try { false } {} - | ^^^ expected expression + | ^^^^^^^^^ the trait `std::ops::Try` is not implemented for `bool` + | + = note: required by `std::ops::Try::from_ok` error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-block/try-block-unused-delims.rs b/src/test/ui/try-block/try-block-unused-delims.rs new file mode 100644 index 0000000000000..0b767eb2dad77 --- /dev/null +++ b/src/test/ui/try-block/try-block-unused-delims.rs @@ -0,0 +1,28 @@ +// check-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] +#![warn(unused_parens, unused_braces)] + +fn consume(_: Result) -> T { todo!() } + +fn main() { + consume((try {})); + //~^ WARN unnecessary parentheses + + consume({ try {} }); + //~^ WARN unnecessary braces + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } + + if let Err(()) = (try {}) {} + //~^ WARN unnecessary parentheses + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } +} diff --git a/src/test/ui/try-block/try-block-unused-delims.stderr b/src/test/ui/try-block/try-block-unused-delims.stderr new file mode 100644 index 0000000000000..5c7602ee0ab12 --- /dev/null +++ b/src/test/ui/try-block/try-block-unused-delims.stderr @@ -0,0 +1,44 @@ +warning: unnecessary parentheses around function argument + --> $DIR/try-block-unused-delims.rs:10:13 + | +LL | consume((try {})); + | ^^^^^^^^ help: remove these parentheses + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:5:9 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ + +warning: unnecessary braces around function argument + --> $DIR/try-block-unused-delims.rs:13:13 + | +LL | consume({ try {} }); + | ^^^^^^^^^^ help: remove these braces + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:5:24 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:16:11 + | +LL | match (try {}) { + | ^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around `let` scrutinee expression + --> $DIR/try-block-unused-delims.rs:21:22 + | +LL | if let Err(()) = (try {}) {} + | ^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:24:11 + | +LL | match (try {}) { + | ^^^^^^^^ help: remove these parentheses + +warning: 5 warnings emitted + From 10ae85f527ee98c0f6fd812fd96bd2821c25b0d2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:52:06 +0200 Subject: [PATCH 11/15] rustc: add lang items "const_slice_ptr" and "mut_slice_ptr" Add lang items for methods on raw slices. --- src/librustc_hir/lang_items.rs | 2 ++ src/librustc_typeck/check/method/probe.rs | 13 ++++++---- .../coherence/inherent_impls.rs | 24 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index 5a3a9cabeb450..53f72804a848d 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -135,6 +135,8 @@ language_item_table! { SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl; ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl; MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl; + ConstSlicePtrImplItem, "const_slice_ptr", const_slice_ptr_impl, Target::Impl; + MutSlicePtrImplItem, "mut_slice_ptr", mut_slice_ptr_impl, Target::Impl; I8ImplItem, "i8", i8_impl, Target::Impl; I16ImplItem, "i16", i16_impl, Target::Impl; I32ImplItem, "i32", i32_impl, Target::Impl; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b5d3f7b55029f..9b1c8b9a9c83e 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -649,11 +649,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => { - let lang_def_id = match mutbl { - hir::Mutability::Not => lang_items.const_ptr_impl(), - hir::Mutability::Mut => lang_items.mut_ptr_impl(), + let (lang_def_id1, lang_def_id2) = match mutbl { + hir::Mutability::Not => { + (lang_items.const_ptr_impl(), lang_items.const_slice_ptr_impl()) + } + hir::Mutability::Mut => { + (lang_items.mut_ptr_impl(), lang_items.mut_slice_ptr_impl()) + } }; - self.assemble_inherent_impl_for_primitive(lang_def_id); + self.assemble_inherent_impl_for_primitive(lang_def_id1); + self.assemble_inherent_impl_for_primitive(lang_def_id2); } ty::Int(i) => { let lang_def_id = match i { diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 9ace9f424b74d..2e84173477074 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -112,6 +112,30 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { item.span, ); } + ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not }) + if matches!(inner.kind, ty::Slice(_)) => + { + self.check_primitive_impl( + def_id, + lang_items.const_slice_ptr_impl(), + None, + "const_slice_ptr", + "*const [T]", + item.span, + ); + } + ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut }) + if matches!(inner.kind, ty::Slice(_)) => + { + self.check_primitive_impl( + def_id, + lang_items.mut_slice_ptr_impl(), + None, + "mut_slice_ptr", + "*mut [T]", + item.span, + ); + } ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { self.check_primitive_impl( def_id, From 0c17b3f4f4ad973694f31c027d44c73f3577fd07 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 21:00:32 +0200 Subject: [PATCH 12/15] rustdoc: add "const_slice_ptr" and "mut_slice_ptr" trait impls --- src/librustdoc/passes/collect_trait_impls.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index da0e97f1075b0..c80967a4b33f2 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -62,6 +62,8 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { lang_items.slice_u8_alloc_impl(), lang_items.const_ptr_impl(), lang_items.mut_ptr_impl(), + lang_items.const_slice_ptr_impl(), + lang_items.mut_slice_ptr_impl(), ]; for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { From 43612e21a61bf6cd4bf741ffce64d7dd3b8ee19f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:57:35 +0200 Subject: [PATCH 13/15] ptr: implement "const_slice_ptr" and "mut_slice_ptr" lang items --- src/libcore/ptr/const_ptr.rs | 4 ++++ src/libcore/ptr/mut_ptr.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 52e224d2a026f..00bd985114a7b 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -706,6 +706,10 @@ impl *const T { } } +#[cfg(not(bootstrap))] +#[lang = "const_slice_ptr"] +impl *const [T] {} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *const T { diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 9f85d781d698a..00084456839e4 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -894,6 +894,10 @@ impl *mut T { } } +#[cfg(not(bootstrap))] +#[lang = "mut_slice_ptr"] +impl *mut [T] {} + // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *mut T { From 2a29f8f89deb34356e767e3c0fb9fdd6d4fdbc27 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 13 Apr 2020 20:58:23 +0200 Subject: [PATCH 14/15] ptr: introduce len() method on raw slices It is already possible to extract the pointer part of a raw slice by a simple cast, but retrieving the length is not possible without relying on the representation of the raw slice when it is not valid to convert the raw slice into a slice reference (i.e. the pointer is null or unaligned). Introduce a len() method on raw slices to add this missing feature. --- src/libcore/ptr/const_ptr.rs | 26 +++++++++++++++++++++++++- src/libcore/ptr/mut_ptr.rs | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 00bd985114a7b..33c9e0b531518 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -708,7 +708,31 @@ impl *const T { #[cfg(not(bootstrap))] #[lang = "const_slice_ptr"] -impl *const [T] {} +impl *const [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_len)] + /// + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[unstable(feature = "slice_ptr_len", issue = "none")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + pub const fn len(self) -> usize { + unsafe { Repr { rust: self }.raw }.len + } +} // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 00084456839e4..89475973675cf 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -896,7 +896,31 @@ impl *mut T { #[cfg(not(bootstrap))] #[lang = "mut_slice_ptr"] -impl *mut [T] {} +impl *mut [T] { + /// Returns the length of a raw slice. + /// + /// The returned value is the number of **elements**, not the number of bytes. + /// + /// This function is safe, even when the raw slice cannot be cast to a slice + /// reference because the pointer is null or unaligned. + /// + /// # Examples + /// + /// ```rust + /// #![feature(slice_ptr_len)] + /// + /// use std::ptr; + /// + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert_eq!(slice.len(), 3); + /// ``` + #[inline] + #[unstable(feature = "slice_ptr_len", issue = "none")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + pub const fn len(self) -> usize { + unsafe { Repr { rust_mut: self }.raw }.len + } +} // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] From dfd68441beba4db959697974949bc7f613a13e2e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 14 Apr 2020 21:34:27 +0200 Subject: [PATCH 15/15] ptr: add tracking issue for len() method on raw slices --- src/libcore/ptr/const_ptr.rs | 4 ++-- src/libcore/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 33c9e0b531518..729e0b897c098 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -727,8 +727,8 @@ impl *const [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[unstable(feature = "slice_ptr_len", issue = "none")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + #[unstable(feature = "slice_ptr_len", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { unsafe { Repr { rust: self }.raw }.len } diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 89475973675cf..3b7e83bf37fa6 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -915,8 +915,8 @@ impl *mut [T] { /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[unstable(feature = "slice_ptr_len", issue = "none")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "none")] + #[unstable(feature = "slice_ptr_len", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] pub const fn len(self) -> usize { unsafe { Repr { rust_mut: self }.raw }.len }