Move projection_mode to InferContext rather than SelectionContext to reduce chance of bugs

This commit is contained in:
Aaron Turon 2016-02-23 12:47:09 -08:00
parent 386f8eefc0
commit 9bcfdb7b9c
27 changed files with 225 additions and 184 deletions

View File

@ -25,6 +25,7 @@ use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization::{cmt};
use middle::pat_util::*;
use middle::traits::ProjectionMode;
use middle::ty::*;
use middle::ty;
use std::cmp::Ordering;
@ -1101,7 +1102,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
//FIXME: (@jroesch) this code should be floated up as well
let infcx = infer::new_infer_ctxt(cx.tcx,
&cx.tcx.tables,
Some(cx.param_env.clone()));
Some(cx.param_env.clone()),
ProjectionMode::AnyFinal);
if infcx.type_moves_by_default(pat_ty, pat.span) {
check_move(p, sub.as_ref().map(|p| &**p));
}
@ -1133,7 +1135,8 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
let infcx = infer::new_infer_ctxt(cx.tcx,
&cx.tcx.tables,
Some(checker.cx.param_env.clone()));
Some(checker.cx.param_env.clone()),
ProjectionMode::AnyFinal);
let mut visitor = ExprUseVisitor::new(&mut checker, &infcx);
visitor.walk_expr(guard);

View File

@ -24,6 +24,7 @@ use middle::def_id::DefId;
use middle::pat_util::def_to_path;
use middle::ty::{self, Ty, TyCtxt};
use middle::ty::util::IntTypeExt;
use middle::traits::ProjectionMode;
use middle::astconv_util::ast_ty_to_prim_ty;
use util::nodemap::NodeMap;
@ -1049,7 +1050,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
trait_ref);
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
let mut selcx = traits::SelectionContext::new(&infcx);
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
@ -1067,6 +1068,11 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
}
};
// NOTE: this code does not currently account for specialization, but when
// it does so, it should hook into the ProjectionMode to determine when the
// constant should resolve; this will also require plumbing through to this
// function whether we are in "trans mode" to pick the right ProjectionMode
// when constructing the inference context above.
match selection {
traits::VtableImpl(ref impl_data) => {
match tcx.associated_consts(impl_data.impl_def_id)

View File

@ -27,7 +27,7 @@ use middle::region::CodeExtent;
use middle::subst;
use middle::subst::Substs;
use middle::subst::Subst;
use middle::traits;
use middle::traits::{self, ProjectionMode};
use middle::ty::adjustment;
use middle::ty::{TyVid, IntVid, FloatVid};
use middle::ty::{self, Ty, TyCtxt};
@ -99,6 +99,11 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
// directly.
normalize: bool,
// Sadly, the behavior of projection varies a bit depending on the
// stage of compilation. The specifics are given in the
// documentation for `ProjectionMode`.
projection_mode: ProjectionMode,
err_count_on_creation: usize,
}
@ -354,7 +359,8 @@ pub fn fixup_err_to_string(f: FixupError) -> String {
pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
tables: &'a RefCell<ty::Tables<'tcx>>,
param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
projection_mode: ProjectionMode)
-> InferCtxt<'a, 'tcx> {
InferCtxt {
tcx: tcx,
@ -366,14 +372,16 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
reported_trait_errors: RefCell::new(FnvHashSet()),
normalize: false,
projection_mode: projection_mode,
err_count_on_creation: tcx.sess.err_count()
}
}
pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
tables: &'a RefCell<ty::Tables<'tcx>>)
tables: &'a RefCell<ty::Tables<'tcx>>,
projection_mode: ProjectionMode)
-> InferCtxt<'a, 'tcx> {
let mut infcx = new_infer_ctxt(tcx, tables, None);
let mut infcx = new_infer_ctxt(tcx, tables, None, projection_mode);
infcx.normalize = true;
infcx
}
@ -514,6 +522,7 @@ pub struct CombinedSnapshot {
region_vars_snapshot: RegionSnapshot,
}
// NOTE: Callable from trans only!
pub fn normalize_associated_type<'tcx,T>(tcx: &TyCtxt<'tcx>, value: &T) -> T
where T : TypeFoldable<'tcx>
{
@ -525,7 +534,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &TyCtxt<'tcx>, value: &T) -> T
return value;
}
let infcx = new_infer_ctxt(tcx, &tcx.tables, None);
let infcx = new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::Any);
let mut selcx = traits::SelectionContext::new(&infcx);
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: result, obligations } =
@ -593,6 +602,10 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn projection_mode(&self) -> ProjectionMode {
self.projection_mode
}
pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}

