From 389100921ab840bc235b3487d8b519197dec77c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Tue, 6 Apr 2021 22:01:00 +0200 Subject: [PATCH 01/16] add lint deref_nullptr --- compiler/rustc_lint/src/builtin.rs | 89 ++++++++++++++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_span/src/symbol.rs | 2 + library/core/src/ptr/mod.rs | 2 + 4 files changed, 94 insertions(+) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3f16bb9f442ee..ab82070ce7342 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2961,3 +2961,92 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { } } } + +declare_lint! { + /// The `deref_nullptr` lint detects when an null pointer is dereferenced, + /// which causes [undefined behavior]. + /// + /// ### Example + /// + /// ```rust,no_run + /// let x: i32 = unsafe { + /// *ptr::null() + /// }; + /// ``` + /// ```rust,no_run + /// unsafe { + /// *(0 as *const i32); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// + /// Dereferencing a null pointer causes [undefined behavior] even as a place expression, + /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + pub DEREF_NULLPTR, + Warn, + "detects when an null pointer is dereferenced" +} + +declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]); + +impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) { + /// test if expression is a null ptr + fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Cast(ref expr, ref ty) => { + if let rustc_hir::TyKind::Ptr(_) = ty.kind { + return is_zero(expr) || is_null_ptr(cx, expr); + } + } + // check for call to `core::ptr::null` or `core::ptr::null_mut` + rustc_hir::ExprKind::Call(ref path, _) => { + if let rustc_hir::ExprKind::Path(ref qpath) = path.kind { + if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() { + return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id) + || cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id); + } + } + } + _ => {} + } + false + } + + /// test if experssion is the literal `0` + fn is_zero(expr: &hir::Expr<'_>) -> bool { + match &expr.kind { + rustc_hir::ExprKind::Lit(ref lit) => { + if let LitKind::Int(a, _) = lit.node { + return a == 0; + } + } + _ => {} + } + false + } + + if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind { + if let rustc_hir::UnOp::Deref = un_op { + if is_null_ptr(cx, expr_deref) { + cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { + let mut err = + lint.build("Dereferencing a null pointer causes undefined behavior"); + err.span_label(expr.span, "a null pointer is dereferenced"); + err.span_label( + expr.span, + "this code causes undefined behavior when executed", + ); + err.emit(); + }); + } + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index e2724b52453a5..2f46969b021e6 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -206,6 +206,7 @@ macro_rules! late_lint_mod_passes { UnreachablePub: UnreachablePub, ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, InvalidValue: InvalidValue, + DerefNullPtr: DerefNullPtr, ] ); }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 54fea5515946f..95a8bda94222c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -900,6 +900,8 @@ symbols! { profiler_runtime, ptr_guaranteed_eq, ptr_guaranteed_ne, + ptr_null, + ptr_null_mut, ptr_offset_from, pub_macro_rules, pub_restricted, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6e207156b55a3..ad8696ab9272d 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -211,6 +211,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null"] pub const fn null() -> *const T { 0 as *const T } @@ -229,6 +230,7 @@ pub const fn null() -> *const T { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_diagnostic_item = "ptr_null_mut"] pub const fn null_mut() -> *mut T { 0 as *mut T } From c7bc41f97aeef3c4f562c0fd2835acd6d6c2b5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Wed, 7 Apr 2021 19:23:17 +0200 Subject: [PATCH 02/16] add test --- compiler/rustc_lint/src/builtin.rs | 2 + src/test/ui/cleanup-shortcircuit.rs | 3 + src/test/ui/lint/lint-deref-nullptr.rs | 32 +++++++ src/test/ui/lint/lint-deref-nullptr.stderr | 98 ++++++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 src/test/ui/lint/lint-deref-nullptr.rs create mode 100644 src/test/ui/lint/lint-deref-nullptr.stderr diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ab82070ce7342..cb81c330b718b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + //! Lints in the Rust compiler. //! //! This contains lints which can feasibly be implemented as their own diff --git a/src/test/ui/cleanup-shortcircuit.rs b/src/test/ui/cleanup-shortcircuit.rs index 4f5197a5ba9b8..fe867ce1fbd57 100644 --- a/src/test/ui/cleanup-shortcircuit.rs +++ b/src/test/ui/cleanup-shortcircuit.rs @@ -3,6 +3,9 @@ // pretty-expanded FIXME #23616 +#![allow(deref_nullptr)] + + use std::env; pub fn main() { diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs new file mode 100644 index 0000000000000..7b10e711c27b8 --- /dev/null +++ b/src/test/ui/lint/lint-deref-nullptr.rs @@ -0,0 +1,32 @@ +// test the deref_nullptr lint + +#![deny(deref_nullptr)] + +fn f() { + unsafe { + let a = 1; + let ub = *(a as *const i32); + let ub = *(0 as *const i32); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *core::ptr::null::(); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *core::ptr::null_mut::(); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *(core::ptr::null::() as *const i32); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = &*core::ptr::null::(); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + core::ptr::addr_of!(*core::ptr::null::()); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + std::ptr::addr_of_mut!(*core::ptr::null_mut::()); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *std::ptr::null::(); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + let ub = *std::ptr::null_mut::(); + //~^ ERROR Dereferencing a null pointer causes undefined behavior + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr new file mode 100644 index 0000000000000..4fc6c54e19707 --- /dev/null +++ b/src/test/ui/lint/lint-deref-nullptr.stderr @@ -0,0 +1,98 @@ +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:9:18 + | +LL | let ub = *(0 as *const i32); + | ^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + | +note: the lint level is defined here + --> $DIR/lint-deref-nullptr.rs:3:9 + | +LL | #![deny(deref_nullptr)] + | ^^^^^^^^^^^^^ + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:11:18 + | +LL | let ub = *core::ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:13:18 + | +LL | let ub = *core::ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:15:18 + | +LL | let ub = *(core::ptr::null::() as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:17:18 + | +LL | let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:19:19 + | +LL | let ub = &*core::ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:21:29 + | +LL | core::ptr::addr_of!(*core::ptr::null::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:23:32 + | +LL | std::ptr::addr_of_mut!(*core::ptr::null_mut::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:25:18 + | +LL | let ub = *std::ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: Dereferencing a null pointer causes undefined behavior + --> $DIR/lint-deref-nullptr.rs:27:18 + | +LL | let ub = *std::ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a null pointer is dereferenced + | this code causes undefined behavior when executed + +error: aborting due to 10 previous errors + From 3d215bdf42514311e48f5dc1cbf71cbd3d74e732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Wed, 7 Apr 2021 20:53:58 +0200 Subject: [PATCH 03/16] change documentation of lint --- compiler/rustc_lint/src/builtin.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index cb81c330b718b..e449cd8c7559a 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2969,16 +2969,25 @@ declare_lint! { /// which causes [undefined behavior]. /// /// ### Example - /// /// ```rust,no_run - /// let x: i32 = unsafe { - /// *ptr::null() + /// unsafe { + /// &*core::ptr::null::() /// }; /// ``` /// ```rust,no_run /// unsafe { - /// *(0 as *const i32); - /// } + /// core::ptr::addr_of!(*std::ptr::null::()) + /// }; + /// ``` + /// ```rust,no_run + /// unsafe { + /// *core::ptr::null::() + /// }; + /// ``` + /// ```rust,no_run + /// unsafe { + /// *(0 as *const i32) + /// }; /// ``` /// /// {{produces}} From 0531ed0b6220257d7c79405ca7d81d9fe66976be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Thu, 8 Apr 2021 12:09:32 +0200 Subject: [PATCH 04/16] fix lint doc --- compiler/rustc_lint/src/builtin.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e449cd8c7559a..905a808f51f97 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2969,32 +2969,21 @@ declare_lint! { /// which causes [undefined behavior]. /// /// ### Example + /// /// ```rust,no_run + /// # #![allow(unused)] /// unsafe { - /// &*core::ptr::null::() - /// }; - /// ``` - /// ```rust,no_run - /// unsafe { - /// core::ptr::addr_of!(*std::ptr::null::()) - /// }; - /// ``` - /// ```rust,no_run - /// unsafe { - /// *core::ptr::null::() - /// }; - /// ``` - /// ```rust,no_run - /// unsafe { - /// *(0 as *const i32) - /// }; + /// let x = &*core::ptr::null::(); + /// let x = core::ptr::addr_of!(*std::ptr::null::()); + /// let x = *core::ptr::null::(); + /// let x = *(0 as *const i32); + /// } /// ``` /// /// {{produces}} /// /// ### Explanation /// - /// /// Dereferencing a null pointer causes [undefined behavior] even as a place expression, /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`. /// From 79666c8857870ed8c16de932781ad50624e1accb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Fri, 9 Apr 2021 16:13:04 +0200 Subject: [PATCH 05/16] changes based on review --- compiler/rustc_lint/src/builtin.rs | 10 ++-- src/test/ui/lint/lint-deref-nullptr.rs | 20 +++---- src/test/ui/lint/lint-deref-nullptr.stderr | 70 +++++++--------------- 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 905a808f51f97..f19572550ebd0 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2972,10 +2972,10 @@ declare_lint! { /// /// ```rust,no_run /// # #![allow(unused)] + /// use std::ptr; /// unsafe { - /// let x = &*core::ptr::null::(); - /// let x = core::ptr::addr_of!(*std::ptr::null::()); - /// let x = *core::ptr::null::(); + /// let x = &*ptr::null::(); + /// let x = ptr::addr_of!(*ptr::null::()); /// let x = *(0 as *const i32); /// } /// ``` @@ -3036,9 +3036,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { if let rustc_hir::UnOp::Deref = un_op { if is_null_ptr(cx, expr_deref) { cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| { - let mut err = - lint.build("Dereferencing a null pointer causes undefined behavior"); - err.span_label(expr.span, "a null pointer is dereferenced"); + let mut err = lint.build("dereferencing a null pointer"); err.span_label( expr.span, "this code causes undefined behavior when executed", diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs index 7b10e711c27b8..a5aee73514031 100644 --- a/src/test/ui/lint/lint-deref-nullptr.rs +++ b/src/test/ui/lint/lint-deref-nullptr.rs @@ -7,25 +7,25 @@ fn f() { let a = 1; let ub = *(a as *const i32); let ub = *(0 as *const i32); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *core::ptr::null::(); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *core::ptr::null_mut::(); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *(core::ptr::null::() as *const i32); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = &*core::ptr::null::(); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer core::ptr::addr_of!(*core::ptr::null::()); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer std::ptr::addr_of_mut!(*core::ptr::null_mut::()); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *std::ptr::null::(); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer let ub = *std::ptr::null_mut::(); - //~^ ERROR Dereferencing a null pointer causes undefined behavior + //~^ ERROR dereferencing a null pointer } } diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr index 4fc6c54e19707..ba27d2c45fcc7 100644 --- a/src/test/ui/lint/lint-deref-nullptr.stderr +++ b/src/test/ui/lint/lint-deref-nullptr.stderr @@ -1,11 +1,8 @@ -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:9:18 | LL | let ub = *(0 as *const i32); - | ^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: the lint level is defined here --> $DIR/lint-deref-nullptr.rs:3:9 @@ -13,86 +10,59 @@ note: the lint level is defined here LL | #![deny(deref_nullptr)] | ^^^^^^^^^^^^^ -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:11:18 | LL | let ub = *core::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:13:18 | LL | let ub = *core::ptr::null_mut::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:15:18 | LL | let ub = *(core::ptr::null::() as *const i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:17:18 | LL | let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:19:19 | LL | let ub = &*core::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:21:29 | LL | core::ptr::addr_of!(*core::ptr::null::()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:23:32 | LL | std::ptr::addr_of_mut!(*core::ptr::null_mut::()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:25:18 | LL | let ub = *std::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: Dereferencing a null pointer causes undefined behavior +error: dereferencing a null pointer --> $DIR/lint-deref-nullptr.rs:27:18 | LL | let ub = *std::ptr::null_mut::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | a null pointer is dereferenced - | this code causes undefined behavior when executed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: aborting due to 10 previous errors From c288414757975874005f45b4bcb5c5d50cbe227a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Sat, 10 Apr 2021 15:40:07 +0200 Subject: [PATCH 06/16] add test offset of a field --- src/test/ui/lint/lint-deref-nullptr.rs | 26 ++++++--- src/test/ui/lint/lint-deref-nullptr.stderr | 64 ++++++++++++---------- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs index a5aee73514031..1dc54a5622b74 100644 --- a/src/test/ui/lint/lint-deref-nullptr.rs +++ b/src/test/ui/lint/lint-deref-nullptr.rs @@ -2,29 +2,37 @@ #![deny(deref_nullptr)] +use std::ptr; + +struct Struct { + field: u8, +} + fn f() { unsafe { let a = 1; let ub = *(a as *const i32); let ub = *(0 as *const i32); //~^ ERROR dereferencing a null pointer - let ub = *core::ptr::null::(); + let ub = *ptr::null::(); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null_mut::(); //~^ ERROR dereferencing a null pointer - let ub = *core::ptr::null_mut::(); + let ub = *(ptr::null::() as *const i32); //~^ ERROR dereferencing a null pointer - let ub = *(core::ptr::null::() as *const i32); + let ub = *(ptr::null::() as *mut i32 as *mut usize as *const u8); //~^ ERROR dereferencing a null pointer - let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); + let ub = &*ptr::null::(); //~^ ERROR dereferencing a null pointer - let ub = &*core::ptr::null::(); + ptr::addr_of!(*ptr::null::()); //~^ ERROR dereferencing a null pointer - core::ptr::addr_of!(*core::ptr::null::()); + ptr::addr_of_mut!(*ptr::null_mut::()); //~^ ERROR dereferencing a null pointer - std::ptr::addr_of_mut!(*core::ptr::null_mut::()); + let ub = *ptr::null::(); //~^ ERROR dereferencing a null pointer - let ub = *std::ptr::null::(); + let ub = *ptr::null_mut::(); //~^ ERROR dereferencing a null pointer - let ub = *std::ptr::null_mut::(); + let offset = ptr::addr_of!((*ptr::null::()).field); //~^ ERROR dereferencing a null pointer } } diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr index ba27d2c45fcc7..40fdfad2368e6 100644 --- a/src/test/ui/lint/lint-deref-nullptr.stderr +++ b/src/test/ui/lint/lint-deref-nullptr.stderr @@ -1,5 +1,5 @@ error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:9:18 + --> $DIR/lint-deref-nullptr.rs:15:18 | LL | let ub = *(0 as *const i32); | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed @@ -11,58 +11,64 @@ LL | #![deny(deref_nullptr)] | ^^^^^^^^^^^^^ error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:11:18 + --> $DIR/lint-deref-nullptr.rs:17:18 | -LL | let ub = *core::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = *ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:13:18 + --> $DIR/lint-deref-nullptr.rs:19:18 | -LL | let ub = *core::ptr::null_mut::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = *ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:15:18 + --> $DIR/lint-deref-nullptr.rs:21:18 | -LL | let ub = *(core::ptr::null::() as *const i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = *(ptr::null::() as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:17:18 + --> $DIR/lint-deref-nullptr.rs:23:18 + | +LL | let ub = *(ptr::null::() as *mut i32 as *mut usize as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:25:19 | -LL | let ub = *(core::ptr::null::() as *mut i32 as *mut usize as *const u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = &*ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:19:19 + --> $DIR/lint-deref-nullptr.rs:27:23 | -LL | let ub = &*core::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | ptr::addr_of!(*ptr::null::()); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:21:29 + --> $DIR/lint-deref-nullptr.rs:29:27 | -LL | core::ptr::addr_of!(*core::ptr::null::()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | ptr::addr_of_mut!(*ptr::null_mut::()); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:23:32 + --> $DIR/lint-deref-nullptr.rs:31:18 | -LL | std::ptr::addr_of_mut!(*core::ptr::null_mut::()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = *ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:25:18 + --> $DIR/lint-deref-nullptr.rs:33:18 | -LL | let ub = *std::ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let ub = *ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:27:18 + --> $DIR/lint-deref-nullptr.rs:35:36 | -LL | let ub = *std::ptr::null_mut::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed +LL | let offset = ptr::addr_of!((*ptr::null::()).field); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors From 7f0f83a26fdec4caa2a8512f9fc611d504b7aad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=C3=A9nore=20Bouttefeux?= Date: Sat, 10 Apr 2021 16:17:09 +0200 Subject: [PATCH 07/16] remove redundant test --- src/test/ui/lint/lint-deref-nullptr.rs | 6 ++--- src/test/ui/lint/lint-deref-nullptr.stderr | 26 +++++++++------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs index 1dc54a5622b74..d052dbd9b647c 100644 --- a/src/test/ui/lint/lint-deref-nullptr.rs +++ b/src/test/ui/lint/lint-deref-nullptr.rs @@ -24,14 +24,12 @@ fn f() { //~^ ERROR dereferencing a null pointer let ub = &*ptr::null::(); //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null_mut::(); + //~^ ERROR dereferencing a null pointer ptr::addr_of!(*ptr::null::()); //~^ ERROR dereferencing a null pointer ptr::addr_of_mut!(*ptr::null_mut::()); //~^ ERROR dereferencing a null pointer - let ub = *ptr::null::(); - //~^ ERROR dereferencing a null pointer - let ub = *ptr::null_mut::(); - //~^ ERROR dereferencing a null pointer let offset = ptr::addr_of!((*ptr::null::()).field); //~^ ERROR dereferencing a null pointer } diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr index 40fdfad2368e6..c6f432e4e4207 100644 --- a/src/test/ui/lint/lint-deref-nullptr.stderr +++ b/src/test/ui/lint/lint-deref-nullptr.stderr @@ -41,34 +41,28 @@ LL | let ub = &*ptr::null::(); | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:27:23 + --> $DIR/lint-deref-nullptr.rs:27:19 + | +LL | let ub = &*ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:29:23 | LL | ptr::addr_of!(*ptr::null::()); | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:29:27 + --> $DIR/lint-deref-nullptr.rs:31:27 | LL | ptr::addr_of_mut!(*ptr::null_mut::()); | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:31:18 - | -LL | let ub = *ptr::null::(); - | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed - -error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:33:18 - | -LL | let ub = *ptr::null_mut::(); - | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed - -error: dereferencing a null pointer - --> $DIR/lint-deref-nullptr.rs:35:36 + --> $DIR/lint-deref-nullptr.rs:33:36 | LL | let offset = ptr::addr_of!((*ptr::null::()).field); | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors From 904ee686ca06c78135d356235265997a1faf292e Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 14 Apr 2021 04:04:27 +0200 Subject: [PATCH 08/16] Explicitly implement `!Send` and `!Sync` for `sys::{Args, Env}` --- library/std/src/sys/hermit/args.rs | 8 ++++---- library/std/src/sys/hermit/os.rs | 7 ++++--- library/std/src/sys/unix/args.rs | 13 ++++++------- library/std/src/sys/unix/os.rs | 7 ++++--- library/std/src/sys/wasi/args.rs | 10 ++++------ library/std/src/sys/wasi/os.rs | 7 ++++--- library/std/src/sys/wasm/args.rs | 7 ++++--- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index 7727293927282..17b27c50bb2d3 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -1,5 +1,4 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; /// One-time global initialization. @@ -19,7 +18,6 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } impl Args { @@ -28,6 +26,9 @@ impl Args { } } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { @@ -53,7 +54,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::ptr; use crate::sys_common::os_str_bytes::*; @@ -76,7 +76,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index 78eabf8f81e98..f09f437e533bf 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -3,7 +3,6 @@ use crate::error::Error as StdError; use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; -use crate::marker::PhantomData; use crate::memchr; use crate::path::{self, PathBuf}; use crate::str; @@ -110,9 +109,11 @@ pub fn init_environment(env: *const *const i8) { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -134,7 +135,7 @@ pub fn env() -> Env { result.push((key.clone(), value.clone())); } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } } diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 6967647249390..4fca0d0752fe8 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -6,7 +6,6 @@ #![allow(dead_code)] // runtime init functions not used during testing use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; /// One-time global initialization. @@ -26,9 +25,11 @@ pub fn args() -> Args { pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Args { pub fn inner_debug(&self) -> &[OsString] { self.iter.as_slice() @@ -76,7 +77,6 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; - use crate::marker::PhantomData; use crate::os::unix::prelude::*; use crate::ptr; use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; @@ -133,7 +133,7 @@ mod imp { } pub fn args() -> Args { - Args { iter: clone().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: clone().into_iter() } } fn clone() -> Vec { @@ -155,7 +155,6 @@ mod imp { mod imp { use super::Args; use crate::ffi::CStr; - use crate::marker::PhantomData; pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} @@ -180,7 +179,7 @@ mod imp { }) .collect::>() }; - Args { iter: vec.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: vec.into_iter() } } // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs @@ -247,6 +246,6 @@ mod imp { } } - Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: res.into_iter() } } } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 4a077e2151ed9..e4355653498cf 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -12,7 +12,6 @@ use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io; use crate::iter; -use crate::marker::PhantomData; use crate::mem; use crate::memchr; use crate::path::{self, PathBuf}; @@ -465,9 +464,11 @@ pub fn current_exe() -> io::Result { pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Env {} +impl !Sync for Env {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -515,7 +516,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { diff --git a/library/std/src/sys/wasi/args.rs b/library/std/src/sys/wasi/args.rs index 9a27218e1fb70..61a9bd28fd812 100644 --- a/library/std/src/sys/wasi/args.rs +++ b/library/std/src/sys/wasi/args.rs @@ -1,7 +1,6 @@ #![deny(unsafe_op_in_unsafe_fn)] use crate::ffi::{CStr, OsStr, OsString}; -use crate::marker::PhantomData; use crate::os::wasi::ffi::OsStrExt; use crate::vec; @@ -11,15 +10,14 @@ pub unsafe fn cleanup() {} pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + /// Returns the command line arguments pub fn args() -> Args { - Args { - iter: maybe_args().unwrap_or(Vec::new()).into_iter(), - _dont_send_or_sync_me: PhantomData, - } + Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() } } fn maybe_args() -> Option> { diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs index 185d6109cb93e..18271a46270cb 100644 --- a/library/std/src/sys/wasi/os.rs +++ b/library/std/src/sys/wasi/os.rs @@ -5,7 +5,6 @@ use crate::error::Error as StdError; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::io; -use crate::marker::PhantomData; use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; use crate::str; @@ -129,9 +128,11 @@ pub fn current_exe() -> io::Result { } pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -155,7 +156,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; + return Env { iter: result.into_iter() }; } // See src/libstd/sys/unix/os.rs, same as that diff --git a/library/std/src/sys/wasm/args.rs b/library/std/src/sys/wasm/args.rs index 3b6557ae3257f..8c25a1d262a63 100644 --- a/library/std/src/sys/wasm/args.rs +++ b/library/std/src/sys/wasm/args.rs @@ -1,5 +1,4 @@ use crate::ffi::OsString; -use crate::marker::PhantomData; use crate::vec; pub unsafe fn init(_argc: isize, _argv: *const *const u8) { @@ -9,14 +8,16 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8) { pub unsafe fn cleanup() {} pub fn args() -> Args { - Args { iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData } + Args { iter: Vec::new().into_iter() } } pub struct Args { iter: vec::IntoIter, - _dont_send_or_sync_me: PhantomData<*mut ()>, } +impl !Send for Args {} +impl !Sync for Args {} + impl Args { pub fn inner_debug(&self) -> &[OsString] { self.iter.as_slice() From b29a88745b047b52bdfb4a5046c85fd05003152e Mon Sep 17 00:00:00 2001 From: CDirkx Date: Wed, 14 Apr 2021 12:42:38 +0200 Subject: [PATCH 09/16] Correct typo Co-authored-by: Mara Bos --- library/std/src/sys/hermit/os.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index f09f437e533bf..fd2a0fe22a95d 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -111,8 +111,8 @@ pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, } -impl !Send for Args {} -impl !Sync for Args {} +impl !Send for Env {} +impl !Sync for Env {} impl Iterator for Env { type Item = (OsString, OsString); From 0e9de930aca7446a23b28c9a286c67d13b5678a3 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Wed, 14 Apr 2021 18:51:54 +0800 Subject: [PATCH 10/16] add macro-or-patterns-2021 test --- src/test/ui/macros/macro-or-patterns-2021.rs | 21 +++++++++++++++ .../ui/macros/macro-or-patterns-2021.stderr | 26 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/test/ui/macros/macro-or-patterns-2021.rs create mode 100644 src/test/ui/macros/macro-or-patterns-2021.stderr diff --git a/src/test/ui/macros/macro-or-patterns-2021.rs b/src/test/ui/macros/macro-or-patterns-2021.rs new file mode 100644 index 0000000000000..edd3f3e7646b8 --- /dev/null +++ b/src/test/ui/macros/macro-or-patterns-2021.rs @@ -0,0 +1,21 @@ +#![feature(edition_macro_pats)] +#![allow(unused_macros)] +macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} } //~ ERROR `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments +macro_rules! baz { ($x:pat2015 | $y:pat2015) => {} } // should be ok +macro_rules! qux { ($x:pat2015 | $y:pat2021) => {} } // should be ok +macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} } //~ ERROR `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat2021 )|+ => $expr_arm:pat2021 ),+ ) => { //~ ERROR `$pat:pat2021` may be followed by `|`, which is not allowed for `pat2021` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/src/test/ui/macros/macro-or-patterns-2021.stderr b/src/test/ui/macros/macro-or-patterns-2021.stderr new file mode 100644 index 0000000000000..67feb0c2891f1 --- /dev/null +++ b/src/test/ui/macros/macro-or-patterns-2021.stderr @@ -0,0 +1,26 @@ +error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments + --> $DIR/macro-or-patterns-2021.rs:3:32 + | +LL | macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} } + | ^ not allowed after `pat2021` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments + --> $DIR/macro-or-patterns-2021.rs:6:32 + | +LL | macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} } + | ^ not allowed after `pat2021` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat2021` may be followed by `|`, which is not allowed for `pat2021` fragments + --> $DIR/macro-or-patterns-2021.rs:8:40 + | +LL | ( $expr:expr , $( $( $pat:pat2021 )|+ => $expr_arm:pat2021 ),+ ) => { + | ^ not allowed after `pat2021` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + From 905d23b65c07a1da4452f9a20b1891fc46533fb7 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 24 Feb 2021 19:16:24 +0100 Subject: [PATCH 11/16] Move `std::sys_common::alloc` to `std::sys::common` --- library/std/src/{sys_common => sys/common}/alloc.rs | 0 library/std/src/sys/common/mod.rs | 1 + library/std/src/sys/mod.rs | 2 ++ library/std/src/sys/unix/alloc.rs | 2 +- library/std/src/sys/windows/alloc.rs | 2 +- library/std/src/sys_common/mod.rs | 1 - 6 files changed, 5 insertions(+), 3 deletions(-) rename library/std/src/{sys_common => sys/common}/alloc.rs (100%) create mode 100644 library/std/src/sys/common/mod.rs diff --git a/library/std/src/sys_common/alloc.rs b/library/std/src/sys/common/alloc.rs similarity index 100% rename from library/std/src/sys_common/alloc.rs rename to library/std/src/sys/common/alloc.rs diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs new file mode 100644 index 0000000000000..920965d5944d7 --- /dev/null +++ b/library/std/src/sys/common/mod.rs @@ -0,0 +1 @@ +pub mod alloc; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 9b359392cf0cd..50c2660ebcf1f 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -22,6 +22,8 @@ #![allow(missing_debug_implementations)] +mod common; + cfg_if::cfg_if! { if #[cfg(target_os = "vxworks")] { mod vxworks; diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs index 964abe8b8c9ea..1b71905aa09b7 100644 --- a/library/std/src/sys/unix/alloc.rs +++ b/library/std/src/sys/unix/alloc.rs @@ -1,6 +1,6 @@ use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; -use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN}; +use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/windows/alloc.rs b/library/std/src/sys/windows/alloc.rs index af93cd7a3e27d..2fe71f9f28d5c 100644 --- a/library/std/src/sys/windows/alloc.rs +++ b/library/std/src/sys/windows/alloc.rs @@ -5,7 +5,7 @@ use crate::ffi::c_void; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sys::c; -use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN}; +use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[cfg(test)] mod tests; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 660f0e0df9732..9700d1f6daa61 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -46,7 +46,6 @@ macro_rules! rtunwrap { }; } -pub mod alloc; pub mod at_exit_imp; pub mod backtrace; pub mod bytestring; From cac0dd63b3514569ce79480b0cdf92335c5cf9f4 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Wed, 14 Apr 2021 14:03:00 +0200 Subject: [PATCH 12/16] Update documentation --- library/std/src/sys/common/alloc.rs | 2 -- library/std/src/sys/common/mod.rs | 12 ++++++++++++ library/std/src/sys_common/mod.rs | 8 +++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 6c1bc0d839ad3..2a54e99020e38 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - use crate::alloc::{GlobalAlloc, Layout, System}; use crate::cmp; use crate::ptr; diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs index 920965d5944d7..ff64d2aa82515 100644 --- a/library/std/src/sys/common/mod.rs +++ b/library/std/src/sys/common/mod.rs @@ -1 +1,13 @@ +// This module contains code that is shared between all platforms, mostly utility or fallback code. +// This explicitly does not include code that is shared between only a few platforms, +// such as when reusing an implementation from `unix` or `unsupported`. +// In those cases the desired code should be included directly using the #[path] attribute, +// not moved to this module. +// +// Currently `sys_common` contains a lot of code that should live in this module, +// ideally `sys_common` would only contain platform-independent abstractions on top of `sys`. +// Progress on this is tracked in #84187. + +#![allow(dead_code)] + pub mod alloc; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 9700d1f6daa61..23a3a0e907dcf 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -8,9 +8,11 @@ //! rest of `std` is complex, with dependencies going in all //! directions: `std` depending on `sys_common`, `sys_common` //! depending on `sys`, and `sys` depending on `sys_common` and `std`. -//! Ideally `sys_common` would be split into two and the dependencies -//! between them all would form a dag, facilitating the extraction of -//! `std::sys` from the standard library. +//! This is because `sys_common` not only contains platform-independent code, +//! but also code that is shared between the different platforms in `sys`. +//! Ideally all that shared code should be moved to `sys::common`, +//! and the dependencies between `std`, `sys_common` and `sys` all would form a dag. +//! Progress on this is tracked in #84187. #![allow(missing_docs)] #![allow(missing_debug_implementations)] From 7b14eda52207a8e17d2e82b915512a232f76bbec Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Wed, 14 Apr 2021 22:16:56 +0800 Subject: [PATCH 13/16] test: add more cases --- ...acro-pat-pattern-followed-by-or-in-2021.rs | 20 ++++++++++++++ ...-pat-pattern-followed-by-or-in-2021.stderr | 26 +++++++++++++++++++ .../macro-pat-pattern-followed-by-or.rs | 20 ++++++++++++++ ...> macro-pat2021-pattern-followed-by-or.rs} | 0 ...cro-pat2021-pattern-followed-by-or.stderr} | 6 ++--- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr create mode 100644 src/test/ui/macros/macro-pat-pattern-followed-by-or.rs rename src/test/ui/macros/{macro-or-patterns-2021.rs => macro-pat2021-pattern-followed-by-or.rs} (100%) rename src/test/ui/macros/{macro-or-patterns-2021.stderr => macro-pat2021-pattern-followed-by-or.stderr} (84%) diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs new file mode 100644 index 0000000000000..20bfe7d7af704 --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs @@ -0,0 +1,20 @@ +// edition:2021 +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! qux { ($x:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr new file mode 100644 index 0000000000000..a5987a25551d2 --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr @@ -0,0 +1,26 @@ +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32 + | +LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36 + | +LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs new file mode 100644 index 0000000000000..c2658cdbffce9 --- /dev/null +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok +macro_rules! qux { ($x:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { // should be ok + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/src/test/ui/macros/macro-or-patterns-2021.rs b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs similarity index 100% rename from src/test/ui/macros/macro-or-patterns-2021.rs rename to src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs diff --git a/src/test/ui/macros/macro-or-patterns-2021.stderr b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr similarity index 84% rename from src/test/ui/macros/macro-or-patterns-2021.stderr rename to src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr index 67feb0c2891f1..fe0b40cd86e12 100644 --- a/src/test/ui/macros/macro-or-patterns-2021.stderr +++ b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr @@ -1,5 +1,5 @@ error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments - --> $DIR/macro-or-patterns-2021.rs:3:32 + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:3:32 | LL | macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} } | ^ not allowed after `pat2021` fragments @@ -7,7 +7,7 @@ LL | macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} } = note: allowed there are: `=>`, `,`, `=`, `if` or `in` error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments - --> $DIR/macro-or-patterns-2021.rs:6:32 + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:6:32 | LL | macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} } | ^ not allowed after `pat2021` fragments @@ -15,7 +15,7 @@ LL | macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} } = note: allowed there are: `=>`, `,`, `=`, `if` or `in` error: `$pat:pat2021` may be followed by `|`, which is not allowed for `pat2021` fragments - --> $DIR/macro-or-patterns-2021.rs:8:40 + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:8:40 | LL | ( $expr:expr , $( $( $pat:pat2021 )|+ => $expr_arm:pat2021 ),+ ) => { | ^ not allowed after `pat2021` fragments From eb944c1466c4bfac0315a0f9e7727454147100a4 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Wed, 14 Apr 2021 22:31:44 +0800 Subject: [PATCH 14/16] test: add reasonable case --- src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs | 2 +- src/test/ui/macros/macro-pat-pattern-followed-by-or.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs index 20bfe7d7af704..f5a97eca21bdb 100644 --- a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs @@ -2,7 +2,7 @@ #![allow(unused_macros)] macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments -macro_rules! qux { ($x:pat) => {} } // should be ok +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok macro_rules! match_any { ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments match $expr { diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs index c2658cdbffce9..54bd13d7ebce8 100644 --- a/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs +++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs @@ -2,7 +2,7 @@ #![allow(unused_macros)] macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok -macro_rules! qux { ($x:pat) => {} } // should be ok +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok macro_rules! match_any { ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { // should be ok match $expr { From e6fd96df983bf0e7f6622ebe80db453e5202a31b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 14 Apr 2021 08:24:06 -0700 Subject: [PATCH 15/16] Update books --- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/embedded-book b/src/doc/embedded-book index d3f2ace94d516..569c3391f5c0c 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit d3f2ace94d51610cf3e3c265705bb8416d37f8e4 +Subproject commit 569c3391f5c0cc43433bc77831d17f8ff4d76602 diff --git a/src/doc/nomicon b/src/doc/nomicon index 6fe476943afd5..8551afbb2ca6f 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 6fe476943afd53a9a6e91f38a6ea7bb48811d8ff +Subproject commit 8551afbb2ca6f5ea37fe58380318b209785e4e02 diff --git a/src/doc/reference b/src/doc/reference index fd97729e2d82f..e1abb17cd94cd 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit fd97729e2d82f8b08d68a31c9bfdf0c37a7fd542 +Subproject commit e1abb17cd94cd5a8a374b48e1bc8134a2208ed48 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 29d91f591c90d..c80f0b09fc15b 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 29d91f591c90dd18fdca6d23f1a9caf9c139d0d7 +Subproject commit c80f0b09fc15b9251825343be910c08531938ab2 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 0687daac28939..a9bd2bbf31e4f 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 0687daac28939c476df51778f5a1d1aff1a3fddf +Subproject commit a9bd2bbf31e4f92b5d3d8e80b22839d0cc7a2022 From 26da4b43554482f5a25f79a3923f46bfe5cacd41 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 14 Apr 2021 16:25:16 +0100 Subject: [PATCH 16/16] Fix typos in rustc_codegen_ssa/src/back/write.rs. --- compiler/rustc_codegen_ssa/src/back/write.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 04d06864ee14f..c8688faa80bc3 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1094,7 +1094,7 @@ fn start_executing_work( // only place where we have access to the compiler `Session`. // - LLVM work can be done on any thread. // - Codegen can only happen on the main thread. - // - Each thread doing substantial work most be in possession of a `Token` + // - Each thread doing substantial work must be in possession of a `Token` // from the `Jobserver`. // - The compiler process always holds one `Token`. Any additional `Tokens` // have to be requested from the `Jobserver`. @@ -1146,7 +1146,7 @@ fn start_executing_work( // if possible. These two goals are at odds with each other: If memory // consumption were not an issue, we could just let the main thread produce // LLVM WorkItems at full speed, assuring maximal utilization of - // Tokens/LLVM worker threads. However, since codegen usual is faster + // Tokens/LLVM worker threads. However, since codegen is usually faster // than LLVM processing, the queue of LLVM WorkItems would fill up and each // WorkItem potentially holds on to a substantial amount of memory. //