From b588edc41374c217b290dad0a27d6206ef183cdb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 12 Nov 2017 06:02:29 -0500 Subject: [PATCH] only normalize operand types when in an ADT constructor --- src/librustc_mir/transform/nll/mod.rs | 2 +- src/librustc_mir/transform/type_check.rs | 27 +++++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 147f061ad11..63cbc637547 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -47,7 +47,7 @@ pub fn compute_regions<'a, 'gcx, 'tcx>( // Run the MIR type-checker. let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap(); - let constraint_sets = &type_check::type_check(infcx, mir_node_id, param_env, mir); + let constraint_sets = &type_check::type_check(infcx, mir_node_id, param_env, mir, def_id); // Create the region inference context, taking ownership of the region inference // data that was contained in `infcx`. diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 6888225de75..cdfa506a3c2 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -11,6 +11,8 @@ //! This pass type-checks the MIR to ensure it is not broken. #![allow(unreachable_code)] +use rustc::hir::def_id::DefId; +use rustc::hir::map::DefPathData; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::infer::region_constraints::RegionConstraintData; use rustc::traits::{self, FulfillmentContext}; @@ -41,8 +43,9 @@ pub fn type_check<'a, 'gcx, 'tcx>( body_id: ast::NodeId, param_env: ty::ParamEnv<'gcx>, mir: &Mir<'tcx>, + mir_def_id: DefId, ) -> MirTypeckRegionConstraints<'tcx> { - let mut checker = TypeChecker::new(infcx, body_id, param_env); + let mut checker = TypeChecker::new(infcx, body_id, param_env, mir_def_id); let errors_reported = { let mut verifier = TypeVerifier::new(&mut checker, mir); verifier.visit_mir(mir); @@ -408,6 +411,11 @@ pub struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { body_id: ast::NodeId, reported_errors: FxHashSet<(Ty<'tcx>, Span)>, constraints: MirTypeckRegionConstraints<'tcx>, + + // FIXME(#45940) - True if this is a MIR shim or ADT constructor + // (e.g., for a tuple struct.) In that case, the internal types of + // operands and things require normalization. + is_adt_constructor: bool, } /// A collection of region constraints that must be satisfied for the @@ -459,7 +467,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, body_id: ast::NodeId, param_env: ty::ParamEnv<'gcx>, + mir_def_id: DefId, ) -> Self { + let def_key = infcx.tcx.def_key(mir_def_id); + let is_adt_constructor = match def_key.disambiguated_data.data { + DefPathData::StructCtor => true, + _ => false, + }; + TypeChecker { infcx, last_span: DUMMY_SP, @@ -467,6 +482,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { param_env, reported_errors: FxHashSet(), constraints: MirTypeckRegionConstraints::default(), + is_adt_constructor, } } @@ -1086,7 +1102,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }; let op_ty = match op { Operand::Consume(lv) => { - self.normalize(&lv.ty(mir, tcx), location).to_ty(tcx) + let lv_ty = lv.ty(mir, tcx).to_ty(tcx); + if self.is_adt_constructor { + self.normalize(&lv_ty, location) + } else { + lv_ty + } } Operand::Constant(c) => c.ty, }; @@ -1178,7 +1199,7 @@ impl MirPass for TypeckMir { } let param_env = tcx.param_env(def_id); tcx.infer_ctxt().enter(|infcx| { - let _region_constraint_sets = type_check(&infcx, id, param_env, mir); + let _region_constraint_sets = type_check(&infcx, id, param_env, mir, def_id); // For verification purposes, we just ignore the resulting // region constraint sets. Not our problem. =)