View File

@ -10,7 +10,6 @@
//! See `README.md` for high-level documentation
use super::build_selcx;
use super::{SelectionContext, Obligation, ObligationCause};
use super::util;
@ -37,7 +36,7 @@ pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx>,
impl1_def_id,
impl2_def_id);
let selcx = &mut build_selcx(infcx).project_topmost().intercrate().build();
let selcx = &mut SelectionContext::intercrate(infcx);
overlap(selcx, impl1_def_id, impl2_def_id)
}

View File

@ -36,17 +36,15 @@ pub use self::coherence::orphan_check;
pub use self::coherence::overlapping_impls;
pub use self::coherence::OrphanCheckErr;
pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
pub use self::project::MismatchedProjectionTypes;
pub use self::project::normalize;
pub use self::project::Normalized;
pub use self::project::{MismatchedProjectionTypes, ProjectionMode};
pub use self::project::{normalize, Normalized};
pub use self::object_safety::is_object_safe;
pub use self::object_safety::astconv_object_safety_violations;
pub use self::object_safety::object_safety_violations;
pub use self::object_safety::ObjectSafetyViolation;
pub use self::object_safety::MethodViolationCode;
pub use self::object_safety::is_vtable_safe_method;
pub use self::select::{EvaluationCache, SelectionContextBuilder, build_selcx};
pub use self::select::{ProjectionMode, SelectionContext, SelectionCache};
pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
pub use self::specialize::{Overlap, specialization_graph, specializes, translate_substs};
@ -435,7 +433,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), ProjectionMode::AnyFinal);
let predicates = match fully_normalize(&infcx,
cause,
&infcx.parameter_environment.caller_bounds) {

View File

@ -35,6 +35,94 @@ use util::common::FN_OUTPUT_NAME;
use std::rc::Rc;
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ProjectionMode {
/// At coherence-checking time, we're still constructing the
/// specialization graph, and thus we only project project
/// non-`default` associated types that are defined directly in
/// the applicable impl. (This behavior should be improved over
/// time, to allow for successful projections modulo cycles
/// between different impls).
// TODO: Add tracking issue to do better here.
///
/// Here's an example that will fail due to the restriction:
///
/// ```
/// trait Assoc {
/// type Output;
/// }
///
/// impl<T> Assoc for T {
/// type Output = bool;
/// }
///
/// impl Assoc for u8 {} // <- inherits the non-default type from above
///
/// trait Foo {}
/// impl Foo for u32 {}
/// impl Foo for <u8 as Assoc>::Output {} // <- this projection will fail
/// ```
///
/// The projection would succeed if `Output` had been defined
/// directly in the impl for `u8`.
// TODO: Add test
Topmost,
/// At type-checking time, we refuse to project any associated
/// type that is marked `default`. Non-`default` ("final") types
/// are always projected. This is necessary in general for
/// soundness of specialization. However, we *could* allow
/// projections in fully-monomorphic cases. We choose not to,
/// because we prefer for `default type` to force the type
/// definition to be treated abstractly by any consumers of the
/// impl. Concretely, that means that the following example will
/// fail to compile:
///
/// ```
/// trait Assoc {
/// type Output;
/// }
///
/// impl<T> Assoc for T {
/// default type Output = bool;
/// }
///
/// fn main() {
/// let <() as Assoc>::Output = true;
/// }
// TODO: Add test
AnyFinal,
/// At trans time, all projections will succeed.
Any,
}
impl ProjectionMode {
pub fn topmost(&self) -> bool {
match *self {
ProjectionMode::Topmost => true,
_ => false,
}
}
pub fn any_final(&self) -> bool {
match *self {
ProjectionMode::AnyFinal => true,
_ => false,
}
}
pub fn any(&self) -> bool {
match *self {
ProjectionMode::Any => true,
_ => false,
}
}
}
pub type PolyProjectionObligation<'tcx> =
Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;

View File

@ -25,6 +25,7 @@ use super::report_overflow_error;
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
use super::{ObjectCastObligation, Obligation};
use super::ProjectionMode;
use super::TraitNotObjectSafe;
use super::Selection;
use super::SelectionResult;
@ -77,98 +78,6 @@ pub struct SelectionContext<'cx, 'tcx:'cx> {
/// there is no type that the user could *actually name* that
/// would satisfy it. This avoids crippling inference, basically.
intercrate: bool,
/// Sadly, the behavior of projection varies a bit depending on the
/// stage of compilation. The specifics are given in the
/// documentation for `ProjectionMode`.
projection_mode: ProjectionMode,
}
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ProjectionMode {
/// At coherence-checking time, we're still constructing the
/// specialization graph, and thus we only project project
/// non-`default` associated types that are defined directly in
/// the applicable impl. (This behavior should be improved over
/// time, to allow for successful projections modulo cycles
/// between different impls).
// TODO: Add tracking issue to do better here.
///
/// Here's an example that will fail due to the restriction:
///
/// ```
/// trait Assoc {
/// type Output;
/// }
///
/// impl<T> Assoc for T {
/// type Output = bool;
/// }
///
/// impl Assoc for u8 {} // <- inherits the non-default type from above
///
/// trait Foo {}
/// impl Foo for u32 {}
/// impl Foo for <u8 as Assoc>::Output {} // <- this projection will fail
/// ```
///
/// The projection would succeed if `Output` had been defined
/// directly in the impl for `u8`.
// TODO: Add test
Topmost,
/// At type-checking time, we refuse to project any associated
/// type that is marked `default`. Non-`default` ("final") types
/// are always projected. This is necessary in general for
/// soundness of specialization. However, we *could* allow
/// projections in fully-monomorphic cases. We choose not to,
/// because we prefer for `default type` to force the type
/// definition to be treated abstractly by any consumers of the
/// impl. Concretely, that means that the following example will
/// fail to compile:
///
/// ```
/// trait Assoc {
/// type Output;
/// }
///
/// impl<T> Assoc for T {
/// default type Output = bool;
/// }
///
/// fn main() {
/// let <() as Assoc>::Output = true;
/// }
// TODO: Add test
AnyFinal,
/// At trans time, all projections will succeed.
Any,
}
impl ProjectionMode {
pub fn topmost(&self) -> bool {
match *self {
ProjectionMode::Topmost => true,
_ => false,
}
}
pub fn any_final(&self) -> bool {
match *self {
ProjectionMode::AnyFinal => true,
_ => false,
}
}
pub fn any(&self) -> bool {
match *self {
ProjectionMode::Any => true,
_ => false,
}
}
}
// A stack that walks back up the stack frame.
@ -348,45 +257,20 @@ pub struct EvaluationCache<'tcx> {
hashmap: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, EvaluationResult>>
}
pub struct SelectionContextBuilder<'cx, 'tcx: 'cx>(SelectionContext<'cx, 'tcx>);
impl<'cx, 'tcx> SelectionContextBuilder<'cx, 'tcx> {
pub fn intercrate(mut self) -> Self {
self.0.intercrate = true;
self
}
pub fn project_any(mut self) -> Self {
self.0.projection_mode = ProjectionMode::Any;
self
}
pub fn project_any_final(mut self) -> Self {
self.0.projection_mode = ProjectionMode::AnyFinal;
self
}
pub fn project_topmost(mut self) -> Self {
self.0.projection_mode = ProjectionMode::Topmost;
self
}
pub fn build(self) -> SelectionContext<'cx, 'tcx> {
self.0
}
}
pub fn build_selcx<'cx, 'tcx>(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContextBuilder<'cx, 'tcx> {
SelectionContextBuilder(SelectionContext::new(infcx))
}
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
freshener: infcx.freshener(),
intercrate: false,
projection_mode: ProjectionMode::AnyFinal,
}
}
pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx: infcx,
freshener: infcx.freshener(),
intercrate: true,
}
}
@ -407,7 +291,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
pub fn projection_mode(&self) -> ProjectionMode {
self.projection_mode
self.infcx.projection_mode()
}
///////////////////////////////////////////////////////////////////////////

