Skip to content

Commit

Permalink
Resolve regions too when normalizing param env.
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Feb 24, 2015
1 parent db6ae66 commit eb841fc
Showing 1 changed file with 50 additions and 41 deletions.
91 changes: 50 additions & 41 deletions src/librustc/middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use self::ObligationCauseCode::*;
use middle::subst;
use middle::ty::{self, HasProjectionTypes, Ty};
use middle::ty_fold::TypeFoldable;
use middle::infer::{self, InferCtxt};
use middle::infer::{self, fixup_err_to_string, InferCtxt};
use std::slice::Iter;
use std::rc::Rc;
use syntax::ast;
Expand Down Expand Up @@ -395,53 +395,64 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
}
}

/// Normalizes the parameter environment, reporting errors if they occur.
pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
cause: ObligationCause<'tcx>)
-> ty::ParameterEnvironment<'a,'tcx>
{
match normalize_param_env(&unnormalized_env, cause) {
Ok(p) => p,
// I'm not wild about reporting errors here; I'd prefer to
// have the errors get reported at a defined place (e.g.,
// during typeck). Instead I have all parameter
// environments, in effect, going through this function
// and hence potentially reporting errors. This ensurse of
// course that we never forget to normalize (the
// alternative seemed like it would involve a lot of
// manual invocations of this fn -- and then we'd have to
// deal with the errors at each of those sites).
//
// In any case, in practice, typeck constructs all the
// parameter environments once for every fn as it goes,
// and errors will get reported then; so after typeck we
// can be sure that no errors should occur.

let tcx = unnormalized_env.tcx;
let span = cause.span;
let body_id = cause.body_id;

debug!("normalize_param_env_or_error(unnormalized_env={})",
unnormalized_env.repr(tcx));

let infcx = infer::new_infer_ctxt(tcx);
let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
&unnormalized_env.caller_bounds) {
Ok(predicates) => predicates,
Err(errors) => {
// I'm not wild about reporting errors here; I'd prefer to
// have the errors get reported at a defined place (e.g.,
// during typeck). Instead I have all parameter
// environments, in effect, going through this function
// and hence potentially reporting errors. This ensurse of
// course that we never forget to normalize (the
// alternative seemed like it would involve a lot of
// manual invocations of this fn -- and then we'd have to
// deal with the errors at each of those sites).
//
// In any case, in practice, typeck constructs all the
// parameter environments once for every fn as it goes,
// and errors will get reported then; so after typeck we
// can be sure that no errors should occur.
let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
report_fulfillment_errors(&infcx, &errors);

// Normalized failed? use what they gave us, it's better than nothing.
unnormalized_env
return unnormalized_env; // an unnormalized env is better than nothing
}
}
}

pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
cause: ObligationCause<'tcx>)
-> Result<ty::ParameterEnvironment<'a,'tcx>,
Vec<FulfillmentError<'tcx>>>
{
let tcx = param_env.tcx;

debug!("normalize_param_env(param_env={})",
param_env.repr(tcx));
};

let infcx = infer::new_infer_ctxt(tcx);
let predicates = try!(fully_normalize(&infcx, param_env, cause, &param_env.caller_bounds));
infcx.resolve_regions_and_report_errors(body_id);
let predicates = match infcx.fully_resolve(&predicates) {
Ok(predicates) => predicates,
Err(fixup_err) => {
// If we encounter a fixup error, it means that some type
// variable wound up unconstrained. I actually don't know
// if this can happen, and I certainly don't expect it to
// happen often, but if it did happen it probably
// represents a legitimate failure due to some kind of
// unconstrained variable, and it seems better not to ICE,
// all things considered.
let err_msg = fixup_err_to_string(fixup_err);
tcx.sess.span_err(span, &err_msg);
return unnormalized_env; // an unnormalized env is better than nothing
}
};

debug!("normalize_param_env: predicates={}",
debug!("normalize_param_env_or_error: predicates={}",
predicates.repr(tcx));

Ok(param_env.with_caller_bounds(predicates))
unnormalized_env.with_caller_bounds(predicates)
}

pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
Expand All @@ -453,8 +464,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
{
let tcx = closure_typer.tcx();

debug!("normalize_param_env(value={})",
value.repr(tcx));
debug!("normalize_param_env(value={})", value.repr(tcx));

let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
let mut fulfill_cx = FulfillmentContext::new();
Expand All @@ -468,8 +478,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
}
try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
debug!("normalize_param_env: resolved_value={}",
resolved_value.repr(tcx));
debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
Ok(resolved_value)
}

Expand Down

0 comments on commit eb841fc

Please sign in to comment.