From c88e6a75f5f681610142aaba351cdd6e30deed95 Mon Sep 17 00:00:00 2001 From: Carsten Andrich Date: Fri, 1 May 2020 17:52:16 +0200 Subject: [PATCH 01/27] add Windows system error codes that map to io::ErrorKind::TimedOut --- src/libstd/io/error.rs | 5 +++++ src/libstd/sys/windows/c.rs | 17 +++++++++++++++-- src/libstd/sys/windows/mod.rs | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index d80a38819ead0..f7248e7547e27 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -160,6 +160,11 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] Interrupted, /// Any I/O error not part of this list. + /// + /// Errors that are `Other` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Other` and to expect any additional characteristics, + /// e.g., a specific [`Error::raw_os_error`] return value. #[stable(feature = "rust1", since = "1.0.0")] Other, diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 134f508dfab09..d2c4cc3bbff53 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -171,13 +171,26 @@ pub const ERROR_FILE_EXISTS: DWORD = 80; pub const ERROR_INVALID_PARAMETER: DWORD = 87; pub const ERROR_BROKEN_PIPE: DWORD = 109; pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; +pub const ERROR_SEM_TIMEOUT: DWORD = 121; pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; pub const ERROR_ALREADY_EXISTS: DWORD = 183; -pub const ERROR_NO_DATA: DWORD = 232; pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; +pub const ERROR_NO_DATA: DWORD = 232; +pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; pub const ERROR_OPERATION_ABORTED: DWORD = 995; pub const ERROR_IO_PENDING: DWORD = 997; -pub const ERROR_TIMEOUT: DWORD = 0x5B4; +pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; +pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; +pub const ERROR_TIMEOUT: DWORD = 1460; +pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; +pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; +pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; +pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; +pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; +pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; +pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; +pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index d745e87a07258..a0d207e932e2c 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,7 +61,22 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, + c::ERROR_SEM_TIMEOUT => return ErrorKind::TimedOut, + c::WAIT_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_DRIVER_CANCEL_TIMEOUT => return ErrorKind::TimedOut, c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut, + c::ERROR_SERVICE_REQUEST_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_COUNTER_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_RESOURCE_CALL_TIMED_OUT => return ErrorKind::TimedOut, + c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_CTX_CLIENT_QUERY_TIMEOUT => return ErrorKind::TimedOut, + c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_DS_TIMELIMIT_EXCEEDED => return ErrorKind::TimedOut, + c::DNS_ERROR_RECORD_TIMED_OUT => return ErrorKind::TimedOut, + c::ERROR_IPSEC_IKE_TIMED_OUT => return ErrorKind::TimedOut, + c::ERROR_RUNLEVEL_SWITCH_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, _ => {} } From 86679967e3cc895d2b5ab4bb974664ff283fe043 Mon Sep 17 00:00:00 2001 From: Carsten Andrich Date: Sat, 2 May 2020 10:56:42 +0200 Subject: [PATCH 02/27] use or pattern to match error codes that map to ErrorKind::TimedOut --- src/libstd/sys/windows/mod.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index a0d207e932e2c..b34686d42b7c9 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,21 +61,21 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, - c::ERROR_SEM_TIMEOUT => return ErrorKind::TimedOut, - c::WAIT_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_DRIVER_CANCEL_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut, - c::ERROR_SERVICE_REQUEST_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_COUNTER_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_RESOURCE_CALL_TIMED_OUT => return ErrorKind::TimedOut, - c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_CTX_CLIENT_QUERY_TIMEOUT => return ErrorKind::TimedOut, - c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_DS_TIMELIMIT_EXCEEDED => return ErrorKind::TimedOut, - c::DNS_ERROR_RECORD_TIMED_OUT => return ErrorKind::TimedOut, - c::ERROR_IPSEC_IKE_TIMED_OUT => return ErrorKind::TimedOut, - c::ERROR_RUNLEVEL_SWITCH_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_SEM_TIMEOUT | + c::WAIT_TIMEOUT | + c::ERROR_DRIVER_CANCEL_TIMEOUT | + c::ERROR_OPERATION_ABORTED | + c::ERROR_SERVICE_REQUEST_TIMEOUT | + c::ERROR_COUNTER_TIMEOUT | + c::ERROR_TIMEOUT | + c::ERROR_RESOURCE_CALL_TIMED_OUT | + c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT | + c::ERROR_CTX_CLIENT_QUERY_TIMEOUT | + c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT | + c::ERROR_DS_TIMELIMIT_EXCEEDED | + c::DNS_ERROR_RECORD_TIMED_OUT | + c::ERROR_IPSEC_IKE_TIMED_OUT | + c::ERROR_RUNLEVEL_SWITCH_TIMEOUT | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, _ => {} } From c69d6c84c7042d767e55f69ff544de0098a6042f Mon Sep 17 00:00:00 2001 From: Carsten Andrich Date: Sat, 2 May 2020 14:05:56 +0200 Subject: [PATCH 03/27] fix formatting issues that fail tidy test --- src/libstd/sys/windows/mod.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index b34686d42b7c9..712085dbba4e4 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -61,22 +61,22 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, - c::ERROR_SEM_TIMEOUT | - c::WAIT_TIMEOUT | - c::ERROR_DRIVER_CANCEL_TIMEOUT | - c::ERROR_OPERATION_ABORTED | - c::ERROR_SERVICE_REQUEST_TIMEOUT | - c::ERROR_COUNTER_TIMEOUT | - c::ERROR_TIMEOUT | - c::ERROR_RESOURCE_CALL_TIMED_OUT | - c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT | - c::ERROR_CTX_CLIENT_QUERY_TIMEOUT | - c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT | - c::ERROR_DS_TIMELIMIT_EXCEEDED | - c::DNS_ERROR_RECORD_TIMED_OUT | - c::ERROR_IPSEC_IKE_TIMED_OUT | - c::ERROR_RUNLEVEL_SWITCH_TIMEOUT | - c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, + c::ERROR_SEM_TIMEOUT + | c::WAIT_TIMEOUT + | c::ERROR_DRIVER_CANCEL_TIMEOUT + | c::ERROR_OPERATION_ABORTED + | c::ERROR_SERVICE_REQUEST_TIMEOUT + | c::ERROR_COUNTER_TIMEOUT + | c::ERROR_TIMEOUT + | c::ERROR_RESOURCE_CALL_TIMED_OUT + | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT + | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT + | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT + | c::ERROR_DS_TIMELIMIT_EXCEEDED + | c::DNS_ERROR_RECORD_TIMED_OUT + | c::ERROR_IPSEC_IKE_TIMED_OUT + | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT + | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, _ => {} } From b97487bad8608afe05f34f07016aa6276c1a291d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 30 May 2020 15:36:42 +0200 Subject: [PATCH 04/27] Add check for doc alias attribute format --- src/librustdoc/clean/types.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 381238165274d..4f99476ebfa55 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -481,6 +481,33 @@ impl Attributes { }) } + /// Enforce the format of attributes inside `#[doc(...)]`. + pub fn check_doc_attributes( + diagnostic: &::rustc_errors::Handler, + mi: &ast::MetaItem, + ) -> Option<(String, String)> { + mi.meta_item_list().and_then(|list| { + for meta in list { + if meta.check_name(sym::alias) { + if !meta.is_value_str() + || meta + .value_str() + .map(|s| s.to_string()) + .unwrap_or_else(String::new) + .is_empty() + { + diagnostic.span_err( + meta.span(), + "doc alias attribute expects a string: #[doc(alias = \"0\")]", + ); + } + } + } + + None + }) + } + pub fn has_doc_flag(&self, flag: Symbol) -> bool { for attr in &self.other_attrs { if !attr.check_name(sym::doc) { @@ -524,6 +551,7 @@ impl Attributes { } else { if attr.check_name(sym::doc) { if let Some(mi) = attr.meta() { + Attributes::check_doc_attributes(&diagnostic, &mi); if let Some(cfg_mi) = Attributes::extract_cfg(&mi) { // Extracted #[doc(cfg(...))] match Cfg::parse(cfg_mi) { From 2d6267a7a8ae0399f2d363b6ac667fee0b53a1a0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 30 May 2020 15:36:57 +0200 Subject: [PATCH 05/27] Add test for doc alias attribute validation --- src/test/rustdoc-ui/check-doc-alias-attr.rs | 9 +++++++++ .../rustdoc-ui/check-doc-alias-attr.stderr | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/rustdoc-ui/check-doc-alias-attr.rs create mode 100644 src/test/rustdoc-ui/check-doc-alias-attr.stderr diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.rs b/src/test/rustdoc-ui/check-doc-alias-attr.rs new file mode 100644 index 0000000000000..2f01099107d9e --- /dev/null +++ b/src/test/rustdoc-ui/check-doc-alias-attr.rs @@ -0,0 +1,9 @@ +#![feature(doc_alias)] + +#[doc(alias = "foo")] // ok! +pub struct Bar; + +#[doc(alias)] //~ ERROR +#[doc(alias = 0)] //~ ERROR +#[doc(alias("bar"))] //~ ERROR +pub struct Foo; diff --git a/src/test/rustdoc-ui/check-doc-alias-attr.stderr b/src/test/rustdoc-ui/check-doc-alias-attr.stderr new file mode 100644 index 0000000000000..480acc821aaa8 --- /dev/null +++ b/src/test/rustdoc-ui/check-doc-alias-attr.stderr @@ -0,0 +1,20 @@ +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:6:7 + | +LL | #[doc(alias)] + | ^^^^^ + +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:7:7 + | +LL | #[doc(alias = 0)] + | ^^^^^^^^^ + +error: doc alias attribute expects a string: #[doc(alias = "0")] + --> $DIR/check-doc-alias-attr.rs:8:7 + | +LL | #[doc(alias("bar"))] + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + From e27a8b59ed8046c9a9c73b680e0f767f4252077d Mon Sep 17 00:00:00 2001 From: Carsten Andrich Date: Sat, 13 Jun 2020 10:02:52 +0200 Subject: [PATCH 06/27] add link list of error codes on docs.microsoft.com --- src/libstd/sys/windows/c.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index d2c4cc3bbff53..4d7177226aaa8 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -161,6 +161,8 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; pub const PROGRESS_CONTINUE: DWORD = 0; +// List of Windows system error codes with descriptions: +// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes pub const ERROR_FILE_NOT_FOUND: DWORD = 2; pub const ERROR_PATH_NOT_FOUND: DWORD = 3; pub const ERROR_ACCESS_DENIED: DWORD = 5; From 1d08b1b0421cc287218196e5fdd144b3e82a482a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 18 Jun 2020 13:10:22 +0200 Subject: [PATCH 07/27] Clean up E0689 explanation --- src/librustc_error_codes/error_codes/E0689.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0689.md b/src/librustc_error_codes/error_codes/E0689.md index 26c2c15ccfaac..a680a20421127 100644 --- a/src/librustc_error_codes/error_codes/E0689.md +++ b/src/librustc_error_codes/error_codes/E0689.md @@ -1,13 +1,16 @@ -This error indicates that the numeric value for the method being passed exists -but the type of the numeric value or binding could not be identified. +A method was called on an ambiguous numeric type. -The error happens on numeric literals: +Erroneous code example: ```compile_fail,E0689 -2.0.neg(); +2.0.neg(); // error! ``` -and on numeric bindings without an identified concrete type: +This error indicates that the numeric value for the method being passed exists +but the type of the numeric value or binding could not be identified. + +The error happens on numeric literals and on numeric bindings without an +identified concrete type: ```compile_fail,E0689 let x = 2.0; @@ -19,8 +22,8 @@ Because of this, you must give the numeric literal or binding a type: ``` use std::ops::Neg; -let _ = 2.0_f32.neg(); +let _ = 2.0_f32.neg(); // ok! let x: f32 = 2.0; -let _ = x.neg(); -let _ = (2.0 as f32).neg(); +let _ = x.neg(); // ok! +let _ = (2.0 as f32).neg(); // ok! ``` From 9245ba83047b14fc7c9cef4c7d2bf37828c445b6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 12 Jun 2020 19:25:14 +0200 Subject: [PATCH 08/27] Remove the const_raw_ptr_comparison feature gate. We can never supply a meaningful implementation of this. Instead, the follow up commits will create two intrinsics that approximate comparisons: * `ptr_maybe_eq` * `ptr_maybe_ne` The fact that `ptr_maybe_eq(a, b)` is not necessarily the same value as `!ptr_maybe_ne(a, b)` is a symptom of this entire problem. --- src/librustc_feature/active.rs | 3 -- src/librustc_feature/removed.rs | 5 ++ .../transform/check_consts/ops.rs | 26 +++++++---- src/librustc_mir/transform/check_unsafety.rs | 15 ------ src/librustc_typeck/collect/type_of.rs | 26 +++++------ .../ui/const-generics/fn-const-param-call.rs | 7 ++- .../const-generics/fn-const-param-call.stderr | 18 ++++++-- .../ui/const-generics/fn-const-param-infer.rs | 11 +++-- .../fn-const-param-infer.stderr | 41 +++-------------- .../raw-ptr-const-param-deref.rs | 7 ++- .../raw-ptr-const-param-deref.stderr | 18 ++++++-- .../ui/const-generics/raw-ptr-const-param.rs | 6 +-- .../const-generics/raw-ptr-const-param.stderr | 14 ++---- .../ui/consts/const-eval/const_raw_ptr_ops.rs | 15 +----- .../const-eval/const_raw_ptr_ops.stderr | 46 +++++-------------- .../consts/const-eval/const_raw_ptr_ops2.rs | 13 ++++++ .../const-eval/const_raw_ptr_ops2.stderr | 28 +++++++++++ .../consts/const-eval/promoted_raw_ptr_ops.rs | 2 +- .../ui/consts/miri_unleashed/ptr_arith.stderr | 2 +- src/test/ui/error-codes/E0395.rs | 4 +- src/test/ui/error-codes/E0395.stderr | 9 ++-- .../feature-gate-const_generics-ptr.rs | 4 +- .../feature-gate-const_generics-ptr.stderr | 10 +--- src/test/ui/issues/issue-25826.rs | 2 +- src/test/ui/issues/issue-25826.stderr | 7 ++- .../ui/unsafe/unsafe-unstable-const-fn.rs | 8 ++-- .../ui/unsafe/unsafe-unstable-const-fn.stderr | 8 ++-- 27 files changed, 165 insertions(+), 190 deletions(-) create mode 100644 src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs create mode 100644 src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index d186f35a12b5a..f167ed97f57e2 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -401,9 +401,6 @@ declare_features! ( /// Allows dereferencing raw pointers during const eval. (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), - /// Allows comparing raw pointers during const eval. - (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - /// Allows `#[doc(alias = "...")]`. (active, doc_alias, "1.27.0", Some(50146), None), diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs index 4e348054fbd4b..8d410894e8b19 100644 --- a/src/librustc_feature/removed.rs +++ b/src/librustc_feature/removed.rs @@ -113,6 +113,11 @@ declare_features! ( Some("removed in favor of `#![feature(marker_trait_attr)]`")), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + + /// Allows comparing raw pointers during const eval. + (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, + Some("cannot be allowed in const eval in any meaningful way")), + // ------------------------------------------------------------------------- // feature-group-end: removed features // ------------------------------------------------------------------------- diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index d5059c98c9511..f09b598ce069d 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -284,18 +284,24 @@ impl NonConstOp for Panic { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn feature_gate() -> Option { - Some(sym::const_compare_raw_pointers) - } - fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_compare_raw_pointers, + let mut err = ccx.tcx.sess.struct_span_err( span, - &format!("comparing raw pointers inside {}", ccx.const_kind()), - ) - .emit(); + "pointers cannot be compared in a meaningful way during const eval.", + ); + err.note( + "It is conceptually impossible for const eval to know in all cases whether two \ + pointers are equal. While sometimes it is clear (the address of a static item \ + is never equal to the address of another static item), comparing an integer \ + address with any allocation's address is impossible to do at compile-time.", + ); + err.note( + "That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all \ + comparisons where CTFE isn't sure whether two addresses are equal. The mirror \ + intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't \ + sure whether two addresses are inequal.", + ); + err.emit(); } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 7dbb2ebad8b99..ac7acff1eca9e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -171,21 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { _ => {} } } - // raw pointer and fn pointer operations are unsafe as it is not clear whether one - // pointer would be "less" or "equal" to another, because we cannot know where llvm - // or the linker will place various statics in memory. Without this information the - // result of a comparison of addresses would differ between runtime and compile-time. - Rvalue::BinaryOp(_, ref lhs, _) - if self.const_context && self.tcx.features().const_compare_raw_pointers => - { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { - self.require_unsafe( - "pointer operation", - "operations on pointers in constants", - UnsafetyViolationKind::General, - ); - } - } _ => {} } self.super_rvalue(rvalue, location); diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index cf5f2ec69d8d8..3dd9c9c5c39db 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -10,8 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits; @@ -303,25 +302,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), GenericParamKind::Const { ty: ref hir_ty, .. } => { let ty = icx.to_ty(hir_ty); - if !tcx.features().const_compare_raw_pointers { - let err = match ty.peel_refs().kind { - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => None, - }; - if let Some(unsupported_type) = err { - feature_err( - &tcx.sess.parse_sess, - sym::const_compare_raw_pointers, + let err = match ty.peel_refs().kind { + ty::FnPtr(_) => Some("function pointers"), + ty::RawPtr(_) => Some("raw pointers"), + _ => None, + }; + if let Some(unsupported_type) = err { + tcx.sess + .struct_span_err( hir_ty.span, &format!( - "using {} as const generic parameters is unstable", + "using {} as const generic parameters is forbidden", unsupported_type ), ) .emit(); - }; - } + }; if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty) .is_some() { diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index afa577fa67ff2..90c438b05cb81 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,15 +1,14 @@ -// run-pass - -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete fn function() -> u32 { 17 } -struct Wrapper u32>; +struct Wrapper u32>; //~ ERROR: using function pointers as const generic parameters impl u32> Wrapper { +//~^ ERROR: using function pointers as const generic parameters fn call() -> u32 { F() } diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 9c0f7e3ab9b87..b5811243caa8a 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fn-const-param-call.rs:3:12 + --> $DIR/fn-const-param-call.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:8:25 + | +LL | struct Wrapper u32>; + | ^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:10:15 + | +LL | impl u32> Wrapper { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 08f6e0db31cae..14fa3b494b3fc 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,7 +1,8 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete struct Checked bool>; +//~^ ERROR: using function pointers as const generic parameters fn not_one(val: usize) -> bool { val != 1 } fn not_two(val: usize) -> bool { val != 2 } @@ -13,14 +14,14 @@ fn generic(val: usize) -> bool { val != 1 } fn main() { let _: Option> = None; let _: Checked = Checked::; - let _: Checked = Checked::; //~ mismatched types + let _: Checked = Checked::; let _ = Checked::; let _ = Checked::<{generic_arg::}>; - let _ = Checked::<{generic_arg::}>; //~ mismatched types + let _ = Checked::<{generic_arg::}>; - let _ = Checked::; //~ type annotations needed + let _ = Checked::; let _ = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; - let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types + let _: Checked<{generic::}> = Checked::<{generic::}>; } diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index de41d2984a655..7aaa41eb7d7b1 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,46 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-const-param-infer.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:16:31 +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:4:25 | -LL | let _: Checked = Checked::; - | ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` - | - = note: expected type `{not_one as fn(usize) -> bool}` - found type `{not_two as fn(usize) -> bool}` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:20:24 - | -LL | let _ = Checked::<{generic_arg::}>; - | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` - | - = note: expected fn pointer `fn(usize) -> _` - found fn item `fn(u32) -> _ {generic_arg::}` - -error[E0282]: type annotations needed - --> $DIR/fn-const-param-infer.rs:22:23 - | -LL | let _ = Checked::; - | ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic` - -error[E0308]: mismatched types - --> $DIR/fn-const-param-infer.rs:25:40 - | -LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` - | - = note: expected type `{generic:: as fn(usize) -> bool}` - found type `{generic:: as fn(usize) -> bool}` +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted -Some errors have detailed explanations: E0282, E0308. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index c498bfe2e9781..97ca9d6a44c9e 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -1,12 +1,11 @@ -// run-pass -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete const A: u32 = 3; -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters -impl Const

