From 7bb6de0ab90e0a1d4d8c7b93dfc1db870bcf1333 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Thu, 10 May 2018 15:46:04 -0300 Subject: [PATCH] closures cannot be constants During type collection, error if a closures is found in constant position, catching that before they go causing ICEs. Fixes #50600. Fixes #48838. --- src/librustc_mir/interpret/const_eval.rs | 11 ++++++++++- src/librustc_typeck/collect.rs | 6 +++++- src/librustc_typeck/diagnostics.rs | 1 + src/test/ui/const-eval/issue-50600.rs | 20 ++++++++++++++++++++ src/test/ui/const-eval/issue-50600.stderr | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/const-eval/issue-50600.rs create mode 100644 src/test/ui/const-eval/issue-50600.stderr diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index dff9fa271aba5..9659f1bc31409 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -444,9 +444,18 @@ pub fn const_eval_provider<'a, 'tcx>( } if let Some(id) = tcx.hir.as_local_node_id(def_id) { - let tables = tcx.typeck_tables_of(def_id); let span = tcx.def_span(def_id); + + // Closures in constant position can hit this in type collection. + if !tcx.has_typeck_tables(def_id) { + return Err(ConstEvalErr { + kind: Lrc::new(TypeckError), + span, + }); + } + let tables = tcx.typeck_tables_of(def_id); + // Do match-check before building MIR if tcx.check_match(def_id).is_err() { return Err(ConstEvalErr { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1b8f2e661c30d..1572c65d4d977 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1085,12 +1085,16 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeField(field) => icx.to_ty(&field.ty), - NodeExpr(&hir::Expr { node: hir::ExprClosure(.., gen), .. }) => { + NodeExpr(&hir::Expr { node: hir::ExprClosure(.., gen), span, .. }) => { if gen.is_some() { let hir_id = tcx.hir.node_to_hir_id(node_id); return tcx.typeck_tables_of(def_id).node_id_to_type(hir_id); } + if !tcx.has_typeck_tables(def_id) { + span_err!(tcx.sess, span, E0912, "closures cannot be constants"); + } + let substs = ty::ClosureSubsts { substs: Substs::for_item( tcx, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index e3f7ff5cb3f74..4d7970c31b599 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4770,4 +4770,5 @@ register_diagnostics! { E0641, // cannot cast to/from a pointer with an unknown kind E0645, // trait aliases not finished E0907, // type inside generator must be known in this context + E0912, // closures cannot be constants } diff --git a/src/test/ui/const-eval/issue-50600.rs b/src/test/ui/const-eval/issue-50600.rs new file mode 100644 index 0000000000000..02da13cdf90f6 --- /dev/null +++ b/src/test/ui/const-eval/issue-50600.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Testing that these do not ICE. + +struct Foo ([u8; |x: u8| { }]); +//~^ ERROR closures cannot be constants +enum Functions { + Square = |x:i32| { }, + //~^ ERROR closures cannot be constants +} + +fn main() {} diff --git a/src/test/ui/const-eval/issue-50600.stderr b/src/test/ui/const-eval/issue-50600.stderr new file mode 100644 index 0000000000000..2a3c4b73d2cd9 --- /dev/null +++ b/src/test/ui/const-eval/issue-50600.stderr @@ -0,0 +1,15 @@ +error[E0912]: closures cannot be constants + --> $DIR/issue-50600.rs:13:18 + | +LL | struct Foo ([u8; |x: u8| { }]); + | ^^^^^^^^^^^ + +error[E0912]: closures cannot be constants + --> $DIR/issue-50600.rs:16:14 + | +LL | Square = |x:i32| { }, + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0912`.