From 72a2d35f165a94e17cd17e56cb61e3dcbef7eb2d Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 20 May 2020 14:57:16 +0200 Subject: [PATCH 1/3] fix is_const_context --- src/librustc_middle/hir/map/mod.rs | 22 +++++----- .../diagnostics/mutability_errors.rs | 2 +- src/test/ui/consts/enum-discr-type-err.stderr | 8 ---- src/test/ui/discrim/discrim-ill-typed.stderr | 40 ------------------- src/test/ui/issues/issue-31910.stderr | 5 --- src/test/ui/issues/issue-8761.stderr | 10 ----- src/test/ui/repeat_count.stderr | 10 ----- 7 files changed, 12 insertions(+), 85 deletions(-) diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index b823516d64f3b..c5f0acb3f0709 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -374,6 +374,16 @@ impl<'hir> Map<'hir> { } } + pub fn enclosing_body_owner(&self, hir_id: HirId) -> HirId { + for (parent, _) in self.parent_iter(hir_id) { + if let Some(body) = self.maybe_body_owned_by(parent) { + return self.body_owner(body); + } + } + + bug!("no `enclosing_body_owner` for hir_id `{}`", hir_id); + } + /// Returns the `HirId` that corresponds to the definition of /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. @@ -577,17 +587,7 @@ impl<'hir> Map<'hir> { /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. pub fn is_const_context(&self, hir_id: HirId) -> bool { - let parent_id = self.get_parent_item(hir_id); - match self.get(parent_id) { - Node::Item(&Item { kind: ItemKind::Const(..) | ItemKind::Static(..), .. }) - | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) - | Node::AnonConst(_) => true, - Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => { - sig.header.constness == Constness::Const - } - _ => false, - } + self.body_const_context(self.local_def_id(self.enclosing_body_owner(hir_id))).is_some() } /// Whether `hir_id` corresponds to a `mod` or a crate. diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 402eac47c462b..ff90748a9d07e 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -495,7 +495,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let closure_id = hir.as_local_hir_id(self.mir_def_id.expect_local()); let fn_call_id = hir.get_parent_node(closure_id); let node = hir.get(fn_call_id); - let item_id = hir.get_parent_item(fn_call_id); + let item_id = hir.enclosing_body_owner(fn_call_id); let mut look_at_return = true; // If we can detect the expression to be an `fn` call where the closure was an argument, // we point at the `fn` definition argument... diff --git a/src/test/ui/consts/enum-discr-type-err.stderr b/src/test/ui/consts/enum-discr-type-err.stderr index 492b79e2e6021..9834a99b79a0e 100644 --- a/src/test/ui/consts/enum-discr-type-err.stderr +++ b/src/test/ui/consts/enum-discr-type-err.stderr @@ -11,10 +11,6 @@ LL | | } | |_- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit - | -LL | $( $v = $s::V.try_into().unwrap(), )* - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/enum-discr-type-err.rs:18:21 @@ -29,10 +25,6 @@ LL | | } | |_- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit - | -LL | $( $v = $s::V.try_into().unwrap(), )* - | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/discrim/discrim-ill-typed.stderr b/src/test/ui/discrim/discrim-ill-typed.stderr index 7b9f086151a84..b0e11ee5a6e60 100644 --- a/src/test/ui/discrim/discrim-ill-typed.stderr +++ b/src/test/ui/discrim/discrim-ill-typed.stderr @@ -3,88 +3,48 @@ error[E0308]: mismatched types | LL | OhNo = 0_u8, | ^^^^ expected `i8`, found `u8` - | -help: change the type of the numeric literal from `u8` to `i8` - | -LL | OhNo = 0_i8, - | ^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:30:16 | LL | OhNo = 0_i8, | ^^^^ expected `u8`, found `i8` - | -help: change the type of the numeric literal from `i8` to `u8` - | -LL | OhNo = 0_u8, - | ^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:43:16 | LL | OhNo = 0_u16, | ^^^^^ expected `i16`, found `u16` - | -help: change the type of the numeric literal from `u16` to `i16` - | -LL | OhNo = 0_i16, - | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:56:16 | LL | OhNo = 0_i16, | ^^^^^ expected `u16`, found `i16` - | -help: change the type of the numeric literal from `i16` to `u16` - | -LL | OhNo = 0_u16, - | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:69:16 | LL | OhNo = 0_u32, | ^^^^^ expected `i32`, found `u32` - | -help: change the type of the numeric literal from `u32` to `i32` - | -LL | OhNo = 0_i32, - | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:82:16 | LL | OhNo = 0_i32, | ^^^^^ expected `u32`, found `i32` - | -help: change the type of the numeric literal from `i32` to `u32` - | -LL | OhNo = 0_u32, - | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:95:16 | LL | OhNo = 0_u64, | ^^^^^ expected `i64`, found `u64` - | -help: change the type of the numeric literal from `u64` to `i64` - | -LL | OhNo = 0_i64, - | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:108:16 | LL | OhNo = 0_i64, | ^^^^^ expected `u64`, found `i64` - | -help: change the type of the numeric literal from `i64` to `u64` - | -LL | OhNo = 0_u64, - | ^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/issues/issue-31910.stderr b/src/test/ui/issues/issue-31910.stderr index c5c988cdaa75a..2603c944207d0 100644 --- a/src/test/ui/issues/issue-31910.stderr +++ b/src/test/ui/issues/issue-31910.stderr @@ -3,11 +3,6 @@ error[E0308]: mismatched types | LL | X = Trait::Number, | ^^^^^^^^^^^^^ expected `isize`, found `i32` - | -help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit - | -LL | X = Trait::Number.try_into().unwrap(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-8761.stderr b/src/test/ui/issues/issue-8761.stderr index 836520a28ef34..6ab74a9e98940 100644 --- a/src/test/ui/issues/issue-8761.stderr +++ b/src/test/ui/issues/issue-8761.stderr @@ -3,22 +3,12 @@ error[E0308]: mismatched types | LL | A = 1i64, | ^^^^ expected `isize`, found `i64` - | -help: change the type of the numeric literal from `i64` to `isize` - | -LL | A = 1isize, - | ^^^^^^ error[E0308]: mismatched types --> $DIR/issue-8761.rs:5:9 | LL | B = 2u8 | ^^^ expected `isize`, found `u8` - | -help: change the type of the numeric literal from `u8` to `isize` - | -LL | B = 2isize - | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index 4a2d1d9f921cb..963319892d4ca 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -39,22 +39,12 @@ error[E0308]: mismatched types | LL | let f = [0; -4_isize]; | ^^^^^^^^ expected `usize`, found `isize` - | -help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit - | -LL | let f = [0; (-4_isize).try_into().unwrap()]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/repeat_count.rs:22:23 | LL | let f = [0_usize; -1_isize]; | ^^^^^^^^ expected `usize`, found `isize` - | -help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit - | -LL | let f = [0_usize; (-1_isize).try_into().unwrap()]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors From ecb593379c3ab075940a3fbf2e980ec5260b6ca4 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 20 May 2020 15:59:57 +0200 Subject: [PATCH 2/3] refactor check_for_cast --- src/librustc_typeck/check/demand.rs | 396 +++++++++---------- src/test/ui/discrim/discrim-ill-typed.stderr | 40 ++ src/test/ui/issues/issue-8761.stderr | 10 + src/test/ui/numeric/const-scope.stderr | 10 + src/test/ui/repeat_count.rs | 3 + src/test/ui/repeat_count.stderr | 15 +- 6 files changed, 265 insertions(+), 209 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9694ce9450c27..6e93f2273ab86 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -16,6 +16,8 @@ use rustc_span::Span; use super::method::probe; +use std::fmt; + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn emit_coerce_suggestions( &self, @@ -689,16 +691,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { - if self.tcx.hir().is_const_context(expr.hir_id) { - // Shouldn't suggest `.into()` on `const`s. - // FIXME(estebank): modify once we decide to suggest `as` casts - return false; - } if self.tcx.sess.source_map().is_imported(expr.span) { // Ignore if span is from within a macro. return false; } + let src = if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { + src + } else { + return false; + }; + // If casting this expression to a given numeric type would be appropriate in case of a type // mismatch. // @@ -727,6 +730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { String::new() }; + if let hir::ExprKind::Call(path, args) = &expr.kind { if let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) = (&path.kind, args.len()) @@ -768,222 +772,200 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty, expected_ty, ); - let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8); - - if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { - let cast_suggestion = format!( - "{}{}{}{} as {}", - prefix, - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }, - expected_ty, - ); - let try_into_suggestion = format!( - "{}{}{}{}.try_into().unwrap()", - prefix, - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }, - ); - let into_suggestion = format!( - "{}{}{}{}.into()", - prefix, - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }, - ); - let suffix_suggestion = format!( - "{}{}{}{}", - if needs_paren { "(" } else { "" }, - if let (ty::Int(_) | ty::Uint(_), ty::Float(_)) = - (&expected_ty.kind, &checked_ty.kind,) - { - // Remove fractional part from literal, for example `42.0f32` into `42` - let src = src.trim_end_matches(&checked_ty.to_string()); - src.split('.').next().unwrap() + let with_opt_paren: fn(&dyn fmt::Display) -> String = + if expr.precedence().order() < PREC_POSTFIX { + |s| format!("({})", s) + } else { + |s| s.to_string() + }; + + let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty); + let try_into_suggestion = format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src)); + let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src)); + let suffix_suggestion = with_opt_paren(&format_args!( + "{}{}", + if matches!( + (&expected_ty.kind, &checked_ty.kind), + (ty::Int(_) | ty::Uint(_), ty::Float(_)) + ) { + // Remove fractional part from literal, for example `42.0f32` into `42` + let src = src.trim_end_matches(&checked_ty.to_string()); + src.split('.').next().unwrap() + } else { + src.trim_end_matches(&checked_ty.to_string()) + }, + expected_ty, + )); + let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| { + if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false } + }; + + let is_const_context = self.tcx.hir().is_const_context(expr.hir_id); + let suggest_to_change_suffix_or_into = + |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| { + let msg = if literal_is_ty_suffixed(expr) { + &lit_msg + } else if is_const_context { + // Do not recommend `into` or `try_into` in const contexts. + return; + } else if is_fallible { + &try_msg } else { - src.trim_end_matches(&checked_ty.to_string()) - }, - expected_ty, - if needs_paren { ")" } else { "" }, - ); - let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| { - if let hir::ExprKind::Lit(lit) = &expr.kind { - lit.node.is_suffixed() + &msg + }; + let suggestion = if literal_is_ty_suffixed(expr) { + suffix_suggestion.clone() + } else if is_fallible { + try_into_suggestion } else { - false - } + into_suggestion.clone() + }; + err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable); }; - let suggest_to_change_suffix_or_into = - |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| { + match (&expected_ty.kind, &checked_ty.kind) { + (&ty::Int(ref exp), &ty::Int(ref found)) => { + let is_fallible = match (exp.bit_width(), found.bit_width()) { + (Some(exp), Some(found)) if exp < found => true, + (None, Some(8 | 16)) => false, + (None, _) | (_, None) => true, + _ => false, + }; + suggest_to_change_suffix_or_into(err, is_fallible); + true + } + (&ty::Uint(ref exp), &ty::Uint(ref found)) => { + let is_fallible = match (exp.bit_width(), found.bit_width()) { + (Some(exp), Some(found)) if exp < found => true, + (None, Some(8 | 16)) => false, + (None, _) | (_, None) => true, + _ => false, + }; + suggest_to_change_suffix_or_into(err, is_fallible); + true + } + (&ty::Int(exp), &ty::Uint(found)) => { + let is_fallible = match (exp.bit_width(), found.bit_width()) { + (Some(exp), Some(found)) if found < exp => false, + (None, Some(8)) => false, + _ => true, + }; + suggest_to_change_suffix_or_into(err, is_fallible); + true + } + (&ty::Uint(_), &ty::Int(_)) => { + suggest_to_change_suffix_or_into(err, true); + true + } + (&ty::Float(ref exp), &ty::Float(ref found)) => { + if found.bit_width() < exp.bit_width() { + suggest_to_change_suffix_or_into(err, false); + } else if literal_is_ty_suffixed(expr) { err.span_suggestion( expr.span, - if literal_is_ty_suffixed(expr) { - &lit_msg - } else if is_fallible { - &try_msg - } else { - &msg - }, - if literal_is_ty_suffixed(expr) { - suffix_suggestion.clone() - } else if is_fallible { - try_into_suggestion - } else { - into_suggestion.clone() - }, + &lit_msg, + suffix_suggestion, Applicability::MachineApplicable, ); - }; - - match (&expected_ty.kind, &checked_ty.kind) { - (&ty::Int(ref exp), &ty::Int(ref found)) => { - let is_fallible = match (exp.bit_width(), found.bit_width()) { - (Some(exp), Some(found)) if exp < found => true, - (None, Some(8 | 16)) => false, - (None, _) | (_, None) => true, - _ => false, - }; - suggest_to_change_suffix_or_into(err, is_fallible); - true - } - (&ty::Uint(ref exp), &ty::Uint(ref found)) => { - let is_fallible = match (exp.bit_width(), found.bit_width()) { - (Some(exp), Some(found)) if exp < found => true, - (None, Some(8 | 16)) => false, - (None, _) | (_, None) => true, - _ => false, - }; - suggest_to_change_suffix_or_into(err, is_fallible); - true - } - (&ty::Int(exp), &ty::Uint(found)) => { - let is_fallible = match (exp.bit_width(), found.bit_width()) { - (Some(exp), Some(found)) if found < exp => false, - (None, Some(8)) => false, - _ => true, - }; - suggest_to_change_suffix_or_into(err, is_fallible); - true - } - (&ty::Uint(_), &ty::Int(_)) => { - suggest_to_change_suffix_or_into(err, true); - true - } - (&ty::Float(ref exp), &ty::Float(ref found)) => { - if found.bit_width() < exp.bit_width() { - suggest_to_change_suffix_or_into(err, false); - } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, - &lit_msg, - suffix_suggestion, - Applicability::MachineApplicable, - ); - } else if can_cast { - // Missing try_into implementation for `f64` to `f32` - err.span_suggestion( - expr.span, - &format!("{}, producing the closest possible value", cast_msg), - cast_suggestion, - Applicability::MaybeIncorrect, // lossy conversion - ); - } - true + } else if can_cast { + // Missing try_into implementation for `f64` to `f32` + err.span_suggestion( + expr.span, + &format!("{}, producing the closest possible value", cast_msg), + cast_suggestion, + Applicability::MaybeIncorrect, // lossy conversion + ); } - (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => { - if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, - &lit_msg, - suffix_suggestion, - Applicability::MachineApplicable, - ); - } else if can_cast { - // Missing try_into implementation for `{float}` to `{integer}` - err.span_suggestion( - expr.span, - &format!("{}, rounding the float towards zero", msg), - cast_suggestion, - Applicability::MaybeIncorrect, // lossy conversion - ); - } - true + true + } + (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => { + if literal_is_ty_suffixed(expr) { + err.span_suggestion( + expr.span, + &lit_msg, + suffix_suggestion, + Applicability::MachineApplicable, + ); + } else if can_cast { + // Missing try_into implementation for `{float}` to `{integer}` + err.span_suggestion( + expr.span, + &format!("{}, rounding the float towards zero", msg), + cast_suggestion, + Applicability::MaybeIncorrect, // lossy conversion + ); } - (&ty::Float(ref exp), &ty::Uint(ref found)) => { - // if `found` is `None` (meaning found is `usize`), don't suggest `.into()` - if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion( - expr.span, - &format!( - "{}, producing the floating point representation of the integer", - msg, - ), - into_suggestion, - Applicability::MachineApplicable, - ); - } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, - &lit_msg, - suffix_suggestion, - Applicability::MachineApplicable, - ); - } else { - // Missing try_into implementation for `{integer}` to `{float}` - err.span_suggestion( - expr.span, - &format!( - "{}, producing the floating point representation of the integer, + true + } + (&ty::Float(ref exp), &ty::Uint(ref found)) => { + // if `found` is `None` (meaning found is `usize`), don't suggest `.into()` + if exp.bit_width() > found.bit_width().unwrap_or(256) { + err.span_suggestion( + expr.span, + &format!( + "{}, producing the floating point representation of the integer", + msg, + ), + into_suggestion, + Applicability::MachineApplicable, + ); + } else if literal_is_ty_suffixed(expr) { + err.span_suggestion( + expr.span, + &lit_msg, + suffix_suggestion, + Applicability::MachineApplicable, + ); + } else { + // Missing try_into implementation for `{integer}` to `{float}` + err.span_suggestion( + expr.span, + &format!( + "{}, producing the floating point representation of the integer, rounded if necessary", - cast_msg, - ), - cast_suggestion, - Applicability::MaybeIncorrect, // lossy conversion - ); - } - true + cast_msg, + ), + cast_suggestion, + Applicability::MaybeIncorrect, // lossy conversion + ); } - (&ty::Float(ref exp), &ty::Int(ref found)) => { - // if `found` is `None` (meaning found is `isize`), don't suggest `.into()` - if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion( - expr.span, - &format!( - "{}, producing the floating point representation of the integer", - &msg, - ), - into_suggestion, - Applicability::MachineApplicable, - ); - } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, - &lit_msg, - suffix_suggestion, - Applicability::MachineApplicable, - ); - } else { - // Missing try_into implementation for `{integer}` to `{float}` - err.span_suggestion( - expr.span, - &format!( - "{}, producing the floating point representation of the integer, \ - rounded if necessary", - &msg, - ), - cast_suggestion, - Applicability::MaybeIncorrect, // lossy conversion - ); - } - true + true + } + (&ty::Float(ref exp), &ty::Int(ref found)) => { + // if `found` is `None` (meaning found is `isize`), don't suggest `.into()` + if exp.bit_width() > found.bit_width().unwrap_or(256) { + err.span_suggestion( + expr.span, + &format!( + "{}, producing the floating point representation of the integer", + &msg, + ), + into_suggestion, + Applicability::MachineApplicable, + ); + } else if literal_is_ty_suffixed(expr) { + err.span_suggestion( + expr.span, + &lit_msg, + suffix_suggestion, + Applicability::MachineApplicable, + ); + } else { + // Missing try_into implementation for `{integer}` to `{float}` + err.span_suggestion( + expr.span, + &format!( + "{}, producing the floating point representation of the integer, \ + rounded if necessary", + &msg, + ), + cast_suggestion, + Applicability::MaybeIncorrect, // lossy conversion + ); } - _ => false, + true } - } else { - false + _ => false, } } } diff --git a/src/test/ui/discrim/discrim-ill-typed.stderr b/src/test/ui/discrim/discrim-ill-typed.stderr index b0e11ee5a6e60..7b9f086151a84 100644 --- a/src/test/ui/discrim/discrim-ill-typed.stderr +++ b/src/test/ui/discrim/discrim-ill-typed.stderr @@ -3,48 +3,88 @@ error[E0308]: mismatched types | LL | OhNo = 0_u8, | ^^^^ expected `i8`, found `u8` + | +help: change the type of the numeric literal from `u8` to `i8` + | +LL | OhNo = 0_i8, + | ^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:30:16 | LL | OhNo = 0_i8, | ^^^^ expected `u8`, found `i8` + | +help: change the type of the numeric literal from `i8` to `u8` + | +LL | OhNo = 0_u8, + | ^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:43:16 | LL | OhNo = 0_u16, | ^^^^^ expected `i16`, found `u16` + | +help: change the type of the numeric literal from `u16` to `i16` + | +LL | OhNo = 0_i16, + | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:56:16 | LL | OhNo = 0_i16, | ^^^^^ expected `u16`, found `i16` + | +help: change the type of the numeric literal from `i16` to `u16` + | +LL | OhNo = 0_u16, + | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:69:16 | LL | OhNo = 0_u32, | ^^^^^ expected `i32`, found `u32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | OhNo = 0_i32, + | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:82:16 | LL | OhNo = 0_i32, | ^^^^^ expected `u32`, found `i32` + | +help: change the type of the numeric literal from `i32` to `u32` + | +LL | OhNo = 0_u32, + | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:95:16 | LL | OhNo = 0_u64, | ^^^^^ expected `i64`, found `u64` + | +help: change the type of the numeric literal from `u64` to `i64` + | +LL | OhNo = 0_i64, + | ^^^^^ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:108:16 | LL | OhNo = 0_i64, | ^^^^^ expected `u64`, found `i64` + | +help: change the type of the numeric literal from `i64` to `u64` + | +LL | OhNo = 0_u64, + | ^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/issues/issue-8761.stderr b/src/test/ui/issues/issue-8761.stderr index 6ab74a9e98940..836520a28ef34 100644 --- a/src/test/ui/issues/issue-8761.stderr +++ b/src/test/ui/issues/issue-8761.stderr @@ -3,12 +3,22 @@ error[E0308]: mismatched types | LL | A = 1i64, | ^^^^ expected `isize`, found `i64` + | +help: change the type of the numeric literal from `i64` to `isize` + | +LL | A = 1isize, + | ^^^^^^ error[E0308]: mismatched types --> $DIR/issue-8761.rs:5:9 | LL | B = 2u8 | ^^^ expected `isize`, found `u8` + | +help: change the type of the numeric literal from `u8` to `isize` + | +LL | B = 2isize + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/numeric/const-scope.stderr b/src/test/ui/numeric/const-scope.stderr index 6e1990e3a7222..d7f18e19b41bd 100644 --- a/src/test/ui/numeric/const-scope.stderr +++ b/src/test/ui/numeric/const-scope.stderr @@ -3,6 +3,11 @@ error[E0308]: mismatched types | LL | const C: i32 = 1i8; | ^^^ expected `i32`, found `i8` + | +help: change the type of the numeric literal from `i8` to `i32` + | +LL | const C: i32 = 1i32; + | ^^^^ error[E0308]: mismatched types --> $DIR/const-scope.rs:2:15 @@ -17,6 +22,11 @@ LL | let c: i32 = 1i8; | --- ^^^ expected `i32`, found `i8` | | | expected due to this + | +help: change the type of the numeric literal from `i8` to `i32` + | +LL | let c: i32 = 1i32; + | ^^^^ error[E0308]: mismatched types --> $DIR/const-scope.rs:6:17 diff --git a/src/test/ui/repeat_count.rs b/src/test/ui/repeat_count.rs index aca7af144a934..7e30491f0bdbc 100644 --- a/src/test/ui/repeat_count.rs +++ b/src/test/ui/repeat_count.rs @@ -22,6 +22,9 @@ fn main() { let f = [0_usize; -1_isize]; //~^ ERROR mismatched types //~| expected `usize`, found `isize` + let f = [0; 4u8]; + //~^ ERROR mismatched types + //~| expected `usize`, found `u8` struct G { g: (), } diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index 963319892d4ca..6a081e23d9d37 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -29,7 +29,7 @@ LL | let e = [0; "foo"]; | ^^^^^ expected `usize`, found `&str` error[E0308]: mismatched types - --> $DIR/repeat_count.rs:28:17 + --> $DIR/repeat_count.rs:31:17 | LL | let g = [0; G { g: () }]; | ^^^^^^^^^^^ expected `usize`, found struct `main::G` @@ -46,7 +46,18 @@ error[E0308]: mismatched types LL | let f = [0_usize; -1_isize]; | ^^^^^^^^ expected `usize`, found `isize` -error: aborting due to 8 previous errors +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:25:17 + | +LL | let f = [0; 4u8]; + | ^^^ expected `usize`, found `u8` + | +help: change the type of the numeric literal from `u8` to `usize` + | +LL | let f = [0; 4usize]; + | ^^^^^^ + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0308, E0435. For more information about an error, try `rustc --explain E0308`. From 6da17d244b08e5f14edd1645fbd07d1f042d00b7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 20 May 2020 20:10:04 +0200 Subject: [PATCH 3/3] `is_const_context` -> `is_inside_const_context` --- src/librustc_middle/hir/map/mod.rs | 2 +- src/librustc_typeck/check/demand.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index c5f0acb3f0709..a5b388f410ddf 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -586,7 +586,7 @@ impl<'hir> Map<'hir> { /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. - pub fn is_const_context(&self, hir_id: HirId) -> bool { + pub fn is_inside_const_context(&self, hir_id: HirId) -> bool { self.body_const_context(self.local_def_id(self.enclosing_body_owner(hir_id))).is_some() } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6e93f2273ab86..44d7be4124f5d 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -800,12 +800,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false } }; - let is_const_context = self.tcx.hir().is_const_context(expr.hir_id); + let in_const_context = self.tcx.hir().is_inside_const_context(expr.hir_id); let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| { let msg = if literal_is_ty_suffixed(expr) { &lit_msg - } else if is_const_context { + } else if in_const_context { // Do not recommend `into` or `try_into` in const contexts. return; } else if is_fallible { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d72c74e4188ee..69252046ad1bb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5097,7 +5097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) { - if self.tcx.hir().is_const_context(expr.hir_id) { + if self.tcx.hir().is_inside_const_context(expr.hir_id) { // Do not suggest `Box::new` in const context. return; } @@ -5134,7 +5134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { // Handle #68197. - if self.tcx.hir().is_const_context(expr.hir_id) { + if self.tcx.hir().is_inside_const_context(expr.hir_id) { // Do not suggest `Box::new` in const context. return false; }