diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-07-26 15:54:44 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-07-27 12:22:26 +0300 |
| commit | 4c900c52482fd398cbec4d1d433fcc2e6888ff1b (patch) | |
| tree | ada190e0f3340111d3355b63addc136a815ac6b6 /src/librustc_const_eval | |
| parent | 5c126bdee6af3feef2d51956debab72f933078c6 (diff) | |
rustc_const_eval: always require correct Substs.
Diffstat (limited to 'src/librustc_const_eval')
| -rw-r--r-- | src/librustc_const_eval/check_match.rs | 13 | ||||
| -rw-r--r-- | src/librustc_const_eval/eval.rs | 53 | ||||
| -rw-r--r-- | src/librustc_const_eval/pattern.rs | 44 |
3 files changed, 49 insertions, 61 deletions
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index fcdabf89e3c..e7a12df0a27 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -21,6 +21,7 @@ use rustc::middle::mem_categorization::{cmt}; use rustc::middle::region::RegionMaps; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::Substs; use rustc::lint; use rustc_errors::{Diagnostic, Level, DiagnosticBuilder}; @@ -51,7 +52,8 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { tcx: self.tcx, tables: self.tcx.body_tables(b), region_maps: &self.tcx.region_maps(def_id), - param_env: self.tcx.param_env(def_id) + param_env: self.tcx.param_env(def_id), + identity_substs: Substs::identity_for_item(self.tcx, def_id), }.visit_body(self.tcx.hir.body(b)); } } @@ -69,6 +71,7 @@ struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, + identity_substs: &'tcx Substs<'tcx>, region_maps: &'a RegionMaps, } @@ -110,7 +113,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { } } -impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn report_inlining_errors(&self, pat_span: Span) { for error in &self.errors { match *error { @@ -162,7 +165,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( arm.pats.iter().map(|pat| { - let mut patcx = PatternContext::new(self.tcx, self.tables); + let substs = self.identity_substs; + let mut patcx = PatternContext::new(self.tcx, self.tables, substs); let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { patcx.report_inlining_errors(pat.span); @@ -229,7 +233,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_irrefutable(&self, pat: &Pat, origin: &str) { let module = self.tcx.hir.get_module_parent(pat.id); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { - let mut patcx = PatternContext::new(self.tcx, self.tables); + let substs = self.identity_substs; + let mut patcx = PatternContext::new(self.tcx, self.tables, substs); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; let pats : Matrix = vec![vec![ diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 72fa858e4cb..bcf5fd2b13d 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -94,11 +94,13 @@ pub struct ConstContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> ConstContext<'a, 'tcx> { - pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>) -> Self { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, + substs: &'tcx Substs<'tcx>) -> Self { ConstContext { - tcx: tcx, - tables: tables, - substs: tcx.intern_substs(&[]), + tcx, + tables, + substs, fn_args: None } } @@ -118,14 +120,7 @@ type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>; fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, e: &Expr) -> EvalResult<'tcx> { let tcx = cx.tcx; - let ety = cx.tables.expr_ty(e); - - // Avoid applying substitutions if they're empty, that'd ICE. - let ety = if cx.substs.is_empty() { - ety - } else { - ety.subst(tcx, cx.substs) - }; + let ety = cx.tables.expr_ty(e).subst(tcx, cx.substs); let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { @@ -269,14 +264,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } hir::ExprCast(ref base, _) => { let base_val = cx.eval(base)?; - let base_ty = cx.tables.expr_ty(base); - - // Avoid applying substitutions if they're empty, that'd ICE. - let base_ty = if cx.substs.is_empty() { - base_ty - } else { - base_ty.subst(tcx, cx.substs) - }; + let base_ty = cx.tables.expr_ty(base).subst(tcx, cx.substs); if ety == base_ty { base_val } else { @@ -287,15 +275,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } } hir::ExprPath(ref qpath) => { - let substs = cx.tables.node_substs(e.id); - - // Avoid applying substitutions if they're empty, that'd ICE. - let substs = if cx.substs.is_empty() { - substs - } else { - substs.subst(tcx, cx.substs) - }; - + let substs = cx.tables.node_substs(e.id).subst(tcx, cx.substs); match cx.tables.qpath_def(qpath, e.id) { Def::Const(def_id) | Def::AssociatedConst(def_id) => { @@ -538,7 +518,10 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match ac { // FIXME(eddyb) Use proper Instance resolution to // get the correct Substs returned from here. - Some(ic) => Some((ic.def_id, Substs::empty())), + Some(ic) => { + let substs = Substs::identity_for_item(tcx, ic.def_id); + Some((ic.def_id, substs)) + } None => { if trait_item.defaultness.has_value() { Some((def_id, substs)) @@ -789,18 +772,12 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); }; - let cx = ConstContext { - tcx, - tables: tcx.typeck_tables_of(def_id), - substs: substs, - fn_args: None - }; - + let tables = tcx.typeck_tables_of(def_id); let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) { tcx.mir_const_qualif(def_id); tcx.hir.body(tcx.hir.body_owned_by(id)) } else { tcx.sess.cstore.item_body(tcx, def_id) }; - cx.eval(&body.value) + ConstContext::new(tcx, tables, substs).eval(&body.value) } diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 0a966b0c170..07c45d3ee51 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -266,17 +266,19 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } } -pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> { - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: &'a ty::TypeckTables<'gcx>, +pub struct PatternContext<'a, 'tcx: 'a> { + pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + pub tables: &'a ty::TypeckTables<'tcx>, + pub substs: &'tcx Substs<'tcx>, pub errors: Vec<PatternError<'tcx>>, } -impl<'a, 'gcx, 'tcx> Pattern<'tcx> { - pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, - tables: &'a ty::TypeckTables<'gcx>, +impl<'a, 'tcx> Pattern<'tcx> { + pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, + substs: &'tcx Substs<'tcx>, pat: &hir::Pat) -> Self { - let mut pcx = PatternContext::new(tcx, tables); + let mut pcx = PatternContext::new(tcx, tables, substs); let result = pcx.lower_pattern(pat); if !pcx.errors.is_empty() { span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors) @@ -286,9 +288,11 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> { } } -impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, tables: &'a ty::TypeckTables<'gcx>) -> Self { - PatternContext { tcx: tcx, tables: tables, errors: vec![] } +impl<'a, 'tcx> PatternContext<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, + substs: &'tcx Substs<'tcx>) -> Self { + PatternContext { tcx, tables, substs, errors: vec![] } } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { @@ -583,20 +587,22 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let def = self.tables.qpath_def(qpath, id); let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let tcx = self.tcx.global_tcx(); let substs = self.tables.node_substs(id); - match eval::lookup_const_by_id(tcx, def_id, substs) { - Some((def_id, _substs)) => { - // Enter the inlined constant's tables temporarily. + match eval::lookup_const_by_id(self.tcx, def_id, substs) { + Some((def_id, substs)) => { + // Enter the inlined constant's tables&substs temporarily. let old_tables = self.tables; - self.tables = tcx.typeck_tables_of(def_id); - let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) { - tcx.hir.body(tcx.hir.body_owned_by(id)) + let old_substs = self.substs; + self.tables = self.tcx.typeck_tables_of(def_id); + self.substs = substs; + let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { + self.tcx.hir.body(self.tcx.hir.body_owned_by(id)) } else { - tcx.sess.cstore.item_body(tcx, def_id) + self.tcx.sess.cstore.item_body(self.tcx, def_id) }; let pat = self.lower_const_expr(&body.value, pat_id, span); self.tables = old_tables; + self.substs = old_substs; return pat; } None => { @@ -616,7 +622,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> { - let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables); + let const_cx = eval::ConstContext::new(self.tcx, self.tables, self.substs); match const_cx.eval(expr) { Ok(value) => { if let ConstVal::Variant(def_id) = value { |
