self.predicates.retain(|predicate| {
// Hack: Retain does not pass in the index, but we want
// to avoid processing the first `start_count` entries.
- if skip == 0 {
- retain_predicate(selcx, predicate,
- &mut selections, &mut errors, region_obligations)
- } else {
- skip -= 1;
- true
- }
+ let processed =
+ if skip == 0 {
+ process_predicate(selcx, predicate,
+ &mut selections, &mut errors, region_obligations)
+ } else {
+ skip -= 1;
+ false
+ };
+ !processed
});
}
}
}
-fn retain_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
- predicate: &PredicateObligation<'tcx>,
- selections: &mut Vec<Selection<'tcx>>,
- errors: &mut Vec<FulfillmentError<'tcx>>,
- region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
- -> bool
+fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+ predicate: &PredicateObligation<'tcx>,
+ selections: &mut Vec<Selection<'tcx>>,
+ errors: &mut Vec<FulfillmentError<'tcx>>,
+ region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
+ -> bool
{
/*!
- * Evaluates a predicate obligation and modifies the appropriate
- * output array. Returns `true` if the predicate must be retained
- * because it could not be fully evaluated yet due to insufficient
+ * Processes a predicate obligation and modifies the appropriate
+ * output array with the successful/error result. Returns `false`
+ * if the predicate could not be processed due to insufficient
* type inference.
*/
trait_ref: trait_ref.clone() };
match selcx.select(&trait_obligation) {
Ok(None) => {
- true
+ false
}
Ok(Some(s)) => {
selections.push(s);
- false
+ true
}
Err(selection_err) => {
debug!("predicate: {} error: {}",
FulfillmentError::new(
predicate.clone(),
CodeSelectionError(selection_err)));
- false
+ true
}
}
}
let origin = infer::EquatePredicate(predicate.cause.span);
match infer::mk_eqty(selcx.infcx(), false, origin, a, b) {
Ok(()) => {
- false
+ true
}
Err(_) => {
errors.push(
FulfillmentError::new(
predicate.clone(),
CodeSelectionError(Unimplemented)));
- false
+ true
}
}
}
ty::Predicate::RegionOutlives(r_a, r_b) => {
let origin = infer::RelateRegionParamBound(predicate.cause.span);
let () = infer::mk_subr(selcx.infcx(), origin, r_b, r_a); // `b : a` ==> `a <= b`
- false
+ true
}
ty::Predicate::TypeOutlives(t_a, r_b) => {
register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
- false
+ true
}
}
}
pub struct ObligationCause<'tcx> {
pub span: Span,
- // the id of XXX
+ // The id of the fn body that triggered this obligation. This is
+ // used for region obligations to determine the precise
+ // environment in which the region obligation should be evaluated
+ // (in particular, closures can add new assumptions). See the
+ // field `region_obligations` of the `FulfillmentContext` for more
+ // information.
pub body_id: ast::NodeId,
pub code: ObligationCauseCode<'tcx>
VtableImpl, VtableParam, VtableParamData, VtableImplData};
///////////////////////////////////////////////////////////////////////////
-// Elaboration iterator
+// `Elaboration` iterator
+///////////////////////////////////////////////////////////////////////////
+/// "Elaboration" is the process of identifying all the predicates that
+/// are implied by a source predicate. Currently this basically means
+/// walking the "supertraits" and other similar assumptions. For
+/// example, if we know that `T : Ord`, the elaborator would deduce
+/// that `T : PartialOrd` holds as well. Similarly, if we have `trait
+/// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
+/// 'static`.
pub struct Elaborator<'cx, 'tcx:'cx> {
tcx: &'cx ty::ctxt<'tcx>,
stack: Vec<StackEntry<'tcx>>,
///////////////////////////////////////////////////////////////////////////
// Supertrait iterator
+///////////////////////////////////////////////////////////////////////////
+/// A filter around the `Elaborator` that just yields up supertrait references,
+/// not other kinds of predicates.
pub struct Supertraits<'cx, 'tcx:'cx> {
elaborator: Elaborator<'cx, 'tcx>,
}
}
}
+///////////////////////////////////////////////////////////////////////////
+// Other
///////////////////////////////////////////////////////////////////////////
// determine the `self` type, using fresh variables for all variables
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub enum Predicate<'tcx> {
- /// where Foo : Bar
+ /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
+ /// the `Self` type of the trait reference and `A`, `B`, and `C`
+ /// would be the parameters in the `TypeSpace`.
Trait(Rc<TraitRef<'tcx>>),
- /// where Foo == Bar
- Equate(Ty<'tcx>, Ty<'tcx>),
+ /// where `T1 == T2`.
+ Equate(/* T1 */ Ty<'tcx>, /* T2 */ Ty<'tcx>),
/// where 'a : 'b
- RegionOutlives(Region, Region),
+ RegionOutlives(/* 'a */ Region, /* 'b */ Region),
/// where T : 'a
TypeOutlives(Ty<'tcx>, Region),
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
- method.span,
method_generics,
method.pe_body().id)
}
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
- method.span,
method_generics,
method.pe_body().id)
}
let fn_pty = ty::lookup_item_type(cx, fn_def_id);
construct_parameter_environment(cx,
- item.span,
&fn_pty.generics,
body.id)
}
ast::ItemStatic(..) => {
let def_id = ast_util::local_def(id);
let pty = ty::lookup_item_type(cx, def_id);
- construct_parameter_environment(cx, item.span,
- &pty.generics, id)
+ construct_parameter_environment(cx, &pty.generics, id)
}
_ => {
cx.sess.span_bug(item.span,
})
}
-/// Given a reference to a trait, returns the bounds declared on the
-/// trait, with appropriate substitutions applied.
+/// Given a reference to a trait, returns the "superbounds" declared
+/// on the trait, with appropriate substitutions applied.
pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
trait_ref: &TraitRef<'tcx>)
-> Vec<ty::Predicate<'tcx>>
/// See `ParameterEnvironment` struct def'n for details
pub fn construct_parameter_environment<'tcx>(
tcx: &ctxt<'tcx>,
- _span: Span,
generics: &ty::Generics<'tcx>,
free_id: ast::NodeId)
-> ParameterEnvironment<'tcx>
let polytype = ty::lookup_item_type(ccx.tcx, item_def_id);
let param_env =
ty::construct_parameter_environment(ccx.tcx,
- item.span,
&polytype.generics,
item.id);
let inh = Inherited::new(ccx.tcx, param_env);