return;
}
- // Depend on trait/impl predicates always being before method's own predicates,
- // to be able to split method predicates into "inherited" and method-specific.
- let trait_predicates = tcx.lookup_predicates(trait_m.container_id()).predicates;
- let impl_predicates = tcx.lookup_predicates(impl_m.container_id()).predicates;
- let trait_method_start = trait_predicates.len();
- let impl_method_start = impl_predicates.len();
- assert_eq!(&trait_predicates[..], &trait_m.predicates.predicates[..trait_method_start]);
- assert_eq!(&impl_predicates[..], &impl_m.predicates.predicates[..impl_method_start]);
-
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| {
let mut fulfillment_cx = traits::FulfillmentContext::new();
- // Normalize the associated types in the trait_bounds.
- let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs);
-
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
// environment. We can't just use `impl_env.caller_bounds`,
// however, because we want to replace all late-bound regions with
// region variables.
- let impl_bounds = impl_m.predicates.instantiate(tcx, impl_to_skol_substs);
+ let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
+ let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
- debug!("compare_impl_method: impl_bounds={:?}", impl_bounds);
+ debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
// This is the only tricky bit of the new way we check implementation methods
// We need to build a set of predicates where only the FnSpace bounds
//
// We then register the obligations from the impl_m and check to see
// if all constraints hold.
- let hybrid_preds = impl_bounds.predicates[..impl_method_start].iter()
- .chain(trait_bounds.predicates[trait_method_start..].iter());
+ hybrid_preds.predicates.extend(
+ trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
- let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.cloned().collect());
+ let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
let trait_param_env = traits::normalize_param_env_or_error(tcx,
trait_param_env,
normalize_cause.clone());
let mut selcx = traits::SelectionContext::new(&infcx);
- let (impl_pred_fns, _) =
+ let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
+ let (impl_m_own_bounds, _) =
infcx.replace_late_bound_regions_with_fresh_var(
impl_m_span,
infer::HigherRankedType,
- &ty::Binder(impl_bounds.predicates[impl_method_start..].to_vec()));
- for predicate in impl_pred_fns {
+ &ty::Binder(impl_m_own_bounds.predicates));
+ for predicate in impl_m_own_bounds {
let traits::Normalized { value: predicate, .. } =
traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
fn get_type_parameter_bounds(&self,
astconv: &AstConv<'tcx, 'tcx>,
- _span: Span,
+ span: Span,
node_id: ast::NodeId)
-> Vec<ty::Predicate<'tcx>>
{
let def = astconv.tcx().type_parameter_def(node_id);
- self.predicates
- .iter()
- .filter(|predicate| {
- match **predicate {
- ty::Predicate::Trait(ref data) => {
- data.skip_binder().self_ty().is_param(def.space, def.index)
- }
- ty::Predicate::TypeOutlives(ref data) => {
- data.skip_binder().0.is_param(def.space, def.index)
- }
- ty::Predicate::Rfc1592(..) |
- ty::Predicate::Equate(..) |
- ty::Predicate::RegionOutlives(..) |
- ty::Predicate::WellFormed(..) |
- ty::Predicate::ObjectSafe(..) |
- ty::Predicate::ClosureKind(..) |
- ty::Predicate::Projection(..) => {
- false
- }
+ let mut results = self.parent.map_or(vec![], |def_id| {
+ let parent = astconv.tcx().lookup_predicates(def_id);
+ parent.get_type_parameter_bounds(astconv, span, node_id)
+ });
+
+ results.extend(self.predicates.iter().filter(|predicate| {
+ match **predicate {
+ ty::Predicate::Trait(ref data) => {
+ data.skip_binder().self_ty().is_param(def.space, def.index)
+ }
+ ty::Predicate::TypeOutlives(ref data) => {
+ data.skip_binder().0.is_param(def.space, def.index)
}
- })
- .cloned()
- .collect()
+ ty::Predicate::Rfc1592(..) |
+ ty::Predicate::Equate(..) |
+ ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
+ ty::Predicate::ClosureKind(..) |
+ ty::Predicate::Projection(..) => {
+ false
+ }
+ }
+ }).cloned());
+
+ results
}
}
let ty_generics = generics_of_def_id(ccx, def_id);
let ty_generic_predicates =
- ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
+ ty_generic_predicates(ccx, FnSpace, &sig.generics, ty_generics.parent, vec![], false);
let (fty, explicit_self_category) = {
let anon_scope = match container {
ty: ty::Ty<'tcx>,
has_value: bool)
{
+ let predicates = ty::GenericPredicates {
+ parent: Some(container.id()),
+ predicates: vec![]
+ };
ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
- ty::GenericPredicates::empty());
+ predicates);
write_ty_to_tcx(ccx, id, ty);
debug!("convert: ast_generics={:?}", generics);
let def_id = ccx.tcx.map.local_def_id(it.id);
let ty_generics = generics_of_def_id(ccx, def_id);
- let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
+ let mut ty_predicates =
+ ty_generic_predicates(ccx, TypeSpace, generics, None, vec![], false);
debug!("convert: impl_bounds={:?}", ty_predicates);
// generic types:
let trait_def = trait_def_of_item(ccx, item);
let self_predicate = ty::GenericPredicates {
+ parent: None,
predicates: vec![trait_def.trait_ref.to_predicate()]
};
let scope = &(generics, &self_predicate);
// Combine the two lists to form the complete set of superbounds:
let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
let superpredicates = ty::GenericPredicates {
+ parent: None,
predicates: superbounds
};
debug!("superpredicates for trait {:?} = {:?}",
// but to get the full set of predicates on a trait we need to add
// in the supertrait bounds and anything declared on the
// associated types.
- let mut base_predicates = super_predicates;
+ let mut base_predicates = super_predicates.predicates;
// Add in a predicate that `Self:Trait` (where `Trait` is the
// current trait). This is needed for builtin bounds.
let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
- base_predicates.predicates.push(self_predicate);
+ base_predicates.push(self_predicate);
// add in the explicit where-clauses
let mut trait_predicates =
- ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true);
+ ty_generic_predicates(ccx, TypeSpace, generics, None, base_predicates, true);
let assoc_predicates = predicates_for_associated_types(ccx,
generics,
it: &hir::Item)
-> ty::GenericPredicates<'tcx> {
let def_id = ccx.tcx.map.local_def_id(it.id);
- let predicates = match it.node {
- hir::ItemStatic(..) | hir::ItemConst(..) => {
- ty::GenericPredicates::empty()
- }
- hir::ItemFn(_, _, _, _, ref ast_generics, _) => {
- ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
- }
+
+ let no_generics = hir::Generics::empty();
+ let (space, generics) = match it.node {
+ hir::ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics),
hir::ItemTy(_, ref generics) |
hir::ItemEnum(_, ref generics) |
- hir::ItemStruct(_, ref generics) => {
- ty_generic_predicates_for_type_or_impl(ccx, generics)
- }
- hir::ItemDefaultImpl(..) |
- hir::ItemTrait(..) |
- hir::ItemExternCrate(..) |
- hir::ItemUse(..) |
- hir::ItemImpl(..) |
- hir::ItemMod(..) |
- hir::ItemForeignMod(..) => {
- span_bug!(
- it.span,
- "predicates_of_item: unexpected item type: {:?}",
- it.node);
- }
+ hir::ItemStruct(_, ref generics) => (TypeSpace, generics),
+ _ => (TypeSpace, &no_generics)
};
+ let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false);
let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id,
predicates.clone());
assert!(prev_predicates.is_none());
let def_id = ccx.tcx.map.local_def_id(it.id);
type_scheme_of_def_id(ccx, def_id);
- let predicates = match it.node {
- hir::ForeignItemFn(_, ref generics) => {
- ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
- }
- hir::ForeignItemStatic(..) => {
- ty::GenericPredicates::empty()
- }
+ let no_generics = hir::Generics::empty();
+ let (space, generics) = match it.node {
+ hir::ForeignItemFn(_, ref generics) => (FnSpace, generics),
+ hir::ForeignItemStatic(..) => (TypeSpace, &no_generics)
};
+ let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false);
let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
assert!(prev_predicates.is_none());
}
-fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- generics: &hir::Generics)
- -> ty::GenericPredicates<'tcx>
-{
- ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false)
-}
-
-fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- generics: &hir::Generics,
- base_predicates: &ty::GenericPredicates<'tcx>)
- -> ty::GenericPredicates<'tcx>
-{
- ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false)
-}
-
// Add the Sized bound, unless the type parameter is marked as `?Sized`.
fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
bounds: &mut ty::BuiltinBounds,
fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
space: ParamSpace,
ast_generics: &hir::Generics,
- base_predicates: &ty::GenericPredicates<'tcx>,
+ parent: Option<DefId>,
+ super_predicates: Vec<ty::Predicate<'tcx>>,
has_self: bool)
-> ty::GenericPredicates<'tcx>
{
let tcx = ccx.tcx;
- let mut result = base_predicates.clone();
+ let ref base_predicates = match parent {
+ Some(def_id) => {
+ assert_eq!(super_predicates, vec![]);
+ tcx.lookup_predicates(def_id)
+ }
+ None => {
+ ty::GenericPredicates {
+ parent: None,
+ predicates: super_predicates.clone()
+ }
+ }
+ };
+ let mut predicates = super_predicates;
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
SizedByDefault::Yes,
None,
param.span);
- result.predicates.extend(bounds.predicates(ccx.tcx, param_ty));
+ predicates.extend(bounds.predicates(ccx.tcx, param_ty));
}
// Collect the region predicates that were declared inline as
for bound in ¶m.bounds {
let bound_region = ast_region_to_region(ccx.tcx, bound);
let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
- result.predicates.push(outlives.to_predicate());
+ predicates.push(outlives.to_predicate());
}
}
ty,
&mut projections);
- result.predicates.push(trait_ref.to_predicate());
+ predicates.push(trait_ref.to_predicate());
for projection in &projections {
- result.predicates.push(projection.to_predicate());
+ predicates.push(projection.to_predicate());
}
}
&hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
let region = ast_region_to_region(tcx, lifetime);
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
- result.predicates.push(ty::Predicate::TypeOutlives(pred))
+ predicates.push(ty::Predicate::TypeOutlives(pred))
}
}
}
for bound in ®ion_pred.bounds {
let r2 = ast_region_to_region(tcx, bound);
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
- result.predicates.push(ty::Predicate::RegionOutlives(pred))
+ predicates.push(ty::Predicate::RegionOutlives(pred))
}
}
}
}
- result
+ ty::GenericPredicates {
+ parent: parent,
+ predicates: predicates
+ }
}
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,