{ +impl Const

{ //~ ERROR: using raw pointers as const generic parameters fn get() -> u32 { unsafe { *P diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr index 1ffc63ffdac03..1ce8bb9c05423 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -1,11 +1,23 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/raw-ptr-const-param-deref.rs:2:12 + --> $DIR/raw-ptr-const-param-deref.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -warning: 1 warning emitted +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:6:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:8:15 + | +LL | impl Const

{ + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index d7d970e952b65..237b410e073d6 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,9 +1,9 @@ -#![feature(const_generics, const_compare_raw_pointers)] +#![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete -struct Const; +struct Const; //~ ERROR: using raw pointers as const generic parameters fn main() { - let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; } diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 7a665397c1207..6e64f8a327fd5 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,21 +1,17 @@ warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/raw-ptr-const-param.rs:1:12 | -LL | #![feature(const_generics, const_compare_raw_pointers)] +LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #44580 for more information -error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:40 +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:4:23 | -LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` - | - = note: expected type `{0xf as *const u32}` - found type `{0xa as *const u32}` +LL | struct Const; + | ^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 9be1374f85d99..91c4bc8972ca5 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -1,17 +1,6 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] - fn main() {} // unconst and bad, will thus error in miri -const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this -// unconst and bad, will thus error in miri -const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this -// unconst and fine -const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; -// unconst and bad, will thus error in miri -const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this -// unconst and fine -const Z: i32 = unsafe { *(&1 as *const i32) }; +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be compared // unconst and bad, will thus error in miri -const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause -const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be compared diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index cc40728e6b574..dee555beca0ca 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -1,44 +1,20 @@ -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:6:26 +error: pointers cannot be compared in a meaningful way during const eval. + --> $DIR/const_raw_ptr_ops.rs:4:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; - | -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[deny(const_err)]` on by default + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:8:27 +error: pointers cannot be compared in a meaningful way during const eval. + --> $DIR/const_raw_ptr_ops.rs:6:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; - | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:12:28 - | -LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; - | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:16:26 - | -LL | const Z2: i32 = unsafe { *(42 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops.rs:17:26 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | const Z3: i32 = unsafe { *(44 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs new file mode 100644 index 0000000000000..d2a7623837a23 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -0,0 +1,13 @@ +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] + +fn main() {} + +// unconst and fine +const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; +// unconst and bad, will thus error in miri +const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this +// unconst and fine +const Z: i32 = unsafe { *(&1 as *const i32) }; +// unconst and bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr new file mode 100644 index 0000000000000..93f2261745d6f --- /dev/null +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -0,0 +1,28 @@ +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:8:28 + | +LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; + | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- + | | + | "pointer-to-integer cast" needs an rfc before being allowed inside constants + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:12:26 + | +LL | const Z2: i32 = unsafe { *(42 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: any use of this value will cause an error + --> $DIR/const_raw_ptr_ops2.rs:13:26 + | +LL | const Z3: i32 = unsafe { *(44 as *const i32) }; + | -------------------------^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs index c6fb5eeab5aec..d724fe3060b21 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -1,4 +1,4 @@ -#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)] +#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] fn main() { let x: &'static bool = &(42 as *const i32 == 43 as *const i32); diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr index 4b3fe9957002e..c5d136ea97dfa 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -12,7 +12,7 @@ LL | let _v = x + 0; warning: skipping const checks | -help: skipping check for `const_compare_raw_pointers` feature +help: skipping check that does not even have a feature gate --> $DIR/ptr_arith.rs:9:14 | LL | let _v = x == x; diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs index bbefff27d7f68..28fba1d306139 100644 --- a/src/test/ui/error-codes/E0395.rs +++ b/src/test/ui/error-codes/E0395.rs @@ -1,10 +1,8 @@ -// gate-test-const_compare_raw_pointers - static FOO: i32 = 42; static BAR: i32 = 42; static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; -//~^ ERROR comparing raw pointers inside static +//~^ ERROR pointers cannot be compared in a meaningful way during const eval fn main() { } diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 20c8622f33726..748126f74407c 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,12 +1,11 @@ -error[E0658]: comparing raw pointers inside static - --> $DIR/E0395.rs:6:29 +error: pointers cannot be compared in a meaningful way during const eval. + --> $DIR/E0395.rs:4:29 | LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs index 1ab11ce3b4423..dc602ba7e6f21 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -1,9 +1,9 @@ struct ConstFn; //~^ ERROR const generics are unstable -//~^^ ERROR using function pointers as const generic parameters is unstable +//~^^ ERROR using function pointers as const generic parameters is forbidden struct ConstPtr; //~^ ERROR const generics are unstable -//~^^ ERROR using raw pointers as const generic parameters is unstable +//~^^ ERROR using raw pointers as const generic parameters is forbidden fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr index dc7ef55e7ab99..b2c96d3810f98 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -16,23 +16,17 @@ LL | struct ConstPtr; = note: see issue #44580 for more information = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: using function pointers as const generic parameters is unstable +error: using function pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:1:25 | LL | struct ConstFn; | ^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable -error[E0658]: using raw pointers as const generic parameters is unstable +error: using raw pointers as const generic parameters is forbidden --> $DIR/feature-gate-const_generics-ptr.rs:5:26 | LL | struct ConstPtr; | ^^^^^^^^^^ - | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs index 36a69cf4c22ff..cb0dfcfa953e4 100644 --- a/src/test/ui/issues/issue-25826.rs +++ b/src/test/ui/issues/issue-25826.rs @@ -1,6 +1,6 @@ fn id(t: T) -> T { t } fn main() { const A: bool = unsafe { id:: as *const () < id:: as *const () }; - //~^ ERROR comparing raw pointers inside constant + //~^ ERROR pointers cannot be compared in a meaningful way during const eval println!("{}", A); } diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index 3a5a6b509ba9d..b3692098341e7 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -1,12 +1,11 @@ -error[E0658]: comparing raw pointers inside constant +error: pointers cannot be compared in a meaningful way during const eval. --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #53020 for more information - = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs index d9d85ee913266..963d892931a75 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs @@ -1,13 +1,13 @@ #![stable(feature = "foo", since = "1.33.0")] #![feature(staged_api)] -#![feature(const_compare_raw_pointers)] +#![feature(const_raw_ptr_deref)] #![feature(const_fn)] #[stable(feature = "foo", since = "1.33.0")] #[rustc_const_unstable(feature = "const_foo", issue = "none")] -const fn unstable(a: *const i32, b: *const i32) -> bool { - a == b - //~^ pointer operation is unsafe +const fn unstable(a: *const i32, b: i32) -> bool { + *a == b + //~^ dereference of raw pointer is unsafe } fn main() {} diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr index d8f3737c8f541..4642a7a5fc9f8 100644 --- a/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr +++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.stderr @@ -1,10 +1,10 @@ -error[E0133]: pointer operation is unsafe and requires unsafe function or block +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block --> $DIR/unsafe-unstable-const-fn.rs:9:5 | -LL | a == b - | ^^^^^^ pointer operation +LL | *a == b + | ^^ dereference of raw pointer | - = note: operations on pointers in constants + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: aborting due to previous error From e09b62033926dff8bfedca35b93e0dfbf767749f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 16 Jun 2020 10:37:34 +0200 Subject: [PATCH 09/27] Add fuzzy pointer comparison intrinsics --- src/libcore/intrinsics.rs | 10 +++ src/libcore/lib.rs | 1 + src/libcore/ptr/const_ptr.rs | 66 +++++++++++++++++++ src/libcore/ptr/mut_ptr.rs | 66 +++++++++++++++++++ src/libcore/slice/mod.rs | 50 +++++++++++++- src/librustc_codegen_llvm/intrinsic.rs | 14 +++- src/librustc_mir/interpret/intrinsics.rs | 5 ++ .../transform/check_consts/ops.rs | 22 ++++--- src/librustc_span/symbol.rs | 2 + src/librustc_typeck/check/intrinsic.rs | 9 ++- .../const-eval/const_raw_ptr_ops.stderr | 10 +-- src/test/ui/consts/miri_unleashed/slice_eq.rs | 17 +++++ src/test/ui/error-codes/E0395.stderr | 5 +- src/test/ui/issues/issue-25826.stderr | 5 +- 14 files changed, 260 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/consts/miri_unleashed/slice_eq.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 9061145a695f8..4648f762bab42 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1948,6 +1948,16 @@ extern "rust-intrinsic" { #[cfg(not(bootstrap))] #[lang = "count_code_region"] pub fn count_code_region(index: u32); + + /// See documentation of `<*const T>::guaranteed_eq` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_eq(ptr: *const T, other: *const T) -> bool; + + /// See documentation of `<*const T>::guaranteed_ne` for details. + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[cfg(not(bootstrap))] + pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index fe05e914e6d44..b2f6f789603a9 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,6 +87,7 @@ #![feature(const_generics)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] +#![cfg_attr(not(bootstrap), feature(const_raw_ptr_comparison))] #![feature(const_result)] #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index e39d18d7733a2..0e2e6848416b6 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -295,6 +295,72 @@ impl *const T { intrinsics::ptr_offset_from(self, origin) } + /// Returns whether two pointers are guaranteed equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self, other) + } + + /// Returns whether two pointers are guaranteed not equal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_ne(self, other: *const T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self, other) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 40b5e4e22340e..67ace1f72a0ab 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -273,6 +273,72 @@ impl *mut T { if self.is_null() { None } else { Some(&mut *self) } } + /// Returns whether two pointers are guaranteed equal. + /// + /// At runtime this function behaves like `self == other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine equality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be equal. + /// But when it returns `true`, the pointers are guaranteed to be equal. + /// + /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_ne`]: #method.guaranteed_ne + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const fn guaranteed_eq(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) + } + + /// Returns whether two pointers are guaranteed not equal. + /// + /// At runtime this function behaves like `self != other`. + /// However, in some contexts (e.g., compile-time evaluation), + /// it is not always possible to determine the inequality of two pointers, so this function may + /// spuriously return `false` for pointers that later actually turn out to be inequal. + /// But when it returns `true`, the pointers are guaranteed to be inequal. + /// + /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer + /// comparisons for which both functions return `false`. + /// + /// [`guaranteed_eq`]: #method.guaranteed_eq + /// + /// The return value may change depending on the compiler version and unsafe code may not + /// rely on the result of this function for soundness. It is suggested to only use this function + /// for performance optimizations where spurious `false` return values by this function do not + /// affect the outcome, but just the performance. + /// The consequences of using this method to make runtime and compile-time code behave + /// differently have not been explored. This method should not be used to introduce such + /// differences, and it should also not be stabilized before we have a better understanding + /// of this issue. + /// ``` + #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] + #[inline] + #[cfg(not(bootstrap))] + pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool + where + T: Sized, + { + intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 21ba2b5abcfb6..12932b06d32d4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5946,7 +5946,8 @@ where } } -// Use an equal-pointer optimization when types are `Eq` +// Remove after boostrap bump +#[cfg(bootstrap)] impl SlicePartialEq for [A] where A: PartialEq + Eq, @@ -5964,7 +5965,8 @@ where } } -// Use memcmp for bytewise equality when the types allow +// Remove after boostrap bump +#[cfg(bootstrap)] impl SlicePartialEq for [A] where A: PartialEq + BytewiseEquality, @@ -5983,6 +5985,50 @@ where } } +// Use an equal-pointer optimization when types are `Eq` +#[cfg(not(bootstrap))] +impl SlicePartialEq for [A] +where + A: PartialEq + Eq, +{ + default fn equal(&self, other: &[A]) -> bool { + if self.len() != other.len() { + return false; + } + + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } + + self.iter().zip(other.iter()).all(|(x, y)| x == y) + } +} + +// Use memcmp for bytewise equality when the types allow +#[cfg(not(bootstrap))] +impl SlicePartialEq for [A] +where + A: PartialEq + BytewiseEquality, +{ + fn equal(&self, other: &[A]) -> bool { + if self.len() != other.len() { + return false; + } + + // While performance would suffer if `guaranteed_eq` just returned `false` + // for all arguments, correctness and return value of this function are not affected. + if self.as_ptr().guaranteed_eq(other.as_ptr()) { + return true; + } + unsafe { + let size = mem::size_of_val(self); + memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0 + } + } +} + #[doc(hidden)] // intermediate trait for specialization of slice's PartialOrd trait SlicePartialOrd: Sized { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 95465939070a0..78c29588e2e1b 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -12,7 +12,7 @@ use log::debug; use rustc_ast::ast; use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; -use rustc_codegen_ssa::common::TypeKind; +use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::glue; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -731,6 +731,18 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } + "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + let a = args[0].immediate(); + let b = args[1].immediate(); + let a = self.ptrtoint(a, self.type_isize()); + let b = self.ptrtoint(b, self.type_isize()); + if name == "ptr_guaranteed_eq" { + self.icmp(IntPredicate::IntEQ, a, b) + } else { + self.icmp(IntPredicate::IntNE, a, b) + } + } + "ptr_offset_from" => { let ty = substs.type_at(0); let pointee_size = self.size_of(ty); diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ac28ccd181520..1b4113a61b451 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -291,6 +291,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self); self.write_scalar(offset_ptr, dest)?; } + sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { + // FIXME: return `true` for at least some comparisons where we can reliably + // determine the result of runtime (in)equality tests at compile-time. + self.write_scalar(Scalar::from_bool(false), dest)?; + } sym::ptr_offset_from => { let a = self.read_immediate(args[0])?.to_scalar()?; let b = self.read_immediate(args[1])?.to_scalar()?; diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index f09b598ce069d..9f005c0b4dda8 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -290,17 +290,23 @@ impl NonConstOp for RawPtrComparison { "pointers cannot be compared in a meaningful way during const eval.", ); err.note( - "It is conceptually impossible for const eval to know in all cases whether two \ - pointers are equal. While sometimes it is clear (the address of a static item \ - is never equal to the address of another static item), comparing an integer \ - address with any allocation's address is impossible to do at compile-time.", + "see issue #53020 \ + for more information", ); err.note( - "That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all \ - comparisons where CTFE isn't sure whether two addresses are equal. The mirror \ - intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't \ - sure whether two addresses are inequal.", + "It is conceptually impossible for const eval to know in all cases whether two \ + pointers are equal. While sometimes it is clear (the address of a non-zst static item \ + is never equal to the address of another non-zst static item), comparing an integer \ + address with any allocation's address is impossible to do at compile-time.", ); + if ccx.tcx.sess.parse_sess.unstable_features.is_nightly_build() { + err.note( + "That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` \ + for all comparisons where CTFE is sure that two addresses are equal. The mirror \ + intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where \ + CTFE is sure that two addresses are inequal.", + ); + } err.emit(); } } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 970a26325926c..06d1f36622b94 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -588,6 +588,8 @@ symbols! { proc_macro_non_items, proc_macro_path_invoc, profiler_runtime, + ptr_guaranteed_eq, + ptr_guaranteed_ne, ptr_offset_from, pub_restricted, pure, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3ec6973a17d56..ef6c7c14404a7 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -74,9 +74,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely" - | "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name" => { - hir::Unsafety::Normal - } + | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32" + | "maxnumf64" | "type_name" => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, } } @@ -258,6 +257,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])) } + "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { + (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool) + } + "ptr_offset_from" => { (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize) } diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index dee555beca0ca..6f27ac74ade83 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval. LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. + = note: see issue #53020 for more information + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: pointers cannot be compared in a meaningful way during const eval. --> $DIR/const_raw_ptr_ops.rs:6:27 @@ -13,8 +14,9 @@ error: pointers cannot be compared in a meaningful way during const eval. LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. + = note: see issue #53020 for more information + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/miri_unleashed/slice_eq.rs b/src/test/ui/consts/miri_unleashed/slice_eq.rs new file mode 100644 index 0000000000000..fd843105daf2a --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/slice_eq.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// run-pass + +#![feature(const_raw_ptr_comparison)] + +const EMPTY_SLICE: &[i32] = &[]; +const EMPTY_EQ: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _); +const EMPTY_EQ2: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[] as *const _); +const EMPTY_NE: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[1] as *const _); +const EMPTY_NE2: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _); + +fn main() { + assert!(!EMPTY_EQ); + assert!(!EMPTY_EQ2); + assert!(!EMPTY_NE); + assert!(!EMPTY_NE2); +} diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 748126f74407c..62949cf15e13c 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval. LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. + = note: see issue #53020 for more information + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index b3692098341e7..cb24aede81a2c 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval. LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal. + = note: see issue #53020 for more information + = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. + = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to previous error From 84f1d73182f4882518d5eef067b18b49b49e985a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 18 Jun 2020 10:06:57 +0200 Subject: [PATCH 10/27] Tidy got confused on `rustc_const_unstable` `issue`s --- src/libcore/intrinsics.rs | 8 ++++---- src/tools/tidy/src/features.rs | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 4648f762bab42..2b34e98028232 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -11,7 +11,7 @@ //! In order to make an intrinsic usable at compile-time, one needs to copy the implementation //! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to //! `librustc_mir/interpret/intrinsics.rs` and add a -//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic. +//! `#[rustc_const_unstable(feature = "foo2", issue = "01234")]` to the intrinsic. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, //! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done @@ -1012,7 +1012,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::type_name`](../../std/any/fn.type_name.html) - #[rustc_const_unstable(feature = "const_type_name", issue = "none")] + #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This @@ -1021,7 +1021,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) - #[rustc_const_unstable(feature = "const_type_id", issue = "none")] + #[rustc_const_unstable(feature = "const_type_id", issue = "41875")] pub fn type_id() -> u64; /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited: @@ -1931,7 +1931,7 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")] + #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index d9320e9147cff..3fa637b5a696f 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -444,10 +444,7 @@ fn map_lib_features( level: Status::Unstable, since: None, has_gate_test: false, - // FIXME(#57563): #57563 is now used as a common tracking issue, - // although we would like to have specific tracking issues for each - // `rustc_const_unstable` in the future. - tracking_issue: NonZeroU32::new(57563), + tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), }; mf(Ok((feature_name, feature)), file, i + 1); continue; From a10e07c1405cd26c3d65df57d5e11de5688a1763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jun 2020 22:45:09 -0700 Subject: [PATCH 11/27] Provide suggestions for some moved value errors When encountering an used moved value where the previous move happened in a `match` or `if let` pattern, suggest using `ref`. Fix #63988. When encountering a `&mut` value that is used in multiple iterations of a loop, suggest reborrowing it with `&mut *`. Fix #62112. --- .../diagnostics/conflict_errors.rs | 38 +++++++++++++++++-- .../diagnostics/explain_borrow.rs | 4 +- .../borrow_check/diagnostics/mod.rs | 17 +++++++-- src/test/ui/borrowck/move-in-pattern.fixed | 13 +++++++ src/test/ui/borrowck/move-in-pattern.rs | 13 +++++++ src/test/ui/borrowck/move-in-pattern.stderr | 18 +++++++++ .../ui/borrowck/mut-borrow-in-loop-2.fixed | 35 +++++++++++++++++ src/test/ui/borrowck/mut-borrow-in-loop-2.rs | 35 +++++++++++++++++ .../ui/borrowck/mut-borrow-in-loop-2.stderr | 17 +++++++++ ...can-live-while-the-other-survives-1.stderr | 8 ++++ 10 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/borrowck/move-in-pattern.fixed create mode 100644 src/test/ui/borrowck/move-in-pattern.rs create mode 100644 src/test/ui/borrowck/move-in-pattern.stderr create mode 100644 src/test/ui/borrowck/mut-borrow-in-loop-2.fixed create mode 100644 src/test/ui/borrowck/mut-borrow-in-loop-2.rs create mode 100644 src/test/ui/borrowck/mut-borrow-in-loop-2.stderr diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 2e897647a3beb..7506bdfda3841 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -212,6 +212,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, format!("variable moved due to use{}", move_spans.describe()), ); + if let UseSpans::PatUse(span) = move_spans { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "borrow this field in the pattern to avoid moving {}", + self.describe_place(moved_place.as_ref()) + .map(|n| format!("`{}`", n)) + .unwrap_or_else(|| "the value".to_string()) + ), + "ref ".to_string(), + Applicability::MachineApplicable, + ); + } } } if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { @@ -256,11 +269,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => true, }; - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + + if is_loop_move { + if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind { + // We have a `&mut` ref, we need to reborrow on each iteration (#62112). + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "consider creating a fresh reborrow of {} here", + self.describe_place(moved_place) + .map(|n| format!("`{}`", n)) + .unwrap_or_else(|| "the mutable reference".to_string()), + ), + "&mut *".to_string(), + Applicability::MachineApplicable, + ); + } + } - let ty = place.ty(self.body, self.infcx.tcx).ty; + if needs_note { let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs index d04059ff0fc7f..b591b938b5ac3 100644 --- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs +++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs @@ -509,7 +509,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Used in a closure. (LaterUseKind::ClosureCapture, var_span) } - UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => { + UseSpans::PatUse(span) + | UseSpans::OtherUse(span) + | UseSpans::FnSelfUse { var_span: span, .. } => { let block = &self.body.basic_blocks()[location.block]; let kind = if let Some(&Statement { diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 04f48cd658230..edfaae533ef03 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -558,7 +558,9 @@ pub(super) enum UseSpans { fn_span: Span, kind: FnSelfUseKind, }, - // This access has a single span associated to it: common case. + /// This access is caused by a `match` or `if let` pattern. + PatUse(Span), + /// This access has a single span associated to it: common case. OtherUse(Span), } @@ -577,6 +579,7 @@ impl UseSpans { match self { UseSpans::ClosureUse { args_span: span, .. } | UseSpans::FnSelfUse { var_span: span, .. } + | UseSpans::PatUse(span) | UseSpans::OtherUse(span) => span, } } @@ -585,6 +588,7 @@ impl UseSpans { match self { UseSpans::ClosureUse { var_span: span, .. } | UseSpans::FnSelfUse { var_span: span, .. } + | UseSpans::PatUse(span) | UseSpans::OtherUse(span) => span, } } @@ -655,7 +659,7 @@ impl UseSpans { match self { closure @ UseSpans::ClosureUse { .. } => closure, fn_self @ UseSpans::FnSelfUse { .. } => fn_self, - UseSpans::OtherUse(_) => if_other(), + UseSpans::PatUse(_) | UseSpans::OtherUse(_) => if_other(), } } } @@ -772,7 +776,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let normal_ret = OtherUse(stmt.source_info.span); + let normal_ret = if let [ProjectionElem::Downcast(..), ProjectionElem::Field(_, _)] = + moved_place.projection + { + PatUse(stmt.source_info.span) + } else { + OtherUse(stmt.source_info.span) + }; // We are trying to find MIR of the form: // ``` @@ -792,6 +802,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => return normal_ret, }; + debug!("move_spans: normal_ret = {:?}", normal_ret); debug!("move_spans: target_temp = {:?}", target_temp); if let Some(Terminator { kind: TerminatorKind::Call { func, args, fn_span, .. }, .. }) = diff --git a/src/test/ui/borrowck/move-in-pattern.fixed b/src/test/ui/borrowck/move-in-pattern.fixed new file mode 100644 index 0000000000000..c44d48163c0c0 --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern.fixed @@ -0,0 +1,13 @@ +// run-rustfix +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +fn main() { + let s = Some(S); + if let Some(ref x) = s { + let _ = x; + } + foo(s); //~ ERROR use of moved value: `s` +} diff --git a/src/test/ui/borrowck/move-in-pattern.rs b/src/test/ui/borrowck/move-in-pattern.rs new file mode 100644 index 0000000000000..910afc01e070b --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern.rs @@ -0,0 +1,13 @@ +// run-rustfix +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +fn main() { + let s = Some(S); + if let Some(x) = s { + let _ = x; + } + foo(s); //~ ERROR use of moved value: `s` +} diff --git a/src/test/ui/borrowck/move-in-pattern.stderr b/src/test/ui/borrowck/move-in-pattern.stderr new file mode 100644 index 0000000000000..fc12b64ab5497 --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `s` + --> $DIR/move-in-pattern.rs:12:9 + | +LL | if let Some(x) = s { + | - value moved here +... +LL | foo(s); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `s.0` + | +LL | if let Some(ref x) = s { + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/mut-borrow-in-loop-2.fixed b/src/test/ui/borrowck/mut-borrow-in-loop-2.fixed new file mode 100644 index 0000000000000..ceeba30a90f29 --- /dev/null +++ b/src/test/ui/borrowck/mut-borrow-in-loop-2.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct Events(R); + +struct Other; + +pub trait Trait { + fn handle(value: T) -> Self; +} + +// Blanket impl. (If you comment this out, compiler figures out that it +// is passing an `&mut` to a method that must be expecting an `&mut`, +// and injects an auto-reborrow.) +impl Trait for T where T: From { + fn handle(_: U) -> Self { unimplemented!() } +} + +impl<'a, R> Trait<&'a mut Events> for Other { + fn handle(_: &'a mut Events) -> Self { unimplemented!() } +} + +fn this_compiles<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); + } +} + +fn this_does_not<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); //~ ERROR use of moved value: `value` + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/mut-borrow-in-loop-2.rs b/src/test/ui/borrowck/mut-borrow-in-loop-2.rs new file mode 100644 index 0000000000000..d13fb7e567939 --- /dev/null +++ b/src/test/ui/borrowck/mut-borrow-in-loop-2.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct Events(R); + +struct Other; + +pub trait Trait { + fn handle(value: T) -> Self; +} + +// Blanket impl. (If you comment this out, compiler figures out that it +// is passing an `&mut` to a method that must be expecting an `&mut`, +// and injects an auto-reborrow.) +impl Trait for T where T: From { + fn handle(_: U) -> Self { unimplemented!() } +} + +impl<'a, R> Trait<&'a mut Events> for Other { + fn handle(_: &'a mut Events) -> Self { unimplemented!() } +} + +fn this_compiles<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); + } +} + +fn this_does_not<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(value); //~ ERROR use of moved value: `value` + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr new file mode 100644 index 0000000000000..fa1b741394acb --- /dev/null +++ b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of moved value: `value` + --> $DIR/mut-borrow-in-loop-2.rs:31:23 + | +LL | fn this_does_not<'a, R>(value: &'a mut Events) { + | ----- move occurs because `value` has type `&mut Events`, which does not implement the `Copy` trait +LL | for _ in 0..3 { +LL | Other::handle(value); + | ^^^^^ value moved here, in previous iteration of loop + | +help: consider creating a fresh reborrow of `value` here + | +LL | Other::handle(&mut *value); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr index f2186b9298e68..8a6ea8e91a25a 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -46,6 +46,10 @@ LL | Some(_z @ ref _y) => {} | value moved here | = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `x.0` + | +LL | Some(ref _z @ ref _y) => {} + | ^^^ error[E0382]: borrow of moved value --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:19 @@ -57,6 +61,10 @@ LL | Some(_z @ ref mut _y) => {} | value moved here | = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `x.0` + | +LL | Some(ref _z @ ref mut _y) => {} + | ^^^ error: aborting due to 6 previous errors From 9e88b48133c703c04780a9474c029b4398ca3260 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 20 Jun 2020 13:25:55 +0200 Subject: [PATCH 12/27] Refer just to the issue in the raw ptr cmp diagnostic instead of explaining everything in the diagnostic --- src/librustc_mir/transform/check_consts/ops.rs | 16 +--------------- .../ui/consts/const-eval/const_raw_ptr_ops.rs | 4 ++-- .../consts/const-eval/const_raw_ptr_ops.stderr | 8 ++------ src/test/ui/error-codes/E0395.rs | 2 +- src/test/ui/error-codes/E0395.stderr | 4 +--- src/test/ui/issues/issue-25826.rs | 2 +- src/test/ui/issues/issue-25826.stderr | 4 +--- 7 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 9f005c0b4dda8..e1a040b2e0ea5 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -287,26 +287,12 @@ impl NonConstOp for RawPtrComparison { fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { let mut err = ccx.tcx.sess.struct_span_err( span, - "pointers cannot be compared in a meaningful way during const eval.", + "pointers cannot be reliably compared during const eval.", ); err.note( "see issue #53020 \ for more information", ); - err.note( - "It is conceptually impossible for const eval to know in all cases whether two \ - pointers are equal. While sometimes it is clear (the address of a non-zst static item \ - is never equal to the address of another non-zst static item), comparing an integer \ - address with any allocation's address is impossible to do at compile-time.", - ); - if ccx.tcx.sess.parse_sess.unstable_features.is_nightly_build() { - err.note( - "That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` \ - for all comparisons where CTFE is sure that two addresses are equal. The mirror \ - intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where \ - CTFE is sure that two addresses are inequal.", - ); - } err.emit(); } } diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 91c4bc8972ca5..083ebfdd4da3f 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -1,6 +1,6 @@ fn main() {} // unconst and bad, will thus error in miri -const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be compared +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably compared // unconst and bad, will thus error in miri -const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be compared +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably compared diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index 6f27ac74ade83..21d3f5e7e8536 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -1,22 +1,18 @@ -error: pointers cannot be compared in a meaningful way during const eval. +error: pointers cannot be reliably compared during const eval. --> $DIR/const_raw_ptr_ops.rs:4:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. -error: pointers cannot be compared in a meaningful way during const eval. +error: pointers cannot be reliably compared during const eval. --> $DIR/const_raw_ptr_ops.rs:6:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs index 28fba1d306139..d2edd97efb232 100644 --- a/src/test/ui/error-codes/E0395.rs +++ b/src/test/ui/error-codes/E0395.rs @@ -2,7 +2,7 @@ static FOO: i32 = 42; static BAR: i32 = 42; static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; -//~^ ERROR pointers cannot be compared in a meaningful way during const eval +//~^ ERROR pointers cannot be reliably compared during const eval fn main() { } diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 62949cf15e13c..674cc69645029 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,12 +1,10 @@ -error: pointers cannot be compared in a meaningful way during const eval. +error: pointers cannot be reliably compared during const eval. --> $DIR/E0395.rs:4:29 | LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs index cb0dfcfa953e4..d1093c205798a 100644 --- a/src/test/ui/issues/issue-25826.rs +++ b/src/test/ui/issues/issue-25826.rs @@ -1,6 +1,6 @@ fn id(t: T) -> T { t } fn main() { const A: bool = unsafe { id:: as *const () < id:: as *const () }; - //~^ ERROR pointers cannot be compared in a meaningful way during const eval + //~^ ERROR pointers cannot be reliably compared during const eval println!("{}", A); } diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index cb24aede81a2c..67d1b3ab9bed6 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -1,12 +1,10 @@ -error: pointers cannot be compared in a meaningful way during const eval. +error: pointers cannot be reliably compared during const eval. --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #53020 for more information - = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time. - = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal. error: aborting due to previous error From 53686b91caac6c6782b8d2a41675f4f0941aa254 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 20 Jun 2020 14:14:30 +0200 Subject: [PATCH 13/27] Satisfy tidy --- src/liballoc/raw_vec.rs | 2 +- src/libcore/intrinsics.rs | 2 +- src/librustc_mir/transform/check_consts/ops.rs | 8 ++++---- src/test/ui/consts/const-eval/const_raw_ptr_ops.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 805dbfe277584..87e73a1b91e69 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -60,7 +60,7 @@ impl RawVec { /// `#[rustc_force_min_const_fn]` attribute which requires conformance /// with `min_const_fn` but does not necessarily allow calling it in /// `stable(...) const fn` / user code not enabling `foo` when - /// `#[rustc_const_unstable(feature = "foo", ..)]` is present. + /// `#[rustc_const_unstable(feature = "foo", issue = "01234")]` is present. pub const NEW: Self = Self::new(); /// Creates the biggest possible `RawVec` (on the system heap) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2b34e98028232..50e321f9c7158 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -11,7 +11,7 @@ //! In order to make an intrinsic usable at compile-time, one needs to copy the implementation //! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to //! `librustc_mir/interpret/intrinsics.rs` and add a -//! `#[rustc_const_unstable(feature = "foo2", issue = "01234")]` to the intrinsic. +//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, //! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index e1a040b2e0ea5..ff22b6b184e54 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -285,10 +285,10 @@ impl NonConstOp for Panic { pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - let mut err = ccx.tcx.sess.struct_span_err( - span, - "pointers cannot be reliably compared during const eval.", - ); + let mut err = ccx + .tcx + .sess + .struct_span_err(span, "pointers cannot be reliably compared during const eval."); err.note( "see issue #53020 \ for more information", diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 083ebfdd4da3f..e238e13b8e2da 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -1,6 +1,6 @@ fn main() {} // unconst and bad, will thus error in miri -const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably compared +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably // unconst and bad, will thus error in miri -const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably compared +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably From 98e97a46e2201520f54082abe462728b0a770a6b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 20 Jun 2020 14:58:15 +0200 Subject: [PATCH 14/27] Address review comments --- src/libcore/ptr/const_ptr.rs | 4 +-- src/libcore/ptr/mut_ptr.rs | 4 +-- src/libcore/slice/mod.rs | 47 +++++++----------------------------- 3 files changed, 13 insertions(+), 42 deletions(-) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index 0e2e6848416b6..e5ac81d8789ec 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -295,7 +295,7 @@ impl *const T { intrinsics::ptr_offset_from(self, origin) } - /// Returns whether two pointers are guaranteed equal. + /// Returns whether two pointers are guaranteed to be equal. /// /// At runtime this function behaves like `self == other`. /// However, in some contexts (e.g., compile-time evaluation), @@ -328,7 +328,7 @@ impl *const T { intrinsics::ptr_guaranteed_eq(self, other) } - /// Returns whether two pointers are guaranteed not equal. + /// Returns whether two pointers are guaranteed to be inequal. /// /// At runtime this function behaves like `self != other`. /// However, in some contexts (e.g., compile-time evaluation), diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 67ace1f72a0ab..b8ff5b0dc72cb 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -273,7 +273,7 @@ impl *mut T { if self.is_null() { None } else { Some(&mut *self) } } - /// Returns whether two pointers are guaranteed equal. + /// Returns whether two pointers are guaranteed to be equal. /// /// At runtime this function behaves like `self == other`. /// However, in some contexts (e.g., compile-time evaluation), @@ -306,7 +306,7 @@ impl *mut T { intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) } - /// Returns whether two pointers are guaranteed not equal. + /// Returns whether two pointers are guaranteed to be inequal. /// /// At runtime this function behaves like `self != other`. /// However, in some contexts (e.g., compile-time evaluation), diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 12932b06d32d4..c69aafe687cf8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5946,8 +5946,7 @@ where } } -// Remove after boostrap bump -#[cfg(bootstrap)] +// Use an equal-pointer optimization when types are `Eq` impl SlicePartialEq for [A] where A: PartialEq + Eq, @@ -5957,47 +5956,14 @@ where return false; } + #[cfg(bootstrap)] if self.as_ptr() == other.as_ptr() { return true; } - self.iter().zip(other.iter()).all(|(x, y)| x == y) - } -} - -// Remove after boostrap bump -#[cfg(bootstrap)] -impl SlicePartialEq for [A] -where - A: PartialEq + BytewiseEquality, -{ - fn equal(&self, other: &[A]) -> bool { - if self.len() != other.len() { - return false; - } - if self.as_ptr() == other.as_ptr() { - return true; - } - unsafe { - let size = mem::size_of_val(self); - memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0 - } - } -} - -// Use an equal-pointer optimization when types are `Eq` -#[cfg(not(bootstrap))] -impl SlicePartialEq for [A] -where - A: PartialEq + Eq, -{ - default fn equal(&self, other: &[A]) -> bool { - if self.len() != other.len() { - return false; - } - // While performance would suffer if `guaranteed_eq` just returned `false` // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] if self.as_ptr().guaranteed_eq(other.as_ptr()) { return true; } @@ -6007,7 +5973,6 @@ where } // Use memcmp for bytewise equality when the types allow -#[cfg(not(bootstrap))] impl SlicePartialEq for [A] where A: PartialEq + BytewiseEquality, @@ -6017,8 +5982,14 @@ where return false; } + #[cfg(bootstrap)] + if self.as_ptr() == other.as_ptr() { + return true; + } + // While performance would suffer if `guaranteed_eq` just returned `false` // for all arguments, correctness and return value of this function are not affected. + #[cfg(not(bootstrap))] if self.as_ptr().guaranteed_eq(other.as_ptr()) { return true; } From 5faf657ae7429faa3b490b5911291f65d033e53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 20 Jun 2020 13:52:27 -0700 Subject: [PATCH 15/27] Change heuristic and add tests --- .../borrow_check/diagnostics/mod.rs | 13 ++++---- src/test/ui/borrowck/move-in-pattern-mut.rs | 23 +++++++++++++ .../ui/borrowck/move-in-pattern-mut.stderr | 33 +++++++++++++++++++ src/test/ui/borrowck/move-in-pattern.fixed | 11 +++++++ src/test/ui/borrowck/move-in-pattern.rs | 11 +++++++ src/test/ui/borrowck/move-in-pattern.stderr | 19 +++++++++-- ...sed-on-type-cyclic-types-issue-4821.stderr | 4 +++ ...orrowck-pat-by-move-and-ref-inverse.stderr | 16 +++++++++ src/test/ui/ref-suggestion.stderr | 4 +++ 9 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/borrowck/move-in-pattern-mut.rs create mode 100644 src/test/ui/borrowck/move-in-pattern-mut.stderr diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index edfaae533ef03..c5d601f06bde7 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -776,13 +776,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let normal_ret = if let [ProjectionElem::Downcast(..), ProjectionElem::Field(_, _)] = - moved_place.projection - { - PatUse(stmt.source_info.span) - } else { - OtherUse(stmt.source_info.span) - }; + let normal_ret = + if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) { + PatUse(stmt.source_info.span) + } else { + OtherUse(stmt.source_info.span) + }; // We are trying to find MIR of the form: // ``` diff --git a/src/test/ui/borrowck/move-in-pattern-mut.rs b/src/test/ui/borrowck/move-in-pattern-mut.rs new file mode 100644 index 0000000000000..175eb3b7a04d1 --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut.rs @@ -0,0 +1,23 @@ +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + +fn main() { + let s = Some(S); + if let Some(mut x) = s { + x = S; + } + foo(s); //~ ERROR use of moved value: `s` + let mut e = E::V { s: S }; + let E::V { s: mut x } = e; + x = S; + bar(e); //~ ERROR use of moved value: `e` +} diff --git a/src/test/ui/borrowck/move-in-pattern-mut.stderr b/src/test/ui/borrowck/move-in-pattern-mut.stderr new file mode 100644 index 0000000000000..391638444c3bd --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut.stderr @@ -0,0 +1,33 @@ +error[E0382]: use of moved value: `s` + --> $DIR/move-in-pattern-mut.rs:18:9 + | +LL | if let Some(mut x) = s { + | ----- value moved here +... +LL | foo(s); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `s.0` + | +LL | if let Some(ref mut x) = s { + | ^^^ + +error[E0382]: use of moved value: `e` + --> $DIR/move-in-pattern-mut.rs:22:9 + | +LL | let E::V { s: mut x } = e; + | ----- value moved here +LL | x = S; +LL | bar(e); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `e.s` + | +LL | let E::V { s: ref mut x } = e; + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/move-in-pattern.fixed b/src/test/ui/borrowck/move-in-pattern.fixed index c44d48163c0c0..f55fdcc5f90e8 100644 --- a/src/test/ui/borrowck/move-in-pattern.fixed +++ b/src/test/ui/borrowck/move-in-pattern.fixed @@ -4,10 +4,21 @@ struct S; fn foo(_: Option) {} +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + fn main() { let s = Some(S); if let Some(ref x) = s { let _ = x; } foo(s); //~ ERROR use of moved value: `s` + let e = E::V { s: S }; + let E::V { s: ref x } = e; + let _ = x; + bar(e); //~ ERROR use of moved value: `e` } diff --git a/src/test/ui/borrowck/move-in-pattern.rs b/src/test/ui/borrowck/move-in-pattern.rs index 910afc01e070b..7ad04b9490c25 100644 --- a/src/test/ui/borrowck/move-in-pattern.rs +++ b/src/test/ui/borrowck/move-in-pattern.rs @@ -4,10 +4,21 @@ struct S; fn foo(_: Option) {} +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + fn main() { let s = Some(S); if let Some(x) = s { let _ = x; } foo(s); //~ ERROR use of moved value: `s` + let e = E::V { s: S }; + let E::V { s: x } = e; + let _ = x; + bar(e); //~ ERROR use of moved value: `e` } diff --git a/src/test/ui/borrowck/move-in-pattern.stderr b/src/test/ui/borrowck/move-in-pattern.stderr index fc12b64ab5497..c5cb24455eb61 100644 --- a/src/test/ui/borrowck/move-in-pattern.stderr +++ b/src/test/ui/borrowck/move-in-pattern.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s` - --> $DIR/move-in-pattern.rs:12:9 + --> $DIR/move-in-pattern.rs:19:9 | LL | if let Some(x) = s { | - value moved here @@ -13,6 +13,21 @@ help: borrow this field in the pattern to avoid moving `s.0` LL | if let Some(ref x) = s { | ^^^ -error: aborting due to previous error +error[E0382]: use of moved value: `e` + --> $DIR/move-in-pattern.rs:23:9 + | +LL | let E::V { s: x } = e; + | - value moved here +LL | let _ = x; +LL | bar(e); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `e.s` + | +LL | let E::V { s: ref x } = e; + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr index fb8562d00ead1..952985fcddee6 100644 --- a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr +++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr @@ -8,6 +8,10 @@ LL | consume(node) + r | ^^^^ value used here after partial move | = note: move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `node.next.0` + | +LL | Some(ref right) => consume(right), + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index f819e671436ec..5058998f2a7c1 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -357,6 +357,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | ^^^ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38 @@ -379,6 +383,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | ^^^ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30 @@ -412,6 +420,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | ^^^ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38 @@ -434,6 +446,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | ^^^ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30 diff --git a/src/test/ui/ref-suggestion.stderr b/src/test/ui/ref-suggestion.stderr index 9ff8e21bb58bd..97d2c174d9adb 100644 --- a/src/test/ui/ref-suggestion.stderr +++ b/src/test/ui/ref-suggestion.stderr @@ -28,6 +28,10 @@ LL | x; | ^ value used here after partial move | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `x.0.0` + | +LL | (Some(ref y), ()) => {}, + | ^^^ error: aborting due to 3 previous errors From fc60282daea83a5deff651e6c5a93dbad4437be7 Mon Sep 17 00:00:00 2001 From: Solomon Ucko Date: Tue, 28 Apr 2020 22:40:18 -0400 Subject: [PATCH 16/27] impl PartialEq> for &[A], &mut [A] --- src/liballoc/tests/vec.rs | 54 +++++++++++++++++++++++++++++++++++++++ src/liballoc/vec.rs | 5 ++++ 2 files changed, 59 insertions(+) diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index a9813a8704f30..62a252c8be2e0 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::collections::TryReserveError::*; +use std::fmt::Debug; use std::mem::size_of; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::vec::{Drain, IntoIter}; @@ -1588,3 +1589,56 @@ fn test_push_growth_strategy() { } } } + +macro_rules! generate_assert_eq_vec_and_prim { + ($name:ident<$B:ident>($type:ty)) => { + fn $name + Debug, $B: Debug>(a: Vec, b: $type) { + assert!(a == b); + assert_eq!(a, b); + } + }; +} + +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_slice (&[B]) } +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_array_3([B; 3]) } + +#[test] +fn partialeq_vec_and_prim() { + assert_eq_vec_and_slice(vec![1, 2, 3], &[1, 2, 3]); + assert_eq_vec_and_array_3(vec![1, 2, 3], [1, 2, 3]); +} + +macro_rules! assert_partial_eq_valid { + ($a2:ident, $a3:ident; $b2:ident, $b3: ident) => { + assert!($a2 == $b2); + assert!($a2 != $b3); + assert!($a3 != $b2); + assert!($a3 == $b3); + assert_eq!($a2, $b2); + assert_ne!($a2, $b3); + assert_ne!($a3, $b2); + assert_eq!($a3, $b3); + }; +} + +#[test] +fn partialeq_vec_full() { + let vec2: Vec<_> = vec![1, 2]; + let vec3: Vec<_> = vec![1, 2, 3]; + let slice2: &[_] = &[1, 2]; + let slice3: &[_] = &[1, 2, 3]; + let slicemut2: &[_] = &mut [1, 2]; + let slicemut3: &[_] = &mut [1, 2, 3]; + let array2: [_; 2] = [1, 2]; + let array3: [_; 3] = [1, 2, 3]; + let arrayref2: &[_; 2] = &[1, 2]; + let arrayref3: &[_; 3] = &[1, 2, 3]; + + assert_partial_eq_valid!(vec2,vec3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; slice2,slice3); + assert_partial_eq_valid!(vec2,vec3; slicemut2,slicemut3); + assert_partial_eq_valid!(slice2,slice3; vec2,vec3); + assert_partial_eq_valid!(slicemut2,slicemut3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; array2,array3); + assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); +} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index f16cac05ea039..c886fa4092752 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2362,6 +2362,8 @@ macro_rules! __impl_slice_eq1 { __impl_slice_eq1! { [] Vec, Vec, } __impl_slice_eq1! { [] Vec, &[B], } __impl_slice_eq1! { [] Vec, &mut [B], } +__impl_slice_eq1! { [] &[A], Vec, } +__impl_slice_eq1! { [] &mut [A], Vec, } __impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } __impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } __impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } @@ -2371,6 +2373,9 @@ __impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? //__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, [A; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, [A; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 } //__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 } From 4896a06667ae8d2df4b55822f98c90e6a6965fbc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 20 Jun 2020 16:02:21 -0700 Subject: [PATCH 17/27] Update stability attribute of new Vec PartialEq impls --- src/liballoc/vec.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index c886fa4092752..e245204751f0b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2344,12 +2344,12 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { } macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - #[stable(feature = "rust1", since = "1.0.0")] + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] impl PartialEq<$rhs> for $lhs where A: PartialEq, - $($constraints)* + $($ty: $bound)? { #[inline] fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } @@ -2359,16 +2359,16 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [] Vec, Vec, } -__impl_slice_eq1! { [] Vec, &[B], } -__impl_slice_eq1! { [] Vec, &mut [B], } -__impl_slice_eq1! { [] &[A], Vec, } -__impl_slice_eq1! { [] &mut [A], Vec, } -__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } -__impl_slice_eq1! { [const N: usize] Vec, [B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &[B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Vec, &mut [B], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] &[A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] &mut [A], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, Vec where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &[B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, [B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [const N: usize] Vec, &[B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? From 63740548aa8887c92d8976ccf478cfb0c44611a5 Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Sat, 20 Jun 2020 22:53:51 -0400 Subject: [PATCH 18/27] Fix typos in doc comments This commit fixes typos in the doc comments of 'librustc_mir/monomorphize/collector.rs' --- src/librustc_mir/monomorphize/collector.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 36f3947d83017..448d8cdd6c6f6 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1,7 +1,7 @@ //! Mono Item Collection //! ==================== //! -//! This module is responsible for discovering all items that will contribute to +//! This module is responsible for discovering all items that will contribute //! to code generation of the crate. The important part here is that it not only //! needs to find syntax-level items (functions, structs, etc) but also all //! their monomorphized instantiations. Every non-generic, non-const function @@ -79,7 +79,7 @@ //! function or method call (represented by a CALL terminator in MIR). But //! calls are not the only thing that might introduce a reference between two //! function mono items, and as we will see below, they are just a -//! specialized of the form described next, and consequently will don't get any +//! specialized of the form described next, and consequently will not get any //! special treatment in the algorithm. //! //! #### Taking a reference to a function or method @@ -158,7 +158,7 @@ //! - Eager mode is meant to be used in conjunction with incremental compilation //! where a stable set of mono items is more important than a minimal //! one. Thus, eager mode will instantiate drop-glue for every drop-able type -//! in the crate, even of no drop call for that type exists (yet). It will +//! in the crate, even if no drop call for that type exists (yet). It will //! also instantiate default implementations of trait methods, something that //! otherwise is only done on demand. //! From e3d735dcbf3f777169c273f660b1388c521bb91c Mon Sep 17 00:00:00 2001 From: Johannes Schilling Date: Sun, 21 Jun 2020 10:22:19 +0200 Subject: [PATCH 19/27] Fix typo in error_codes doc --- src/librustc_error_codes/error_codes/E0081.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0081.md b/src/librustc_error_codes/error_codes/E0081.md index fd5eca68e21fd..b834a734cefc4 100644 --- a/src/librustc_error_codes/error_codes/E0081.md +++ b/src/librustc_error_codes/error_codes/E0081.md @@ -1,4 +1,4 @@ -A discrimant value is present more than once. +A discriminant value is present more than once. Erroneous code example: From e465b227d15fec8f16863ba8e77191ceb5c8670b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 21 Jun 2020 13:17:05 +0200 Subject: [PATCH 20/27] `icmp` can handle raw pointers just fine, there's no need to cast to int. --- src/librustc_codegen_llvm/intrinsic.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 78c29588e2e1b..0a8525f06fa3d 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -734,8 +734,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => { let a = args[0].immediate(); let b = args[1].immediate(); - let a = self.ptrtoint(a, self.type_isize()); - let b = self.ptrtoint(b, self.type_isize()); if name == "ptr_guaranteed_eq" { self.icmp(IntPredicate::IntEQ, a, b) } else { From 467415d50cdf8a0d15ec19dc63251443b35d4cee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Jun 2020 12:28:33 +0200 Subject: [PATCH 21/27] deprecate wrapping_offset_from --- src/libcore/ptr/const_ptr.rs | 6 ++++++ src/libcore/ptr/mut_ptr.rs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index e39d18d7733a2..acc09ddc014e6 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -330,6 +330,12 @@ impl *const T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 40b5e4e22340e..2bbeb95965e7e 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -380,11 +380,18 @@ impl *mut T { /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[rustc_deprecated( + since = "1.46.0", + reason = "Pointer distances across allocation \ + boundaries are not typically meaningful. \ + Use integer subtraction if you really need this." + )] #[inline] pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized, { + #[allow(deprecated_in_future, deprecated)] (self as *const T).wrapping_offset_from(origin) } From a657be42b1a7550c071bcccfc66dee22a55a96d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 21 Jun 2020 11:24:35 +0200 Subject: [PATCH 22/27] Create E0765 error for unterminated double quote strings --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0765.md | 13 +++++++++++++ src/librustc_parse/lexer/mod.rs | 11 +++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0765.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 738b3bc7539a6..6a5e23adafa53 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -445,6 +445,7 @@ E0761: include_str!("./error_codes/E0761.md"), E0762: include_str!("./error_codes/E0762.md"), E0763: include_str!("./error_codes/E0763.md"), E0764: include_str!("./error_codes/E0764.md"), +E0765: include_str!("./error_codes/E0765.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0765.md b/src/librustc_error_codes/error_codes/E0765.md new file mode 100644 index 0000000000000..456e3f3e9e408 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0765.md @@ -0,0 +1,13 @@ +A double quote string (`"`) was not terminated. + +Erroneous code example: + +```compile_fail,E0765 +let s = "; // error! +``` + +To fix this error, add the missing double quote at the end of the string: + +``` +let s = ""; // ok! +``` diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index 2e3cf4e746ae9..8e74c3847bc90 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -353,8 +353,15 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.fatal_span_(start, suffix_start, "unterminated double quote string") - .raise() + self.sess + .span_diagnostic + .struct_span_fatal_with_code( + self.mk_sp(start, suffix_start), + "unterminated double quote string", + error_code!(E0765), + ) + .emit(); + FatalError.raise(); } (token::Str, Mode::Str, 1, 1) // " " } From 726b6f4a69a129ebf97d55f8cde1b3735b6df6aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Jun 2020 16:13:31 +0200 Subject: [PATCH 23/27] Miri: replace many bug! by span_bug! --- src/librustc_mir/interpret/cast.rs | 36 ++++++++++++++++------ src/librustc_mir/interpret/eval_context.rs | 7 +++-- src/librustc_mir/interpret/intrinsics.rs | 7 ++++- src/librustc_mir/interpret/operand.rs | 15 +++++---- src/librustc_mir/interpret/operator.rs | 22 ++++++++----- src/librustc_mir/interpret/terminator.rs | 2 +- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index cfe856abe36dd..60cf21552e9e9 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -52,7 +52,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { - bug!("reifying a fn ptr that requires const arguments"); + span_bug!( + self.cur_span(), + "reifying a fn ptr that requires const arguments" + ); } let instance = ty::Instance::resolve_for_fn_ptr( @@ -66,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("reify fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), } } @@ -77,7 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // No change to value self.write_immediate(*src, dest)?; } - _ => bug!("fn to unsafe fn cast on {:?}", cast_ty), + _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty), } } @@ -99,7 +102,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(fn_ptr, dest)?; } - _ => bug!("closure fn pointer on {:?}", src.layout.ty), + _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), } } } @@ -162,7 +165,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert!(src.layout.ty.is_unsafe_ptr()); return match *src { Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => bug!( + Immediate::Scalar(..) => span_bug!( + self.cur_span(), "{:?} input to a fat-to-thin cast ({:?} -> {:?})", *src, src.layout.ty, @@ -216,7 +220,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Casts to bool are not permitted by rustc, no need to handle them here. - _ => bug!("invalid int to {:?} cast", cast_ty), + _ => span_bug!(self.cur_span(), "invalid int to {:?} cast", cast_ty), } } @@ -248,7 +252,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // float -> f64 Float(FloatTy::F64) => Scalar::from_f64(f.convert(&mut false).value), // That's it. - _ => bug!("invalid float to {:?} cast", dest_ty), + _ => span_bug!(self.cur_span(), "invalid float to {:?} cast", dest_ty), } } @@ -287,7 +291,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(val, dest) } - _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty), + _ => { + span_bug!(self.cur_span(), "invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty) + } } } @@ -307,7 +313,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert_eq!(def_a, def_b); if def_a.is_box() || def_b.is_box() { if !def_a.is_box() || !def_b.is_box() { - bug!("invalid unsizing between {:?} -> {:?}", src.layout.ty, cast_ty.ty); + span_bug!( + self.cur_span(), + "invalid unsizing between {:?} -> {:?}", + src.layout.ty, + cast_ty.ty + ); } return self.unsize_into_ptr( src, @@ -335,7 +346,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Ok(()) } - _ => bug!("unsize_into: invalid conversion: {:?} -> {:?}", src.layout, dest.layout), + _ => span_bug!( + self.cur_span(), + "unsize_into: invalid conversion: {:?} -> {:?}", + src.layout, + dest.layout + ), } } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 22f4691c22b3d..ceacbbe5139bf 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -536,7 +536,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if sized_size == Size::ZERO { return Ok(None); } else { - bug!("Fields cannot be extern types, unless they are at offset 0") + span_bug!( + self.cur_span(), + "Fields cannot be extern types, unless they are at offset 0" + ) } } }; @@ -584,7 +587,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Foreign(_) => Ok(None), - _ => bug!("size_and_align_of::<{:?}> not supported", layout.ty), + _ => span_bug!(self.cur_span(), "size_and_align_of::<{:?}> not supported", layout.ty), } } #[inline] diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ac28ccd181520..31bdc45a2eab9 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -135,7 +135,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { Abi::Scalar(ref scalar) => scalar.value, - _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty), + _ => span_bug!( + self.cur_span(), + "{} called on invalid type {:?}", + intrinsic_name, + ty + ), }; let (nonzero, intrinsic_name) = match intrinsic_name { sym::cttz_nonzero => (true, sym::cttz), diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 35e433c4bd5cd..38948ee53846a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -311,7 +311,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Ok(imm) = self.try_read_immediate(op)? { Ok(imm) } else { - bug!("primitive read failed for type: {:?}", op.layout.ty); + span_bug!(self.cur_span(), "primitive read failed for type: {:?}", op.layout.ty); } } @@ -360,9 +360,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = if offset.bytes() == 0 { a } else { b }; Immediate::from(val) } - Immediate::Scalar(val) => { - bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout) - } + Immediate::Scalar(val) => span_bug!( + self.cur_span(), + "field access on non aggregate {:#?}, {:#?}", + val, + op.layout + ), }; Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout }) } @@ -545,7 +548,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::ConstKind::Infer(..) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) => { - bug!("eval_const_to_op: Unexpected ConstKind {:?}", val) + span_bug!(self.cur_span(), "eval_const_to_op: Unexpected ConstKind {:?}", val) } ty::ConstKind::Value(val_val) => val_val, }; @@ -656,7 +659,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .discriminants(def_id, *self.tcx) .find(|(_, var)| var.val == discr_bits) } - _ => bug!("tagged layout for non-adt non-generator"), + _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), } .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?; // Return the cast value, and the index. diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index d651267f82b79..607122935347e 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -61,7 +61,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Le => l <= r, Gt => l > r, Ge => l >= r, - _ => bug!("Invalid operation on char: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -84,7 +84,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitAnd => l & r, BitOr => l | r, BitXor => l ^ r, - _ => bug!("Invalid operation on bool: {:?}", bin_op), + _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op), }; (Scalar::from_bool(res), false, self.tcx.types.bool) } @@ -110,7 +110,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Mul => ((l * r).value.into(), ty), Div => ((l / r).value.into(), ty), Rem => ((l % r).value.into(), ty), - _ => bug!("invalid float op: `{:?}`", bin_op), + _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op), }; (val, false, ty) } @@ -154,7 +154,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // For the remaining ops, the types must be the same on both sides if left_layout.ty != right_layout.ty { - bug!( + span_bug!( + self.cur_span(), "invalid asymmetric binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, l, @@ -251,7 +252,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )); } - _ => bug!( + _ => span_bug!( + self.cur_span(), "invalid binary op {:?}: {:?}, {:?} (both {:?})", bin_op, l, @@ -333,7 +335,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::binary_ptr_op(self, bin_op, left, right) } - _ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty), + _ => span_bug!( + self.cur_span(), + "Invalid MIR: bad LHS type for binop: {:?}", + left.layout.ty + ), } } @@ -367,7 +373,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = val.to_bool()?; let res = match un_op { Not => !val, - _ => bug!("Invalid bool op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op), }; Ok((Scalar::from_bool(res), false, self.tcx.types.bool)) } @@ -375,7 +381,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let res = match (un_op, fty) { (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?), (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), - _ => bug!("Invalid float op {:?}", un_op), + _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op), }; Ok((res, false, layout.ty)) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 1d57fce39734e..0f3fbcf819574 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -232,7 +232,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), ty::Closure(..) => Abi::RustCall, ty::Generator(..) => Abi::Rust, - _ => bug!("unexpected callee ty: {:?}", instance_ty), + _ => span_bug!(self.cur_span(), "unexpected callee ty: {:?}", instance_ty), } }; let normalize_abi = |abi| match abi { From c14d85fd33934765fcf33122200cecca2d878061 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 21 Jun 2020 11:24:45 +0200 Subject: [PATCH 24/27] Update UI tests --- src/test/rustdoc-ui/test-compile-fail3.stderr | 3 ++- src/test/rustdoc-ui/unparseable-doc-test.stdout | 3 ++- src/test/ui/codemap_tests/tab_2.stderr | 3 ++- src/test/ui/issues/issue-44078.stderr | 3 ++- src/test/ui/parser/unbalanced-doublequote.stderr | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr index 7a2f1815ed8e5..fab801b3beaea 100644 --- a/src/test/rustdoc-ui/test-compile-fail3.stderr +++ b/src/test/rustdoc-ui/test-compile-fail3.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/test-compile-fail3.rs:3:1 | 3 | "fail @@ -6,3 +6,4 @@ error: unterminated double quote string error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout index 4ea6455d3aa4c..29cb22e2e4b09 100644 --- a/src/test/rustdoc-ui/unparseable-doc-test.stdout +++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout @@ -5,7 +5,7 @@ test $DIR/unparseable-doc-test.rs - foo (line 6) ... FAILED failures: ---- $DIR/unparseable-doc-test.rs - foo (line 6) stdout ---- -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unparseable-doc-test.rs:8:1 | LL | "unterminated @@ -13,6 +13,7 @@ LL | "unterminated error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. Couldn't compile the test. failures: diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr index 70414bbd953d6..0bfdc3ac2651d 100644 --- a/src/test/ui/codemap_tests/tab_2.stderr +++ b/src/test/ui/codemap_tests/tab_2.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/tab_2.rs:4:7 | LL | """; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/issues/issue-44078.stderr b/src/test/ui/issues/issue-44078.stderr index 43b49e463128f..daf67219f4d0a 100644 --- a/src/test/ui/issues/issue-44078.stderr +++ b/src/test/ui/issues/issue-44078.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/issue-44078.rs:2:8 | LL | "😊""; @@ -8,3 +8,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. diff --git a/src/test/ui/parser/unbalanced-doublequote.stderr b/src/test/ui/parser/unbalanced-doublequote.stderr index 4d98515c224ad..94b300a7bd765 100644 --- a/src/test/ui/parser/unbalanced-doublequote.stderr +++ b/src/test/ui/parser/unbalanced-doublequote.stderr @@ -1,4 +1,4 @@ -error: unterminated double quote string +error[E0765]: unterminated double quote string --> $DIR/unbalanced-doublequote.rs:5:5 | LL | / " @@ -7,3 +7,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0765`. From 893077ca76eeb1ad35608872d534478d68c953c9 Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Sun, 21 Jun 2020 11:43:30 -0400 Subject: [PATCH 25/27] Update src/librustc_mir/monomorphize/collector.rs typo fix Co-authored-by: Jonas Schievink --- src/librustc_mir/monomorphize/collector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 448d8cdd6c6f6..e51d9ba9c021d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -79,7 +79,7 @@ //! function or method call (represented by a CALL terminator in MIR). But //! calls are not the only thing that might introduce a reference between two //! function mono items, and as we will see below, they are just a -//! specialized of the form described next, and consequently will not get any +//! specialization of the form described next, and consequently will not get any //! special treatment in the algorithm. //! //! #### Taking a reference to a function or method From fea5ab12c269bd816b828d3ceea6bb90e4f72825 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Sat, 13 Jun 2020 20:58:46 +0300 Subject: [PATCH 26/27] Prefer accessible paths in 'use' suggestions This fixes an issue with the following sample: mod foo { mod inaccessible { pub struct X; } pub mod avail { pub struct X; } } fn main() { X; } Instead of suggesting both `use crate::foo::inaccessible::X;` and `use crate::foo::avail::X;`, it should only suggest the latter. It is done by trimming the list of suggestions from inaccessible paths if accessible paths are present. Visibility is checked with `is_accessible_from` now instead of being hard-coded. - Some tests fixes are trivial, and others require a bit more explaining, here are my comments: src/test/ui/issues/issue-35675.stderr: Only needs to make the enum public to have the suggestion make sense. src/test/ui/issues/issue-42944.stderr: Importing the tuple struct won't help because its constructor is not visible, so the attempted constructor does not work. In that case, it's better not to suggest it. The case where the constructor is public is covered in `issue-26545.rs`. --- src/librustc_resolve/diagnostics.rs | 65 ++++++++++++++++-------- src/librustc_resolve/late/diagnostics.rs | 7 ++- src/test/ui/hygiene/globs.stderr | 6 +-- src/test/ui/issues/issue-26545.rs | 12 +++++ src/test/ui/issues/issue-26545.stderr | 14 +++++ src/test/ui/issues/issue-35675.rs | 2 +- src/test/ui/issues/issue-42944.rs | 12 ++--- src/test/ui/issues/issue-42944.stderr | 14 ++--- src/test/ui/issues/issue-4366-2.stderr | 4 +- src/test/ui/issues/issue-4366.stderr | 4 +- src/test/ui/privacy/privacy-ns1.stderr | 18 ++----- src/test/ui/privacy/privacy-ns2.stderr | 18 ++----- src/test/ui/resolve/issue-21221-1.stderr | 5 +- 13 files changed, 99 insertions(+), 82 deletions(-) create mode 100644 src/test/ui/issues/issue-26545.rs create mode 100644 src/test/ui/issues/issue-26545.stderr diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index bd2ce5a72e8d9..bb88b8191f1ad 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -49,6 +49,7 @@ crate struct ImportSuggestion { pub did: Option, pub descr: &'static str, pub path: Path, + pub accessible: bool, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -640,9 +641,11 @@ impl<'a> Resolver<'a> { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); let not_local_module = crate_name.name != kw::Crate; - let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; + let mut worklist = + vec![(start_module, Vec::::new(), true, not_local_module)]; - while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { + while let Some((in_module, path_segments, accessible, in_module_is_extern)) = worklist.pop() + { // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -650,11 +653,20 @@ impl<'a> Resolver<'a> { if name_binding.is_import() && !name_binding.is_extern_crate() { return; } + // avoid non-importable candidates as well if !name_binding.is_importable() { return; } + let child_accessible = + accessible && this.is_accessible_from(name_binding.vis, parent_scope.module); + + // do not venture inside inaccessible items of other crates + if in_module_is_extern && !child_accessible { + return; + } + // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving if ident.name == lookup_ident.name @@ -673,22 +685,29 @@ impl<'a> Resolver<'a> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms }; - // the entity is accessible in the following cases: - // 1. if it's defined in the same crate, it's always - // accessible (since private entities can be made public) - // 2. if it's defined in another crate, it's accessible - // only if both the module is public and the entity is - // declared as public (due to pruning, we don't explore - // outside crate private modules => no need to check this) - if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { - let did = match res { - Res::Def(DefKind::Ctor(..), did) => this.parent(did), - _ => res.opt_def_id(), - }; - if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { - candidates.push(ImportSuggestion { did, descr: res.descr(), path }); + let did = match res { + Res::Def(DefKind::Ctor(..), did) => this.parent(did), + _ => res.opt_def_id(), + }; + + if child_accessible { + // Remove invisible match if exists + if let Some(idx) = candidates + .iter() + .position(|v: &ImportSuggestion| v.did == did && !v.accessible) + { + candidates.remove(idx); } } + + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + candidates.push(ImportSuggestion { + did, + descr: res.descr(), + path, + accessible: child_accessible, + }); + } } } @@ -701,20 +720,22 @@ impl<'a> Resolver<'a> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && lookup_ident.span.rust_2018(); - let is_visible_to_user = - !in_module_is_extern || name_binding.vis == ty::Visibility::Public; - - if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user { - // add the module to the lookup + if !is_extern_crate_that_also_appears_in_prelude { let is_extern = in_module_is_extern || name_binding.is_extern_crate(); + // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { - worklist.push((module, path_segments, is_extern)); + worklist.push((module, path_segments, child_accessible, is_extern)); } } } }) } + // If only some candidates are accessible, take just them + if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) { + candidates = candidates.into_iter().filter(|x| x.accessible).collect(); + } + candidates } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 05ef0aa0bb689..478698ba20c70 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -887,7 +887,12 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let path = Path { span: name_binding.span, segments: path_segments }; result = Some(( module, - ImportSuggestion { did: Some(def_id), descr: "module", path }, + ImportSuggestion { + did: Some(def_id), + descr: "module", + path, + accessible: true, + }, )); } else { // add the module to the lookup diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index 8f6b7aca8fda8..6dcbf055a8bb7 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -23,14 +23,10 @@ LL | | } | |_____- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing one of these items +help: consider importing this function | LL | use bar::g; | -LL | use foo::test2::test::g; - | -LL | use foo::test::g; - | error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 diff --git a/src/test/ui/issues/issue-26545.rs b/src/test/ui/issues/issue-26545.rs new file mode 100644 index 0000000000000..5652ee7470605 --- /dev/null +++ b/src/test/ui/issues/issue-26545.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct B(pub ()); +} + +mod baz { + fn foo() { + B(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-26545.stderr b/src/test/ui/issues/issue-26545.stderr new file mode 100644 index 0000000000000..d3c86692501d6 --- /dev/null +++ b/src/test/ui/issues/issue-26545.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope + --> $DIR/issue-26545.rs:7:9 + | +LL | B(()); + | ^ not found in this scope + | +help: consider importing this tuple struct + | +LL | use foo::B; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-35675.rs b/src/test/ui/issues/issue-35675.rs index 7876811a9ac39..683761667d40a 100644 --- a/src/test/ui/issues/issue-35675.rs +++ b/src/test/ui/issues/issue-35675.rs @@ -33,7 +33,7 @@ fn qux() -> Some { fn main() {} mod x { - enum Enum { + pub enum Enum { Variant1, Variant2(), Variant3(usize), diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs index cc365dc4c938e..a088f91554dfb 100644 --- a/src/test/ui/issues/issue-42944.rs +++ b/src/test/ui/issues/issue-42944.rs @@ -1,20 +1,20 @@ mod foo { - pub struct B(()); + pub struct Bx(()); } mod bar { - use foo::B; + use foo::Bx; fn foo() { - B(()); - //~^ ERROR expected function, tuple struct or tuple variant, found struct `B` [E0423] + Bx(()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `Bx` [E0423] } } mod baz { fn foo() { - B(()); - //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + Bx(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425] } } diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr index e7e251e39c04f..9fad43757ba62 100644 --- a/src/test/ui/issues/issue-42944.stderr +++ b/src/test/ui/issues/issue-42944.stderr @@ -1,18 +1,18 @@ -error[E0423]: expected function, tuple struct or tuple variant, found struct `B` +error[E0423]: expected function, tuple struct or tuple variant, found struct `Bx` --> $DIR/issue-42944.rs:9:9 | -LL | B(()); - | ^ constructor is not visible here due to private fields +LL | Bx(()); + | ^^ constructor is not visible here due to private fields -error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope +error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope --> $DIR/issue-42944.rs:16:9 | -LL | B(()); - | ^ not found in this scope +LL | Bx(()); + | ^^ not found in this scope | help: consider importing this tuple struct | -LL | use foo::B; +LL | use foo::Bx; | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr index ecee595d4ab6a..a86ec7fabea4b 100644 --- a/src/test/ui/issues/issue-4366-2.stderr +++ b/src/test/ui/issues/issue-4366-2.stderr @@ -15,12 +15,10 @@ error[E0423]: expected function, found module `foo` LL | foo(); | ^^^ not a function | -help: consider importing one of these items instead +help: consider importing this function instead | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr index a094180572daa..469ea93e90468 100644 --- a/src/test/ui/issues/issue-4366.stderr +++ b/src/test/ui/issues/issue-4366.stderr @@ -4,12 +4,10 @@ error[E0425]: cannot find function `foo` in this scope LL | fn sub() -> isize { foo(); 1 } | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing this function | LL | use foo::foo; | -LL | use m1::foo; - | error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 4d2af735fa6b9..eda9d4c128d81 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -11,14 +11,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0425]: cannot find function, tuple struct or tuple variant `Bar` in this scope --> $DIR/privacy-ns1.rs:51:5 @@ -33,14 +29,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items - | -LL | use foo1::Bar; +help: consider importing this function | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0412]: cannot find type `Bar` in this scope --> $DIR/privacy-ns1.rs:52:17 @@ -55,14 +47,10 @@ help: a struct with a similar name exists | LL | let _x: Box; | ^^^ -help: consider importing one of these items +help: consider importing this trait | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0107]: wrong number of const arguments: expected 0, found 1 --> $DIR/privacy-ns1.rs:35:17 diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index f1aa523742ae4..d7d9b83527509 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -4,14 +4,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar LL | Bar(); | ^^^ not a function, tuple struct or tuple variant | -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` --> $DIR/privacy-ns2.rs:26:5 @@ -26,14 +22,10 @@ help: a unit struct with a similar name exists | LL | Baz(); | ^^^ -help: consider importing one of these items instead - | -LL | use foo1::Bar; +help: consider importing this function instead | LL | use foo2::Bar; | -LL | use foo3::Bar; - | error[E0573]: expected type, found function `Bar` --> $DIR/privacy-ns2.rs:43:14 @@ -45,14 +37,10 @@ help: use `=` if you meant to assign | LL | let _x = Bar(); | ^ -help: consider importing one of these items instead +help: consider importing this trait instead | LL | use foo1::Bar; | -LL | use foo2::Bar; - | -LL | use foo3::Bar; - | error[E0603]: trait `Bar` is private --> $DIR/privacy-ns2.rs:63:15 diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index d3e1953435359..538eeead9fc9d 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -25,11 +25,8 @@ LL | use mul1::Mul; | LL | use mul2::Mul; | -LL | use mul3::Mul; - | -LL | use mul4::Mul; +LL | use std::ops::Mul; | - and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 From ae71e965dcc5b5b4c4b0ac94d22852968fbf085d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 21 Jun 2020 18:09:58 +0200 Subject: [PATCH 27/27] Do not send a notification for P-high stable regressions Add comment to clarify the pattern --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index fc2dbb8d4402d..5361a618d4e85 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -113,7 +113,7 @@ topic = "P-critical #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-critical`." [notify-zulip."P-high"] -required_labels = ["regression-from-stable-to-*"] +required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions zulip_stream = 227806 # #t-compiler/wg-prioritization topic = "P-high regression #{number} {title}" message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-high` and is a regression."