View File

@ -17,7 +17,7 @@
// See traits/README.md for a bit more detail on how specialization
// fits together with the rest of the trait machinery.
use super::{build_selcx, SelectionContext, FulfillmentContext};
use super::{SelectionContext, FulfillmentContext};
use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig};
use middle::cstore::CrateStore;
@ -25,7 +25,7 @@ use middle::def_id::DefId;
use middle::infer::{self, InferCtxt, TypeOrigin};
use middle::region;
use middle::subst::{Subst, Substs};
use middle::traits;
use middle::traits::{self, ProjectionMode};
use middle::ty;
use syntax::codemap::DUMMY_SP;
@ -159,7 +159,7 @@ pub fn specializes(tcx: &ty::ctxt, impl1_def_id: DefId, impl2_def_id: DefId) ->
return false
}
let mut infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
let mut infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Topmost);
// Skiolemize impl1: we want to prove that "for all types matched by impl1,
// those types are also matched by impl2".
@ -199,7 +199,7 @@ fn fulfill_implication<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-> Result<Substs<'tcx>, ()>
{
infcx.probe(|_| {
let selcx = &mut build_selcx(&infcx).project_topmost().build();
let selcx = &mut SelectionContext::new(&infcx);
let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl);
let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx,
target_impl,

View File

@ -16,7 +16,7 @@ use super::{Overlap, specializes};
use middle::cstore::CrateStore;
use middle::def_id::DefId;
use middle::infer;
use middle::traits;
use middle::traits::{self, ProjectionMode};
use middle::ty::{self, ImplOrTraitItem, TraitDef, TypeFoldable};
use syntax::ast::Name;
use util::nodemap::DefIdMap;
@ -93,7 +93,7 @@ impl Graph {
for slot in possible_siblings.iter_mut() {
let possible_sibling = *slot;
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::Topmost);
let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id);
if let Some(trait_ref) = overlap {

View File

@ -17,7 +17,7 @@ use middle::def_id::DefId;
use middle::subst;
use middle::infer;
use middle::pat_util;
use middle::traits;
use middle::traits::{self, ProjectionMode};
use middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
use middle::ty::{Disr, ParameterEnvironment};
use middle::ty::TypeVariants::*;
@ -130,7 +130,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
let tcx = self.tcx;
// FIXME: (@jroesch) float this code up
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()));
let infcx = infer::new_infer_ctxt(tcx,
&tcx.tables,
Some(self.clone()),
ProjectionMode::AnyFinal);
let adt = match self_type.sty {
ty::TyStruct(struct_def, substs) => {
@ -542,7 +545,10 @@ impl<'tcx> ty::TyS<'tcx> {
-> bool
{
let tcx = param_env.tcx;
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()));
let infcx = infer::new_infer_ctxt(tcx,
&tcx.tables,
Some(param_env.clone()),
ProjectionMode::AnyFinal);
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
self, bound, span);

View File

@ -27,6 +27,7 @@ use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization;
use rustc::middle::region;
use rustc::middle::ty::{self, TyCtxt};
use rustc::middle::traits::ProjectionMode;
use syntax::ast;
use syntax::codemap::Span;
use rustc_front::hir;
@ -202,7 +203,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
debug!("check_loans(body id={})", body.id);
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env));
let infcx = infer::new_infer_ctxt(bccx.tcx,
&bccx.tcx.tables,
Some(param_env),
ProjectionMode::AnyFinal);
let mut clcx = CheckLoanCtxt {
bccx: bccx,

View File

@ -24,6 +24,7 @@ use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization;
use rustc::middle::region;
use rustc::middle::ty::{self, TyCtxt};
use rustc::middle::traits::ProjectionMode;
use syntax::ast;
use syntax::codemap::Span;
@ -55,7 +56,10 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
};
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
let infcx = infer::new_infer_ctxt(bccx.tcx, &bccx.tcx.tables, Some(param_env));
let infcx = infer::new_infer_ctxt(bccx.tcx,
&bccx.tcx.tables,
Some(param_env),
ProjectionMode::AnyFinal);
{
let mut euv = euv::ExprUseVisitor::new(&mut glcx, &infcx);
euv.walk_fn(decl, body);
@ -525,7 +529,10 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> {
impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
fn visit_expr(&mut self, ex: &Expr) {
if let hir::ExprAddrOf(mutbl, ref base) = ex.node {
let infcx = infer::new_infer_ctxt(self.bccx.tcx, &self.bccx.tcx.tables, None);
let infcx = infer::new_infer_ctxt(self.bccx.tcx,
&self.bccx.tcx.tables,
None,
ProjectionMode::AnyFinal);
let mc = mc::MemCategorizationContext::new(&infcx);
let base_cmt = mc.cat_expr(&base).unwrap();
let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);

View File

@ -35,6 +35,7 @@ use middle::def_id::DefId;
use middle::subst::Substs;
use middle::ty::{self, Ty, TyCtxt};
use middle::ty::adjustment;
use middle::traits::ProjectionMode;
use rustc::front::map as hir_map;
use util::nodemap::{NodeSet};
use lint::{Level, LateContext, LintContext, LintArray, Lint};
@ -868,7 +869,10 @@ impl LateLintPass for UnconditionalRecursion {
let node_id = tcx.map.as_local_node_id(method.def_id).unwrap();
let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
let infcx = infer::new_infer_ctxt(tcx,
&tcx.tables,
Some(param_env),
ProjectionMode::AnyFinal);
let mut selcx = traits::SelectionContext::new(&infcx);
match selcx.select(&obligation) {
// The method comes from a `T: Trait` bound.

View File

@ -27,7 +27,7 @@ use hair::cx::Cx;
use rustc::mir::mir_map::MirMap;
use rustc::middle::infer;
use rustc::middle::region::CodeExtentData;
use rustc::middle::ty::{self, Ty, TyCtxt};
use rustc::middle::traits::ProjectionMode;
use rustc::util::common::ErrorReported;
use rustc::util::nodemap::NodeMap;
use rustc_front::hir;
@ -137,7 +137,11 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
};
let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
let infcx = infer::new_infer_ctxt(self.tcx,
&self.tcx.tables,
Some(param_env),
ProjectionMode::AnyFinal);
match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
Ok(mir) => assert!(self.map.map.insert(id, mir).is_none()),
Err(ErrorReported) => {}

View File

@ -35,8 +35,8 @@ use rustc::middle::expr_use_visitor as euv;
use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::mem_categorization::Categorization;
use rustc::middle::traits;
use rustc::middle::ty::{self, Ty, TyCtxt};
use rustc::middle::traits::{self, ProjectionMode};
use rustc::util::nodemap::NodeMap;
use rustc::middle::const_qualif::ConstQualif;
use rustc::lint::builtin::CONST_ERR;
@ -92,7 +92,10 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
None => self.tcx.empty_parameter_environment()
};
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
let infcx = infer::new_infer_ctxt(self.tcx,
&self.tcx.tables,
Some(param_env),
ProjectionMode::AnyFinal);
f(&mut euv::ExprUseVisitor::new(self, &infcx))
}
@ -247,7 +250,10 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn check_static_type(&self, e: &hir::Expr) {
let ty = self.tcx.node_id_to_type(e.id);
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
let infcx = infer::new_infer_ctxt(self.tcx,
&self.tcx.tables,
None,
ProjectionMode::AnyFinal);
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
let mut fulfillment_cx = traits::FulfillmentContext::new();
fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);

View File

@ -16,6 +16,7 @@ use rustc::middle::expr_use_visitor as euv;
use rustc::middle::infer;
use rustc::middle::mem_categorization as mc;
use rustc::middle::ty::{self, TyCtxt, ParameterEnvironment};
use rustc::middle::traits::ProjectionMode;
use rustc_front::hir;
use rustc_front::intravisit;
@ -43,7 +44,8 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
let infcx = infer::new_infer_ctxt(self.tcx,
&self.tcx.tables,
Some(param_env.clone()));
Some(param_env.clone()),
ProjectionMode::AnyFinal);
let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
euv.walk_fn(fd, b);

View File

@ -217,6 +217,7 @@ use trans::tvec;
use trans::type_of;
use trans::Disr;
use middle::ty::{self, Ty, TyCtxt};
use middle::traits::ProjectionMode;
use session::config::NoDebugInfo;
use util::common::indenter;
use util::nodemap::FnvHashMap;
@ -1475,7 +1476,9 @@ fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool
reassigned: false
};
{
let infcx = infer::normalizing_infer_ctxt(bcx.tcx(), &bcx.tcx().tables);
let infcx = infer::normalizing_infer_ctxt(bcx.tcx(),
&bcx.tcx().tables,
ProjectionMode::Any);
let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx);
visitor.walk_expr(body);
}

