Skip to content

Commit eb841fc

Browse files
committed
Resolve regions too when normalizing param env.
1 parent db6ae66 commit eb841fc

File tree

1 file changed

+50
-41
lines changed
  • src/librustc/middle/traits

1 file changed

+50
-41
lines changed

src/librustc/middle/traits/mod.rs

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use self::ObligationCauseCode::*;
1818
use middle::subst;
1919
use middle::ty::{self, HasProjectionTypes, Ty};
2020
use middle::ty_fold::TypeFoldable;
21-
use middle::infer::{self, InferCtxt};
21+
use middle::infer::{self, fixup_err_to_string, InferCtxt};
2222
use std::slice::Iter;
2323
use std::rc::Rc;
2424
use syntax::ast;
@@ -395,53 +395,64 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
395395
}
396396
}
397397

398+
/// Normalizes the parameter environment, reporting errors if they occur.
398399
pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
399400
cause: ObligationCause<'tcx>)
400401
-> ty::ParameterEnvironment<'a,'tcx>
401402
{
402-
match normalize_param_env(&unnormalized_env, cause) {
403-
Ok(p) => p,
403+
// I'm not wild about reporting errors here; I'd prefer to
404+
// have the errors get reported at a defined place (e.g.,
405+
// during typeck). Instead I have all parameter
406+
// environments, in effect, going through this function
407+
// and hence potentially reporting errors. This ensurse of
408+
// course that we never forget to normalize (the
409+
// alternative seemed like it would involve a lot of
410+
// manual invocations of this fn -- and then we'd have to
411+
// deal with the errors at each of those sites).
412+
//
413+
// In any case, in practice, typeck constructs all the
414+
// parameter environments once for every fn as it goes,
415+
// and errors will get reported then; so after typeck we
416+
// can be sure that no errors should occur.
417+
418+
let tcx = unnormalized_env.tcx;
419+
let span = cause.span;
420+
let body_id = cause.body_id;
421+
422+
debug!("normalize_param_env_or_error(unnormalized_env={})",
423+
unnormalized_env.repr(tcx));
424+
425+
let infcx = infer::new_infer_ctxt(tcx);
426+
let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
427+
&unnormalized_env.caller_bounds) {
428+
Ok(predicates) => predicates,
404429
Err(errors) => {
405-
// I'm not wild about reporting errors here; I'd prefer to
406-
// have the errors get reported at a defined place (e.g.,
407-
// during typeck). Instead I have all parameter
408-
// environments, in effect, going through this function
409-
// and hence potentially reporting errors. This ensurse of
410-
// course that we never forget to normalize (the
411-
// alternative seemed like it would involve a lot of
412-
// manual invocations of this fn -- and then we'd have to
413-
// deal with the errors at each of those sites).
414-
//
415-
// In any case, in practice, typeck constructs all the
416-
// parameter environments once for every fn as it goes,
417-
// and errors will get reported then; so after typeck we
418-
// can be sure that no errors should occur.
419-
let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
420430
report_fulfillment_errors(&infcx, &errors);
421-
422-
// Normalized failed? use what they gave us, it's better than nothing.
423-
unnormalized_env
431+
return unnormalized_env; // an unnormalized env is better than nothing
424432
}
425-
}
426-
}
427-
428-
pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
429-
cause: ObligationCause<'tcx>)
430-
-> Result<ty::ParameterEnvironment<'a,'tcx>,
431-
Vec<FulfillmentError<'tcx>>>
432-
{
433-
let tcx = param_env.tcx;
434-
435-
debug!("normalize_param_env(param_env={})",
436-
param_env.repr(tcx));
433+
};
437434

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

441-
debug!("normalize_param_env: predicates={}",
452+
debug!("normalize_param_env_or_error: predicates={}",
442453
predicates.repr(tcx));
443454

444-
Ok(param_env.with_caller_bounds(predicates))
455+
unnormalized_env.with_caller_bounds(predicates)
445456
}
446457

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

456-
debug!("normalize_param_env(value={})",
457-
value.repr(tcx));
467+
debug!("normalize_param_env(value={})", value.repr(tcx));
458468

459469
let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
460470
let mut fulfill_cx = FulfillmentContext::new();
@@ -468,8 +478,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
468478
}
469479
try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
470480
let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
471-
debug!("normalize_param_env: resolved_value={}",
472-
resolved_value.repr(tcx));
481+
debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
473482
Ok(resolved_value)
474483
}
475484

0 commit comments

Comments
 (0)