--- /dev/null
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This module contains code to equate the input/output types appearing
+//! in the MIR with the expected input/output types from the function
+//! signature. This requires a bit of processing, as the expected types
+//! are supplied to us before normalization and may contain existential
+//! `impl Trait` instances. In contrast, the input/output types found in
+//! the MIR (specifically, in the special local variables for the
+//! `RETURN_PLACE` the MIR arguments) are always fully normalize (and
+//! contain revealed `impl Trait` values).
+
+use borrow_check::nll::universal_regions::UniversalRegions;
+use rustc::ty::Ty;
+use rustc::mir::*;
+
+use rustc_data_structures::indexed_vec::Idx;
+
+use super::{AtLocation, TypeChecker};
+
+impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
+ pub(super) fn equate_inputs_and_outputs(
+ &mut self,
+ mir: &Mir<'tcx>,
+ universal_regions: &UniversalRegions<'tcx>,
+ ) {
+ let &UniversalRegions {
+ unnormalized_output_ty,
+ unnormalized_input_tys,
+ ..
+ } = universal_regions;
+
+ let start_position = Location {
+ block: START_BLOCK,
+ statement_index: 0,
+ };
+
+ // Equate expected input tys with those in the MIR.
+ let argument_locals = (1..).map(Local::new);
+ for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) {
+ let input_ty = self.normalize(&unnormalized_input_ty, start_position);
+ let mir_input_ty = mir.local_decls[local].ty;
+ self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
+ }
+
+ // Return types are a bit more complex. They may contain existential `impl Trait`
+ // types.
+
+ let output_ty = self.normalize(&unnormalized_output_ty, start_position);
+ let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
+ self.equate_normalized_input_or_output(start_position, output_ty, mir_output_ty);
+ }
+
+ fn equate_normalized_input_or_output(&mut self, location: Location, a: Ty<'tcx>, b: Ty<'tcx>) {
+ debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
+
+ if let Err(terr) = self.eq_types(a, b, location.at_self()) {
+ span_mirbug!(
+ self,
+ location,
+ "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
+ a,
+ b,
+ terr
+ );
+ }
+ }
+}
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::Idx;
+macro_rules! span_mirbug {
+ ($context:expr, $elem:expr, $($message:tt)*) => ({
+ $crate::borrow_check::nll::type_check::mirbug(
+ $context.tcx(),
+ $context.last_span,
+ &format!(
+ "broken MIR in {:?} ({:?}): {}",
+ $context.body_id,
+ $elem,
+ format_args!($($message)*),
+ ),
+ )
+ })
+}
+
+macro_rules! span_mirbug_and_err {
+ ($context:expr, $elem:expr, $($message:tt)*) => ({
+ {
+ span_mirbug!($context, $elem, $($message)*);
+ $context.error()
+ }
+ })
+}
+
mod liveness;
+mod input_output;
/// Type checks the given `mir` in the context of the inference
/// context `infcx`. Returns any region constraints that have yet to
&mut |cx| {
liveness::generate(cx, mir, liveness, flow_inits, move_data);
- // Equate the input and output tys given by the user with
- // the ones found in the MIR.
- let &UniversalRegions {
- unnormalized_output_ty,
- unnormalized_input_tys,
- ..
- } = universal_regions;
- cx.equate_input_or_output(unnormalized_output_ty, mir.local_decls[RETURN_PLACE].ty);
- let arg_locals = (1..).map(Local::new);
- for (&input_ty, local) in unnormalized_input_tys.iter().zip(arg_locals) {
- cx.equate_input_or_output(input_ty, mir.local_decls[local].ty);
- }
+ cx.equate_inputs_and_outputs(mir, universal_regions);
},
)
}
checker.constraints
}
-
fn mirbug(tcx: TyCtxt, span: Span, msg: &str) {
// We sometimes see MIR failures (notably predicate failures) due to
// the fact that we check rvalue sized predicates here. So use `delay_span_bug`
tcx.sess.diagnostic().delay_span_bug(span, msg);
}
-macro_rules! span_mirbug {
- ($context:expr, $elem:expr, $($message:tt)*) => ({
- mirbug($context.tcx(), $context.last_span,
- &format!("broken MIR in {:?} ({:?}): {}",
- $context.body_id,
- $elem,
- format_args!($($message)*)))
- })
-}
-
-macro_rules! span_mirbug_and_err {
- ($context:expr, $elem:expr, $($message:tt)*) => ({
- {
- span_mirbug!($context, $elem, $($message)*);
- $context.error()
- }
- })
-}
-
enum FieldAccessError {
OutOfRange { field_count: usize },
}
})
}
- fn equate_input_or_output(&mut self, unnormalized_a: Ty<'tcx>, b: Ty<'tcx>) {
- let start_position = Location {
- block: START_BLOCK,
- statement_index: 0,
- };
- let a = self.normalize(&unnormalized_a, start_position);
- if let Err(terr) = self.eq_types(a, b, start_position.at_self()) {
- span_mirbug!(
- self,
- start_position,
- "bad input or output {:?} normalized to {:?} should equal {:?} but got error {:?}",
- unnormalized_a,
- a,
- b,
- terr
- );
- }
- }
-
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
self.infcx.tcx
}