View File

@ -13,6 +13,7 @@ use libc::{c_uint, c_ulonglong};
use llvm::{self, ValueRef, AttrHelper};
use middle::ty;
use middle::infer;
use middle::traits::ProjectionMode;
use session::config::NoDebugInfo;
use syntax::abi::Abi;
pub use syntax::attr::InlineAttr;
@ -133,7 +134,9 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
let (fn_sig, abi, env_ty) = match fn_type.sty {
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => (&f.sig, f.abi, None),
ty::TyClosure(closure_did, ref substs) => {
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(),
&ccx.tcx().tables,
ProjectionMode::Any);
function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
(&function_type.sig, Abi::RustCall, Some(self_type))

View File

@ -13,6 +13,7 @@ use back::link::{self, mangle_internal_name_by_path_and_seq};
use llvm::{ValueRef, get_params};
use middle::def_id::DefId;
use middle::infer;
use middle::traits::ProjectionMode;
use trans::adt;
use trans::attributes;
use trans::base::*;
@ -206,7 +207,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
// this function (`trans_closure`) is invoked at the point
// of the closure expression.
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables, ProjectionMode::Any);
let function_type = infcx.closure_type(closure_def_id, closure_substs);
let freevars: Vec<ty::Freevar> =
@ -329,7 +330,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
ccx.tn().val_to_string(llreffn));
let tcx = ccx.tcx();
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables, ProjectionMode::Any);
// Find a version of the closure type. Substitute static for the
// region since it doesn't really matter.

