Auto merge of #72346 - Dylan-DPC:rollup-vp418xs, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #71886 (Stabilize saturating_abs and saturating_neg) - #72066 (correctly handle uninferred consts) - #72068 (Ignore arguments when looking for `IndexMut` for subsequent `mut` obligation) - #72338 (Fix ICE in -Zsave-analysis) - #72344 (Assert doc wording) Failed merges: r? @ghost
This commit is contained in:
commit
42acd9086f
13 changed files with 154 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -1165,8 +1165,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);
|
||||
|
@ -1175,7 +1174,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 {
|
||||
|
@ -1192,8 +1191,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);
|
||||
|
@ -1202,7 +1200,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 {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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<hir::BodyId>,
|
||||
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(
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
|
|
12
src/test/ui/const-generics/uninferred-consts.rs
Normal file
12
src/test/ui/const-generics/uninferred-consts.rs
Normal file
|
@ -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<const N: usize>(self) {}
|
||||
}
|
||||
fn main() {
|
||||
Foo.foo();
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
20
src/test/ui/const-generics/uninferred-consts.stderr
Normal file
20
src/test/ui/const-generics/uninferred-consts.stderr
Normal file
|
@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
|
@ -1,6 +1,5 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(saturating_neg)]
|
||||
#![feature(const_checked_int_methods)]
|
||||
#![feature(const_euclidean_int_methods)]
|
||||
#![feature(const_overflowing_int_methods)]
|
||||
|
|
29
src/test/ui/issues/issue-72002.rs
Normal file
29
src/test/ui/issues/issue-72002.rs
Normal file
|
@ -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
|
||||
}
|
7
src/test/ui/save-analysis/issue-72267.rs
Normal file
7
src/test/ui/save-analysis/issue-72267.rs
Normal file
|
@ -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
|
||||
}
|
15
src/test/ui/save-analysis/issue-72267.stderr
Normal file
15
src/test/ui/save-analysis/issue-72267.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue