From e3cff797a7dcc2358b37c170dc9d83d34d118725 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 30 May 2016 21:41:05 +0300 Subject: [PATCH] normalize types in MIR typeck after erasing regions --- src/librustc_mir/transform/type_check.rs | 49 +++++++++---------- .../run-pass/mir_call_with_associated_type.rs | 29 +++++++++++ 2 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 src/test/run-pass/mir_call_with_associated_type.rs diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 40157aa934c..80c56a5dc08 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -118,10 +118,6 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.cx.infcx.tcx } - fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> { - self.cx.infcx - } - fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { if ty.needs_infer() || ty.has_escaping_regions() || ty.references_error() { span_mirbug_and_err!(self, parent, "bad type {:?}", ty) @@ -292,30 +288,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }; if let Some(field) = variant.fields.get(field.index()) { - Ok(self.normalize(field.ty(tcx, substs))) + Ok(self.cx.normalize(&field.ty(tcx, substs))) } else { Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() }) } } - - fn normalize(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let infcx = self.infcx(); - let mut selcx = traits::SelectionContext::new(infcx); - let cause = traits::ObligationCause::misc(self.last_span, 0); - let traits::Normalized { value: ty, obligations } = - traits::normalize(&mut selcx, cause, &ty); - - debug!("normalize: ty={:?} obligations={:?}", - ty, - obligations); - - let mut fulfill_cx = &mut self.cx.fulfillment_cx; - for obligation in obligations { - fulfill_cx.register_predicate_obligation(infcx, obligation); - } - - ty - } } pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { @@ -373,7 +350,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn check_terminator(&self, + fn check_terminator(&mut self, mir: &Mir<'tcx>, term: &Terminator<'tcx>) { debug!("check_terminator: {:?}", term); @@ -431,6 +408,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } }; let sig = tcx.erase_late_bound_regions(&func_ty.sig); + let sig = self.normalize(&sig); self.check_call_dest(mir, term, &sig, destination); if self.is_box_free(func) { @@ -558,6 +536,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } + + fn normalize(&mut self, value: &T) -> T + where T: fmt::Debug + TypeFoldable<'tcx> + { + let mut selcx = traits::SelectionContext::new(self.infcx); + let cause = traits::ObligationCause::misc(self.last_span, 0); + let traits::Normalized { value, obligations } = + traits::normalize(&mut selcx, cause, value); + + debug!("normalize: value={:?} obligations={:?}", + value, + obligations); + + let mut fulfill_cx = &mut self.fulfillment_cx; + for obligation in obligations { + fulfill_cx.register_predicate_obligation(self.infcx, obligation); + } + + value + } + fn verify_obligations(&mut self, mir: &Mir<'tcx>) { self.last_span = mir.span; if let Err(e) = self.fulfillment_cx.select_all_or_error(self.infcx) { diff --git a/src/test/run-pass/mir_call_with_associated_type.rs b/src/test/run-pass/mir_call_with_associated_type.rs new file mode 100644 index 00000000000..08401c275a5 --- /dev/null +++ b/src/test/run-pass/mir_call_with_associated_type.rs @@ -0,0 +1,29 @@ +// Copyright 2016 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. + +#![feature(rustc_attrs)] + +trait Trait { + type Type; +} + +impl<'a> Trait for &'a () { + type Type = u32; +} + +#[rustc_mir] +fn foo<'a>(t: <&'a () as Trait>::Type) -> <&'a () as Trait>::Type { + t +} + +#[rustc_mir] +fn main() { + assert_eq!(foo(4), 4); +}