View File

@ -37,8 +37,8 @@ use trans::machine;
use trans::monomorphize;
use trans::type_::Type;
use trans::type_of;
use middle::traits;
use middle::ty::{self, Ty, TyCtxt};
use middle::traits::{self, SelectionContext, ProjectionMode};
use middle::ty::fold::{TypeFolder, TypeFoldable};
use rustc_front::hir;
use rustc::mir::repr::Mir;
@ -1137,8 +1137,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
let mut selcx = traits::build_selcx(&infcx).project_any().build();
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
let mut selcx = SelectionContext::new(&infcx);
let obligation =
traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
@ -1198,8 +1198,8 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
predicates);
let tcx = ccx.tcx();
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
let mut selcx = traits::build_selcx(&infcx).project_any().build();
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
let mut selcx = SelectionContext::new(&infcx);
let mut fulfill_cx = traits::FulfillmentContext::new();
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: predicates, obligations } =

View File

@ -22,6 +22,7 @@
use llvm::{self, ValueRef};
use middle::ty;
use middle::infer;
use middle::traits::ProjectionMode;
use syntax::abi::Abi;
use trans::attributes;
use trans::base;
@ -111,7 +112,9 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
(&f.sig, f.abi, None)
}
ty::TyClosure(closure_did, ref substs) => {
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
let infcx = infer::normalizing_infer_ctxt(ccx.tcx(),
&ccx.tcx().tables,
ProjectionMode::Any);
function_type = infcx.closure_type(closure_did, substs);
let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);

View File

@ -17,7 +17,7 @@ use middle::def_id::DefId;
use middle::infer;
use middle::subst::{Subst, Substs};
use middle::subst;
use middle::traits;
use middle::traits::{self, ProjectionMode};
use trans::base::*;
use trans::build::*;
use trans::callee::{Callee, Virtual, ArgVals,
@ -488,7 +488,7 @@ pub fn get_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let trait_def = tcx.lookup_trait_def(trait_def_id);
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() {
Some(node_item) => {

View File

@ -10,8 +10,8 @@
use middle::free_region::FreeRegionMap;
use middle::infer::{self, TypeOrigin};
use middle::traits;
use middle::ty::{self, TyCtxt};
use middle::traits::{self, ProjectionMode};
use middle::subst::{self, Subst, Substs, VecPerParamSpace};
use syntax::ast;
@ -42,7 +42,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
impl_trait_ref);
let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
let mut fulfillment_cx = traits::FulfillmentContext::new();
let trait_to_impl_substs = &impl_trait_ref.substs;
@ -416,7 +416,7 @@ pub fn compare_const_impl<'tcx>(tcx: &TyCtxt<'tcx>,
debug!("compare_const_impl(impl_trait_ref={:?})",
impl_trait_ref);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
let mut fulfillment_cx = traits::FulfillmentContext::new();
// The below is for the most part highly similar to the procedure

View File

@ -15,8 +15,8 @@ use middle::free_region::FreeRegionMap;
use middle::infer;
use middle::region;
use middle::subst::{self, Subst};
use middle::traits;
use middle::ty::{self, Ty, TyCtxt};
use middle::traits::{self, ProjectionMode};
use util::nodemap::FnvHashSet;
use syntax::ast;
@ -82,7 +82,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
// check that the impl type can be made to match the trait type.
let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(impl_param_env));
let infcx = infer::new_infer_ctxt(tcx,
&tcx.tables,
Some(impl_param_env),
ProjectionMode::AnyFinal);
let mut fulfillment_cx = traits::FulfillmentContext::new();
let named_type = tcx.lookup_item_type(self_type_did).ty;

View File

@ -92,7 +92,7 @@ use middle::infer;
use middle::infer::{TypeOrigin, TypeTrace, type_variable};
use middle::pat_util::{self, pat_id_map};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
use middle::traits::{self, report_fulfillment_errors};
use middle::traits::{self, report_fulfillment_errors, ProjectionMode};
use middle::ty::{GenericPredicates, TypeScheme};
use middle::ty::{ParamTy, ParameterEnvironment};
use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
@ -307,7 +307,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
-> Inherited<'a, 'tcx> {
Inherited {
infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), ProjectionMode::AnyFinal),
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
locals: RefCell::new(NodeMap()),
tables: tables,

View File

@ -18,8 +18,8 @@
use middle::def_id::DefId;
use middle::lang_items::UnsizeTraitLangItem;
use middle::subst::{self, Subst};
use middle::traits;
use middle::ty::{self, TyCtxt, TypeFoldable};
use middle::traits::{self, ProjectionMode};
use middle::ty::{ImplOrTraitItemId, ConstTraitItemId};
use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
@ -384,7 +384,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
source, target);
let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), ProjectionMode::Topmost);
let origin = TypeOrigin::Misc(span);
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>,
@ -529,7 +529,10 @@ pub fn report_duplicate_item<'tcx>(tcx: &TyCtxt<'tcx>, sp: Span, name: ast::Name
pub fn check_coherence(crate_context: &CrateCtxt) {
let _task = crate_context.tcx.dep_graph.in_task(DepNode::Coherence);
let infcx = new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None);
let infcx = new_infer_ctxt(crate_context.tcx,
&crate_context.tcx.tables,
None,
ProjectionMode::Topmost);
CoherenceChecker {
crate_context: crate_context,
inference_context: infcx,

View File

@ -106,6 +106,7 @@ use middle::def::Def;
use middle::infer::{self, TypeOrigin};
use middle::subst::Substs;
use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use middle::traits::ProjectionMode;
use session::{config, CompileResult};
use util::common::time;
use rustc_front::hir;
@ -196,7 +197,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &TyCtxt<'tcx>,
{
let result = match maybe_infcx {
None => {
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
infer::mk_eqty(&infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2)
}
Some(infcx) => {