From f99344ace44abc91f76df276625e048f1e8a9536 Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Mon, 4 May 2020 17:32:27 +0200 Subject: [PATCH 1/5] Stabilize saturating_abs and saturating_neg Stabilizes the following signed integer functions with saturation mechanics: * saturating_abs() * saturating_neg() Closes #59983 --- src/libcore/num/mod.rs | 10 ++++------ src/libcore/tests/lib.rs | 1 - src/test/ui/consts/const-int-arithmetic.rs | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a259e293b0c1a..d600b8e1c2515 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1114,8 +1114,7 @@ instead of overflowing. Basic usage: ``` -", $Feature, "#![feature(saturating_neg)] -assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100); +", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100); assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100); assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), "::MAX); @@ -1124,7 +1123,7 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT) $EndFeature, " ```"), - #[unstable(feature = "saturating_neg", issue = "59983")] + #[stable(feature = "saturating_neg", since = "1.45.0")] #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[inline] pub const fn saturating_neg(self) -> Self { @@ -1141,8 +1140,7 @@ MIN` instead of overflowing. Basic usage: ``` -", $Feature, "#![feature(saturating_neg)] -assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100); +", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100); assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100); assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), "::MAX); @@ -1151,7 +1149,7 @@ assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($ $EndFeature, " ```"), - #[unstable(feature = "saturating_neg", issue = "59983")] + #[stable(feature = "saturating_neg", since = "1.45.0")] #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")] #[inline] pub const fn saturating_abs(self) -> Self { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index e7d36d327cd89..6a297f0dc03b1 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -17,7 +17,6 @@ #![feature(pattern)] #![feature(range_is_empty)] #![feature(raw)] -#![feature(saturating_neg)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] #![feature(specialization)] diff --git a/src/test/ui/consts/const-int-arithmetic.rs b/src/test/ui/consts/const-int-arithmetic.rs index 2c3421b7a8d0b..ab24abeba32fe 100644 --- a/src/test/ui/consts/const-int-arithmetic.rs +++ b/src/test/ui/consts/const-int-arithmetic.rs @@ -1,6 +1,5 @@ // run-pass -#![feature(saturating_neg)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] #![feature(const_overflowing_int_methods)] From 0dcde02cc7bdd47f48af12e911829390c2864c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 9 May 2020 17:40:04 -0700 Subject: [PATCH 2/5] Ignore arguments when looking for `IndexMut` for subsequent `mut` obligation Given code like `v[&field].boo();` where `field: String` and `.boo(&mut self)`, typeck will have decided that `v` is accessed using `Index`, but when `boo` adds a new `mut` obligation, `convert_place_op_to_mutable` is called. When this happens, for *some reason* the arguments' dereference adjustments are completely ignored causing an error saying that `IndexMut` is not satisfied: ``` error[E0596]: cannot borrow data in an index of `Indexable` as mutable --> src/main.rs:30:5 | 30 | v[&field].boo(); | ^^^^^^^^^ cannot borrow as mutable | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Indexable` ``` This is not true, but by changing `try_overloaded_place_op` to retry when given `Needs::MutPlace` without passing the argument types, the example successfully compiles. I believe there might be more appropriate ways to deal with this. --- src/librustc_typeck/check/method/confirm.rs | 4 ++- src/test/ui/issues/issue-72002.rs | 29 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-72002.rs diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 64dc34ab3b0a7..c4805c54a7d43 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -468,7 +468,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { match expr.kind { hir::ExprKind::Index(ref base_expr, ref index_expr) => { - let index_expr_ty = self.node_ty(index_expr.hir_id); + // We need to get the final type in case dereferences were needed for the trait + // to apply (#72002). + let index_expr_ty = self.tables.borrow().expr_ty_adjusted(index_expr); self.convert_place_op_to_mutable( PlaceOp::Index, expr, diff --git a/src/test/ui/issues/issue-72002.rs b/src/test/ui/issues/issue-72002.rs new file mode 100644 index 0000000000000..54ff89355ff3a --- /dev/null +++ b/src/test/ui/issues/issue-72002.rs @@ -0,0 +1,29 @@ +// check-pass +struct Indexable; + +impl Indexable { + fn boo(&mut self) {} +} + +impl std::ops::Index<&str> for Indexable { + type Output = Indexable; + + fn index(&self, field: &str) -> &Indexable { + self + } +} + +impl std::ops::IndexMut<&str> for Indexable { + fn index_mut(&mut self, field: &str) -> &mut Indexable { + self + } +} + +fn main() { + let mut v = Indexable; + let field = "hello".to_string(); + + v[field.as_str()].boo(); + + v[&field].boo(); // < This should work +} From 5da74304d500d1a472f171c06c932f156f77eb9a Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 10 May 2020 00:01:23 +0200 Subject: [PATCH 3/5] correctly handle uninferred consts --- .../infer/error_reporting/need_type_info.rs | 43 ++++++++++++++++++- src/librustc_typeck/check/writeback.rs | 20 +++++++-- .../ui/const-generics/uninferred-consts.rs | 12 ++++++ .../const-generics/uninferred-consts.stderr | 20 +++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/const-generics/uninferred-consts.rs create mode 100644 src/test/ui/const-generics/uninferred-consts.stderr diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index 0141ba8273775..dfc7177921d31 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -172,8 +172,19 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { } pub enum TypeAnnotationNeeded { + /// ```compile_fail,E0282 + /// let x = "hello".chars().rev().collect(); + /// ``` E0282, + /// An implementation cannot be chosen unambiguously because of lack of information. + /// ```compile_fail,E0283 + /// let _ = Default::default(); + /// ``` E0283, + /// ```compile_fail,E0284 + /// let mut d: u64 = 2; + /// d = d % 1u32.into(); + /// ``` E0284, } @@ -261,7 +272,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.name_resolver = Some(Box::new(&getter)); let _ = if let ty::FnDef(..) = ty.kind { // We don't want the regular output for `fn`s because it includes its path in - // invalid pseduo-syntax, we want the `fn`-pointer output instead. + // invalid pseudo-syntax, we want the `fn`-pointer output instead. ty.fn_sig(self.tcx).print(printer) } else { ty.print(printer) @@ -518,6 +529,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } + // FIXME(const_generics): We should either try and merge this with `need_type_info_err` + // or improve the errors created here. + // + // Unlike for type inference variables, we don't yet store the origin of const inference variables. + // This is needed for to get a more relevant error span. + pub fn need_type_info_err_const( + &self, + body_id: Option, + span: Span, + ct: &'tcx ty::Const<'tcx>, + error_code: TypeAnnotationNeeded, + ) -> DiagnosticBuilder<'tcx> { + let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span); + if let Some(body_id) = body_id { + let expr = self.tcx.hir().expect_expr(body_id.hir_id); + local_visitor.visit_expr(expr); + } + + let error_code = error_code.into(); + let mut err = self.tcx.sess.struct_span_err_with_code( + local_visitor.target_span, + &format!("type annotations needed"), + error_code, + ); + + err.note("unable to infer the value of a const parameter"); + + err + } + /// If the `FnSig` for the method call can be found and type arguments are identified as /// needed, suggest annotating the call, otherwise point out the resulting type of the call. fn annotate_method_call( diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index c5bf151bc1e11..154ca391aa5fd 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -647,13 +647,26 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false } } - fn report_error(&self, t: Ty<'tcx>) { + fn report_type_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282) .emit(); } } + + fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) { + if !self.tcx.sess.has_errors() { + self.infcx + .need_type_info_err_const( + Some(self.body.id()), + self.span.to_span(self.tcx), + c, + E0282, + ) + .emit(); + } + } } impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { @@ -666,7 +679,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { Ok(t) => self.infcx.tcx.erase_regions(&t), Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); - self.report_error(t); + self.report_type_error(t); self.replaced_with_error = true; self.tcx().types.err } @@ -683,8 +696,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { Ok(ct) => self.infcx.tcx.erase_regions(&ct), Err(_) => { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); - // FIXME: we'd like to use `self.report_error`, but it doesn't yet - // accept a &'tcx ty::Const. + self.report_const_error(ct); self.replaced_with_error = true; self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) } diff --git a/src/test/ui/const-generics/uninferred-consts.rs b/src/test/ui/const-generics/uninferred-consts.rs new file mode 100644 index 0000000000000..3b2bb49197d01 --- /dev/null +++ b/src/test/ui/const-generics/uninferred-consts.rs @@ -0,0 +1,12 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete + +// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893 +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + Foo.foo(); + //~^ ERROR type annotations needed +} diff --git a/src/test/ui/const-generics/uninferred-consts.stderr b/src/test/ui/const-generics/uninferred-consts.stderr new file mode 100644 index 0000000000000..a3620084a4289 --- /dev/null +++ b/src/test/ui/const-generics/uninferred-consts.stderr @@ -0,0 +1,20 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/uninferred-consts.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error[E0282]: type annotations needed + --> $DIR/uninferred-consts.rs:10:5 + | +LL | Foo.foo(); + | ^^^^^^^^^ + | + = note: unable to infer the value of a const parameter + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0282`. From ef3f2c0a7c153f3a50ee3a884900d46cb99c67be Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Mon, 18 May 2020 22:48:06 +0100 Subject: [PATCH 4/5] Fix ICE in -Zsave-analysis --- src/librustc_save_analysis/lib.rs | 6 +++++- src/test/ui/save-analysis/issue-72267.rs | 7 +++++++ src/test/ui/save-analysis/issue-72267.stderr | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/save-analysis/issue-72267.rs create mode 100644 src/test/ui/save-analysis/issue-72267.stderr diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8ae6853210f18..43fd2b1853011 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -620,7 +620,11 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } pub fn get_path_res(&self, id: NodeId) -> Res { - let hir_id = self.tcx.hir().node_id_to_hir_id(id); + // FIXME(#71104) + let hir_id = match self.tcx.hir().opt_node_id_to_hir_id(id) { + Some(id) => id, + None => return Res::Err, + }; match self.tcx.hir().get(hir_id) { Node::TraitRef(tr) => tr.path.res, diff --git a/src/test/ui/save-analysis/issue-72267.rs b/src/test/ui/save-analysis/issue-72267.rs new file mode 100644 index 0000000000000..eea0a7fea0cef --- /dev/null +++ b/src/test/ui/save-analysis/issue-72267.rs @@ -0,0 +1,7 @@ +// compile-flags: -Z save-analysis + +fn main() { + let _: Box<(dyn ?Sized)>; + //~^ ERROR `?Trait` is not permitted in trait object types + //~| ERROR at least one trait is required for an object type +} diff --git a/src/test/ui/save-analysis/issue-72267.stderr b/src/test/ui/save-analysis/issue-72267.stderr new file mode 100644 index 0000000000000..76fc6c57cbc36 --- /dev/null +++ b/src/test/ui/save-analysis/issue-72267.stderr @@ -0,0 +1,15 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/issue-72267.rs:4:21 + | +LL | let _: Box<(dyn ?Sized)>; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-72267.rs:4:17 + | +LL | let _: Box<(dyn ?Sized)>; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. From 5b65c0f9a5506d154b41048356dfa9807386b0c8 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 19 May 2020 11:19:09 +0100 Subject: [PATCH 5/5] Assert doc wording --- src/libcore/macros/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 14bfa8bab8939..13a569e81d0f2 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1243,7 +1243,7 @@ pub(crate) mod builtin { /// be disabled. See [`debug_assert!`] for assertions that are not enabled in /// release builds by default. /// - /// Unsafe code relies on `assert!` to enforce run-time invariants that, if + /// Unsafe code may rely on `assert!` to enforce run-time invariants that, if /// violated could lead to unsafety. /// /// Other use-cases of `assert!` include testing and enforcing run-time