From e9fed696b5ae033195e2ec2f9ba1edf2c3dae5c5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 21 May 2020 17:05:13 -0700 Subject: [PATCH 1/7] Impl Ord for proc_macro::LineColumn --- src/libproc_macro/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index f11401b5a0c7c..2d5bd7e872bd5 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -39,6 +39,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::cmp::Ordering; use std::ops::{Bound, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; @@ -420,6 +421,20 @@ impl !Send for LineColumn {} #[unstable(feature = "proc_macro_span", issue = "54725")] impl !Sync for LineColumn {} +#[unstable(feature = "proc_macro_span", issue = "54725")] +impl Ord for LineColumn { + fn cmp(&self, other: &Self) -> Ordering { + self.line.cmp(&other.line).then(self.column.cmp(&other.column)) + } +} + +#[unstable(feature = "proc_macro_span", issue = "54725")] +impl PartialOrd for LineColumn { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + /// The source file of a given `Span`. #[unstable(feature = "proc_macro_span", issue = "54725")] #[derive(Clone)] From 5a4bf448c764696be75eafb6631e182d95064e72 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 21 May 2020 17:12:29 -0700 Subject: [PATCH 2/7] Add test for proc_macro::LineColumn --- src/libproc_macro/tests/test.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/libproc_macro/tests/test.rs diff --git a/src/libproc_macro/tests/test.rs b/src/libproc_macro/tests/test.rs new file mode 100644 index 0000000000000..331b330cf29f0 --- /dev/null +++ b/src/libproc_macro/tests/test.rs @@ -0,0 +1,12 @@ +#![feature(proc_macro_span)] + +use proc_macro::LineColumn; + +#[test] +fn test_line_column_ord() { + let line0_column0 = LineColumn { line: 0, column: 0 }; + let line0_column1 = LineColumn { line: 0, column: 1 }; + let line1_column0 = LineColumn { line: 1, column: 0 }; + assert!(line0_column0 < line0_column1); + assert!(line0_column1 < line1_column0); +} From 407958a2b88d1028e2a86f5927091540f6be04c4 Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Sun, 17 May 2020 16:49:18 +0800 Subject: [PATCH 3/7] Replace obligation construction with deref_steps() --- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/demand.rs | 72 ++++++++++----------------- 2 files changed, 27 insertions(+), 47 deletions(-) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 2a1c6b895ce20..a324bd03eca8f 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -887,7 +887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce = Coerce::new(self, cause, AllowTwoPhase::No); coerce .autoderef(rustc_span::DUMMY_SP, expr_ty) - .find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps)) + .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps)) } /// Given some expressions, their known unified type and another expression, diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index fc7a9c1d59b76..700b9359d06ed 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,16 +1,15 @@ use crate::check::FnCtxt; use rustc_infer::infer::InferOk; use rustc_trait_selection::infer::InferCtxtExt as _; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCause}; +use rustc_trait_selection::traits::ObligationCause; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem}; +use rustc_hir::lang_items::CloneTraitLangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::ty::adjustment::AllowTwoPhase; -use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut}; +use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } _ if sp == expr.span && !is_macro => { - // Check for `Deref` implementations by constructing a predicate to - // prove: `::Output == U` - let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp)); - let item_def_id = self - .tcx - .associated_items(deref_trait) - .in_definition_order() - .find(|item| item.kind == ty::AssocKind::Type) - .unwrap() - .def_id; - let predicate = - ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate { - // `::Output` - projection_ty: ty::ProjectionTy { - // `T` - substs: self.tcx.intern_substs(&[checked_ty.into()]), - // `Deref::Output` - item_def_id, - }, - // `U` - ty: expected, - })) - .to_predicate(self.tcx); - let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate); - let impls_deref = self.infcx.predicate_may_hold(&obligation); - - // For a suggestion to make sense, the type would need to be `Copy`. - let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp); - - if is_copy && impls_deref { - if let Ok(code) = sm.span_to_snippet(sp) { - let message = if checked_ty.is_region_ptr() { - "consider dereferencing the borrow" - } else { - "consider dereferencing the type" - }; - let suggestion = if is_struct_pat_shorthand_field { - format!("{}: *{}", code, code) - } else { - format!("*{}", code) - }; - return Some((sp, message, suggestion, Applicability::MachineApplicable)); + if let Some(steps) = self.deref_steps(checked_ty, expected) { + if steps == 1 { + // For a suggestion to make sense, the type would need to be `Copy`. + if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) { + if let Ok(code) = sm.span_to_snippet(sp) { + let message = if checked_ty.is_region_ptr() { + "consider dereferencing the borrow" + } else { + "consider dereferencing the type" + }; + let suggestion = if is_struct_pat_shorthand_field { + format!("{}: *{}", code, code) + } else { + format!("*{}", code) + }; + return Some(( + sp, + message, + suggestion, + Applicability::MachineApplicable, + )); + } + } } } } From 58fe05a124383d87ab3eaa3a2f754577954eb94a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 23 May 2020 17:51:58 +0900 Subject: [PATCH 4/7] Add test for #69415 --- .../feature-gate-associated_type_bounds.rs | 3 ++ ...feature-gate-associated_type_bounds.stderr | 32 +++++++++---------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 0faa9090f4ebc..9bce274027ee0 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -1,3 +1,6 @@ +// compile-flags: -Zsave-analysis +// This is also a regression test for #69415 and the above flag is needed. + #![feature(untagged_unions)] trait Tr1 { type As1: Copy; } diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index bfa59d83c82fa..7f2704e1bc371 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -1,5 +1,5 @@ error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:12:22 + --> $DIR/feature-gate-associated_type_bounds.rs:15:22 | LL | type A: Iterator; | ^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | type A: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:15:22 + --> $DIR/feature-gate-associated_type_bounds.rs:18:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type B: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:19:20 + --> $DIR/feature-gate-associated_type_bounds.rs:22:20 | LL | struct _St1> { | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _St1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:26:18 + --> $DIR/feature-gate-associated_type_bounds.rs:29:18 | LL | enum _En1> { | ^^^^^^^^ @@ -35,7 +35,7 @@ LL | enum _En1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:33:19 + --> $DIR/feature-gate-associated_type_bounds.rs:36:19 | LL | union _Un1> { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | union _Un1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:40:37 + --> $DIR/feature-gate-associated_type_bounds.rs:43:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type _TaWhere1 where T: Iterator = T; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:43:22 + --> $DIR/feature-gate-associated_type_bounds.rs:46:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:45:26 + --> $DIR/feature-gate-associated_type_bounds.rs:48:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:48:24 + --> $DIR/feature-gate-associated_type_bounds.rs:51:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:51:31 + --> $DIR/feature-gate-associated_type_bounds.rs:54:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:54:23 + --> $DIR/feature-gate-associated_type_bounds.rs:57:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:60:24 + --> $DIR/feature-gate-associated_type_bounds.rs:63:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:67:21 + --> $DIR/feature-gate-associated_type_bounds.rs:70:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:54:14 + --> $DIR/feature-gate-associated_type_bounds.rs:57:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:60:15 + --> $DIR/feature-gate-associated_type_bounds.rs:63:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:67:12 + --> $DIR/feature-gate-associated_type_bounds.rs:70:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ From 47e35cb9bdcb4d2fd66595d566633e9444325ad4 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 23 May 2020 17:52:11 +0900 Subject: [PATCH 5/7] Add test for #72455 --- src/test/ui/issues/issue-72455.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/ui/issues/issue-72455.rs diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/issues/issue-72455.rs new file mode 100644 index 0000000000000..b6c3bb222876d --- /dev/null +++ b/src/test/ui/issues/issue-72455.rs @@ -0,0 +1,27 @@ +// check-pass + +pub trait ResultExt { + type Ok; + fn err_eprint_and_ignore(self) -> Option; +} + +impl ResultExt for std::result::Result +where + E: std::error::Error, +{ + type Ok = O; + fn err_eprint_and_ignore(self) -> Option + where + Self: , + { + match self { + Err(e) => { + eprintln!("{}", e); + None + } + Ok(o) => Some(o), + } + } +} + +fn main() {} From 749d9e7a26a29b5689f2daaaa9b89f654b2862af Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sat, 23 May 2020 07:29:22 -0400 Subject: [PATCH 6/7] Correct small typo: 'not' -> 'note' --- src/libstd/f32.rs | 2 +- src/libstd/f64.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 8e743ace99bfb..deb9eb5b4b05c 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -882,7 +882,7 @@ impl f32 { /// Returns `max` if `self` is greater than `max`, and `min` if `self` is /// less than `min`. Otherwise this returns `self`. /// - /// Not that this function returns NaN if the initial value was NaN as + /// Note that this function returns NaN if the initial value was NaN as /// well. /// /// # Panics diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index fe64d27b1efc8..b79e550ed265e 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -884,7 +884,7 @@ impl f64 { /// Returns `max` if `self` is greater than `max`, and `min` if `self` is /// less than `min`. Otherwise this returns `self`. /// - /// Not that this function returns NaN if the initial value was NaN as + /// Note that this function returns NaN if the initial value was NaN as /// well. /// /// # Panics From 1c9b96b7540ed1f3df0c3559bde2d5ce1bea4ef3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 May 2020 19:18:37 +0200 Subject: [PATCH 7/7] add warning sign to UB examples --- src/libcore/mem/maybe_uninit.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index f7ea7eba7b16b..01c97444ae3ae 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -20,9 +20,9 @@ use crate::mem::ManuallyDrop; /// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// -/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! +/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ /// // The equivalent code with `MaybeUninit<&i32>`: -/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! +/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️ /// ``` /// /// This is exploited by the compiler for various optimizations, such as eliding @@ -35,9 +35,9 @@ use crate::mem::ManuallyDrop; /// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// -/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! +/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ /// // The equivalent code with `MaybeUninit`: -/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ /// ``` /// /// Moreover, uninitialized memory is special in that the compiler knows that @@ -49,9 +49,9 @@ use crate::mem::ManuallyDrop; /// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// -/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! +/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ /// // The equivalent code with `MaybeUninit`: -/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ /// ``` /// (Notice that the rules around uninitialized integers are not finalized yet, but /// until they are, it is advisable to avoid them.) @@ -348,7 +348,7 @@ impl MaybeUninit { /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); /// let x = unsafe { x.assume_init() }; /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. - /// // This is undefined behavior. + /// // This is undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline] @@ -400,7 +400,7 @@ impl MaybeUninit { /// /// let x = MaybeUninit::>::uninit(); /// let x_vec = unsafe { &*x.as_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ /// ``` /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but @@ -437,7 +437,7 @@ impl MaybeUninit { /// /// let mut x = MaybeUninit::>::uninit(); /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ /// ``` /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but @@ -489,7 +489,7 @@ impl MaybeUninit { /// /// let x = MaybeUninit::>::uninit(); /// let x_init = unsafe { x.assume_init() }; - /// // `x` had not been initialized yet, so this last line caused undefined behavior. + /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] @@ -553,7 +553,7 @@ impl MaybeUninit { /// x.write(Some(vec![0,1,2])); /// let x1 = unsafe { x.read() }; /// let x2 = unsafe { x.read() }; - /// // We now created two copies of the same vector, leading to a double-free when + /// // We now created two copies of the same vector, leading to a double-free ⚠️ when /// // they both get dropped! /// ``` #[unstable(feature = "maybe_uninit_extra", issue = "63567")] @@ -603,7 +603,7 @@ impl MaybeUninit { /// /// let x = MaybeUninit::>::uninit(); /// let x_vec: &Vec = unsafe { x.get_ref() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ /// ``` /// /// ```rust,no_run @@ -686,7 +686,7 @@ impl MaybeUninit { /// unsafe { /// *b.get_mut() = true; /// // We have created a (mutable) reference to an uninitialized `bool`! - /// // This is undefined behavior. + /// // This is undefined behavior. ⚠️ /// } /// ``` ///