diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4c889ef41005c..86b5ef73d4446 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -639,18 +639,22 @@ 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(..), .. }) - | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) - | Node::AnonConst(_) - | Node::Item(&Item { kind: ItemKind::Static(..), .. }) => true, - Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => { - sig.header.constness == Constness::Const + for (_, node) in self.parent_iter(hir_id) { + match node { + Node::Item(&Item { kind: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) + | Node::AnonConst(_) + | Node::Item(&Item { kind: ItemKind::Static(..), .. }) => return true, + Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => { + if sig.header.constness == Constness::Const { + return true; + } + } + _ => {} } - _ => false, } + false } /// Whether `hir_id` corresponds to a `mod` or a crate. diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11e9acf3a3912..2dd26397d76f4 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -437,6 +437,7 @@ rustc_queries! { desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } } + query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 351e557d40b30..2d83c7311c122 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -158,6 +158,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::Projection(projection) => (false, Some(projection)), _ => return, }; + if self.tcx.hir().is_const_context(body_id) { + err.note( + "associated types cannot be referenced in `const` contexts, \ + like the length of an array", + ); + return; + } let suggest_restriction = |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0556c80e4f707..6c60e5a9c429f 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -598,11 +598,9 @@ 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; - } + // Shouldn't suggest `.into()` on `const`s. + // FIXME(estebank): modify once we decide to suggest `as` casts + let is_const_context = self.tcx.hir().is_const_context(expr.hir_id); if self.tcx.sess.source_map().is_imported(expr.span) { // Ignore if span is from within a macro. return false; @@ -728,24 +726,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| { let into_sugg = into_suggestion.clone(); - 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_sugg - }, - Applicability::MachineApplicable, - ); + if !is_const_context || 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_sugg + }, + Applicability::MachineApplicable, + ); + } }; match (&expected_ty.kind, &checked_ty.kind) { diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr index ec60db47f4429..310d3adc3a930 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr @@ -7,11 +7,7 @@ LL | const Y: usize; LL | let _array = [4; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | -help: consider further restricting this bound with `+ Foo` - --> $DIR/associated-const-type-parameter-arrays-2.rs:15:16 - | -LL | pub fn test() { - | ^^^ + = note: associated types cannot be referenced in `const` contexts, like the length of an array error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr index 3d38deb5a8763..5ded42efd498a 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr @@ -7,11 +7,7 @@ LL | const Y: usize; LL | let _array: [u32; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` | -help: consider further restricting this bound with `+ Foo` - --> $DIR/associated-const-type-parameter-arrays.rs:15:16 - | -LL | pub fn test() { - | ^^^ + = note: associated types cannot be referenced in `const` contexts, like the length of an array error: aborting due to previous error diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index 6924956bdf706..fc2b2b8b7ff44 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -1,76 +1,58 @@ const X: usize = 42 && 39; //~^ ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` const ARR: [i32; X] = [99; 34]; //~^ ERROR evaluation of constant value failed const X1: usize = 42 || 39; //~^ ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` const ARR1: [i32; X1] = [99; 47]; //~^ ERROR evaluation of constant value failed const X2: usize = -42 || -39; //~^ ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` const ARR2: [i32; X2] = [99; 18446744073709551607]; //~^ ERROR evaluation of constant value failed const X3: usize = -42 && -39; //~^ ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` const ARR3: [i32; X3] = [99; 6]; //~^ ERROR evaluation of constant value failed const Y: usize = 42.0 == 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR: [i32; Y] = [99; 1]; //~^ ERROR evaluation of constant value failed const Y1: usize = 42.0 >= 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR1: [i32; Y1] = [99; 1]; //~^ ERROR evaluation of constant value failed const Y2: usize = 42.0 <= 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR2: [i32; Y2] = [99; 1]; //~^ ERROR evaluation of constant value failed const Y3: usize = 42.0 > 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR3: [i32; Y3] = [99; 0]; //~^ ERROR evaluation of constant value failed const Y4: usize = 42.0 < 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR4: [i32; Y4] = [99; 0]; //~^ ERROR evaluation of constant value failed const Y5: usize = 42.0 != 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` const ARRR5: [i32; Y5] = [99; 0]; //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 9001fefd1029f..ca0908722712f 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -17,151 +17,151 @@ LL | const X: usize = 42 && 39; | ^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:8:18 + --> $DIR/const-integer-bool-ops.rs:5:18 | LL | const ARR: [i32; X] = [99; 34]; | ^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:19 + --> $DIR/const-integer-bool-ops.rs:8:19 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:25 + --> $DIR/const-integer-bool-ops.rs:8:25 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:19 + --> $DIR/const-integer-bool-ops.rs:8:19 | LL | const X1: usize = 42 || 39; | ^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:18:19 + --> $DIR/const-integer-bool-ops.rs:12:19 | LL | const ARR1: [i32; X1] = [99; 47]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:19 + --> $DIR/const-integer-bool-ops.rs:15:19 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:26 + --> $DIR/const-integer-bool-ops.rs:15:26 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:19 + --> $DIR/const-integer-bool-ops.rs:15:19 | LL | const X2: usize = -42 || -39; | ^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:28:19 + --> $DIR/const-integer-bool-ops.rs:19:19 | LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:19 + --> $DIR/const-integer-bool-ops.rs:22:19 | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:26 + --> $DIR/const-integer-bool-ops.rs:22:26 | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:19 + --> $DIR/const-integer-bool-ops.rs:22:19 | LL | const X3: usize = -42 && -39; | ^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:38:19 + --> $DIR/const-integer-bool-ops.rs:26:19 | LL | const ARR3: [i32; X3] = [99; 6]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:41:18 + --> $DIR/const-integer-bool-ops.rs:29:18 | LL | const Y: usize = 42.0 == 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:44:19 + --> $DIR/const-integer-bool-ops.rs:31:19 | LL | const ARRR: [i32; Y] = [99; 1]; | ^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:47:19 + --> $DIR/const-integer-bool-ops.rs:34:19 | LL | const Y1: usize = 42.0 >= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:50:20 + --> $DIR/const-integer-bool-ops.rs:36:20 | LL | const ARRR1: [i32; Y1] = [99; 1]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:53:19 + --> $DIR/const-integer-bool-ops.rs:39:19 | LL | const Y2: usize = 42.0 <= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:56:20 + --> $DIR/const-integer-bool-ops.rs:41:20 | LL | const ARRR2: [i32; Y2] = [99; 1]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:59:19 + --> $DIR/const-integer-bool-ops.rs:44:19 | LL | const Y3: usize = 42.0 > 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:62:20 + --> $DIR/const-integer-bool-ops.rs:46:20 | LL | const ARRR3: [i32; Y3] = [99; 0]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:65:19 + --> $DIR/const-integer-bool-ops.rs:49:19 | LL | const Y4: usize = 42.0 < 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:68:20 + --> $DIR/const-integer-bool-ops.rs:51:20 | LL | const ARRR4: [i32; Y4] = [99; 0]; | ^^ referenced constant has errors error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:71:19 + --> $DIR/const-integer-bool-ops.rs:54:19 | LL | const Y5: usize = 42.0 != 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:74:20 + --> $DIR/const-integer-bool-ops.rs:56:20 | LL | const ARRR5: [i32; Y5] = [99; 0]; | ^^ referenced constant has errors diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs index 763263c6aeb4f..ed8779ab1c46d 100644 --- a/src/test/ui/consts/const-tup-index-span.rs +++ b/src/test/ui/consts/const-tup-index-span.rs @@ -2,7 +2,6 @@ const TUP: (usize,) = 5usize << 64; //~^ ERROR mismatched types -//~| expected tuple, found `usize` const ARR: [i32; TUP.0] = []; //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index 8e4a092e40f5e..aaf4e9eea4bbb 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -8,7 +8,7 @@ LL | const TUP: (usize,) = 5usize << 64; found type `usize` error[E0080]: evaluation of constant value failed - --> $DIR/const-tup-index-span.rs:6:18 + --> $DIR/const-tup-index-span.rs:5:18 | LL | const ARR: [i32; TUP.0] = []; | ^^^ referenced constant has errors 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/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 8836de0023c9d..0f8bbea941d58 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -16,30 +16,26 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim | LL | pub struct Foo(A, B); | --------------------------- required by `Foo` -LL | -LL | impl Foo { - | - this type parameter needs to be `std::marker::Sized` ... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit + = note: associated types cannot be referenced in `const` contexts, like the length of an array error[E0277]: the size for values of type `B` cannot be known at compilation time --> $DIR/too_generic_eval_ice.rs:7:13 | LL | pub struct Foo(A, B); | --------------------------- required by `Foo` -LL | -LL | impl Foo { - | - this type parameter needs to be `std::marker::Sized` ... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `B` = note: to learn more, visit + = note: associated types cannot be referenced in `const` contexts, like the length of an array error: aborting due to 3 previous errors diff --git a/src/test/ui/inference/inference_unstable.rs b/src/test/ui/inference/inference_unstable.rs index 0b95770018241..1d31c0156c3a9 100644 --- a/src/test/ui/inference/inference_unstable.rs +++ b/src/test/ui/inference/inference_unstable.rs @@ -15,5 +15,5 @@ use inference_unstable_itertools::IpuItertools; fn main() { assert_eq!('x'.ipu_flatten(), 1); //~^ WARN a method with this name may be added to the standard library in the future - //~^^ WARN once this method is added to the standard library, the ambiguity may cause an error + //~| WARN once this method is added to the standard library, the ambiguity may cause an error } 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/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.stderr b/src/test/ui/repeat_count.stderr index efad00b272cdc..df100a09b5635 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -33,22 +33,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[E0308]: mismatched types --> $DIR/repeat_count.rs:28:17