diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index db3aa9a1efa..d44fdd5d9b9 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -516,6 +516,7 @@ define_dep_nodes!( <'tcx> [] UsedTraitImports(DefId), [] HasTypeckTables(DefId), [] ConstEval { param_env: ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)> }, + [] CheckMatch(DefId), [] SymbolName(DefId), [] InstanceSymbolName { instance: Instance<'tcx> }, [] SpecializationGraph(DefId), diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index a477e779af9..18c60394a8e 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -37,7 +37,7 @@ use ty::{self, CrateInherentImpls, Ty, TyCtxt}; use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; -use util::common::{profq_msg, ProfileQueriesMsg}; +use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_back::PanicStrategy; @@ -205,6 +205,9 @@ define_maps! { <'tcx> [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> const_val::EvalResult<'tcx>, + [] fn check_match: CheckMatch(DefId) + -> Result<(), ErrorReported>, + /// Performs the privacy check and computes "access levels". [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 739537c7c3a..e63365aa4a8 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -800,6 +800,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::SpecializationGraph => { force!(specialization_graph_of, def_id!()); } DepKind::ObjectSafety => { force!(is_object_safe, def_id!()); } DepKind::TraitImpls => { force!(trait_impls_of, def_id!()); } + DepKind::CheckMatch => { force!(check_match, def_id!()); } DepKind::ParamEnv => { force!(param_env, def_id!()); } DepKind::DescribeDef => { force!(describe_def, def_id!()); } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index bae3cf4db01..c76da589a1b 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -24,6 +24,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use rustc::lint; use rustc_errors::DiagnosticBuilder; +use rustc::util::common::ErrorReported; use rustc::hir::def::*; use rustc::hir::def_id::DefId; @@ -47,17 +48,14 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { b: hir::BodyId, s: Span, id: ast::NodeId) { intravisit::walk_fn(self, fk, fd, b, s, id); - let def_id = self.tcx.hir.local_def_id(id); - - check_body(self.tcx, def_id, b); + check_body(self.tcx, b); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); match item.node { hir::ItemStatic(.., body_id) | hir::ItemConst(.., body_id) => { - let def_id = self.tcx.hir.local_def_id(item.id); - check_body(self.tcx, def_id, body_id); + check_body(self.tcx, body_id); } _ => (), } @@ -66,16 +64,14 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { intravisit::walk_impl_item(self, ii); if let hir::ImplItemKind::Const(_, body_id) = ii.node { - let def_id = self.tcx.hir.local_def_id(ii.id); - check_body(self.tcx, def_id, body_id); + check_body(self.tcx, body_id); } } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { intravisit::walk_trait_item(self, ti); if let hir::TraitItemKind::Const(_, Some(body_id)) = ti.node { - let def_id = self.tcx.hir.local_def_id(ti.id); - check_body(self.tcx, def_id, body_id); + check_body(self.tcx, body_id); } } @@ -83,23 +79,38 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { // but they are const-evaluated during typeck. } +fn check_body<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + body_id: hir::BodyId, +) { + let def_id = tcx.hir.body_owner_def_id(body_id); + let _ = tcx.check_match(def_id); +} + pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir.krate().visit_all_item_likes(&mut OuterVisitor { tcx: tcx }.as_deep_visitor()); tcx.sess.abort_if_errors(); } -pub(crate) fn check_body<'a, 'tcx>( +pub(crate) fn check_match<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - body_id: hir::BodyId, -) { - MatchVisitor { - tcx, - tables: tcx.body_tables(body_id), - region_scope_tree: &tcx.region_scope_tree(def_id), - param_env: tcx.param_env(def_id), - identity_substs: Substs::identity_for_item(tcx, def_id), - }.visit_body(tcx.hir.body(body_id)); +) -> Result<(), ErrorReported> { + let body_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { + tcx.hir.body_owned_by(id) + } else { + return Ok(()); + }; + + tcx.sess.track_errors(|| { + MatchVisitor { + tcx, + tables: tcx.body_tables(body_id), + region_scope_tree: &tcx.region_scope_tree(def_id), + param_env: tcx.param_env(def_id), + identity_substs: Substs::identity_for_item(tcx, def_id), + }.visit_body(tcx.hir.body(body_id)); + }) } fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index a987995e6e5..b4b12e994c8 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -18,7 +18,6 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::LayoutOf; -use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; use rustc::ty::subst::{Substs, Subst}; use rustc::util::common::ErrorReported; @@ -684,14 +683,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { } } -pub fn provide(providers: &mut Providers) { - *providers = Providers { - const_eval, - ..*providers - }; -} - -fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub(crate) fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> EvalResult<'tcx> { let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, key) { @@ -708,14 +700,12 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let body_id = tcx.hir.body_owned_by(id); // Do match-check before building MIR - tcx.sess - .track_errors(|| super::check_match::check_body(tcx, def_id, body_id)) - .map_err(|_| { - ConstEvalErr { - span: tcx.def_span(key.value.0), - kind: MatchCheckError, - } - })?; + if tcx.check_match(def_id).is_err() { + return Err(ConstEvalErr { + span: tcx.def_span(key.value.0), + kind: MatchCheckError, + }); + } tcx.mir_const_qualif(def_id); tcx.hir.body(body_id) diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 7b1c33cb271..714cead4bef 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -48,5 +48,15 @@ pub mod pattern; pub use eval::*; +use rustc::ty::maps::Providers; + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + const_eval: eval::const_eval, + check_match: check_match::check_match, + ..*providers + }; +} + // Build the diagnostics array at the end so that the metadata includes error use sites. __build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS }