rustc: split GenericPredicates of a method from its parent predicates.

This commit is contained in:
Eduard Burtescu 2016-08-11 09:19:42 +03:00
parent 3e74e5bffe
commit 6f5e455c2d
14 changed files with 136 additions and 150 deletions

View File

@ -2897,20 +2897,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in
// that order.
let predicates = tcx
.lookup_predicates(def_id)
.predicates.iter()
.flat_map(|predicate| {
let predicate =
normalize_with_depth(self, cause.clone(), recursion_depth,
&predicate.subst(tcx, substs));
predicate.obligations.into_iter().chain(
Some(Obligation {
cause: cause.clone(),
recursion_depth: recursion_depth,
predicate: predicate.value
}))
}).collect();
let predicates = tcx.lookup_predicates(def_id);
assert_eq!(predicates.parent, None);
let predicates = predicates.predicates.iter().flat_map(|predicate| {
let predicate = normalize_with_depth(self, cause.clone(), recursion_depth,
&predicate.subst(tcx, substs));
predicate.obligations.into_iter().chain(
Some(Obligation {
cause: cause.clone(),
recursion_depth: recursion_depth,
predicate: predicate.value
}))
}).collect();
self.infcx().plug_leaks(skol_map, snapshot, &predicates)
}
}

View File

@ -768,27 +768,38 @@ pub struct Generics<'tcx> {
/// Bounds on generics.
#[derive(Clone)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
pub predicates: Vec<Predicate<'tcx>>,
}
impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
pub fn empty() -> GenericPredicates<'tcx> {
GenericPredicates {
predicates: vec![]
pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
let mut instantiated = InstantiatedPredicates::empty();
self.instantiate_into(tcx, &mut instantiated, substs);
instantiated
}
pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
predicates: self.predicates.subst(tcx, substs)
}
}
pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
predicates: self.predicates.subst(tcx, substs),
fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
instantiated: &mut InstantiatedPredicates<'tcx>,
substs: &Substs<'tcx>) {
if let Some(def_id) = self.parent {
tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs);
}
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
}
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
-> InstantiatedPredicates<'tcx>
{
assert_eq!(self.parent, None);
InstantiatedPredicates {
predicates: self.predicates.iter().map(|pred| {
pred.subst_supertrait(tcx, poly_trait_ref)

View File

@ -832,18 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::GenericPredicates {
predicates: self.predicates.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.predicates.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {

View File

@ -1591,6 +1591,7 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
let doc = reader::get_doc(base_doc, tag);
ty::GenericPredicates {
parent: item_parent_item(cdata, doc),
predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| {
doc_predicate(cdata, predicate_doc, tcx)
}).collect()

View File

@ -525,6 +525,9 @@ fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
tag: usize)
{
rbml_w.start_tag(tag);
if let Some(def_id) = predicates.parent {
rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id));
}
for predicate in &predicates.predicates {
rbml_w.wr_tagged_u32(tag_predicate,
index.add_xref(XRef::Predicate(predicate.clone())));

View File

@ -1726,6 +1726,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let predicates = bounds.predicates(tcx, ty);
let predicates = tcx.lift_to_global(&predicates).unwrap();
tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates {
parent: None,
predicates: predicates
});

View File

@ -211,29 +211,18 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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
@ -242,14 +231,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
//
// 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());
@ -261,12 +250,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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);

View File

@ -184,6 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
// 'a:'b and T:'b into region inference constraints. It is simpler
// just to look for all the predicates directly.
assert_eq!(dtor_predicates.parent, None);
for predicate in &dtor_predicates.predicates {
// (We do not need to worry about deep analysis of type
// expressions etc because the Drop impls are already forced

View File

@ -1612,8 +1612,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
bounds: &ty::GenericPredicates<'tcx>)
-> ty::InstantiatedPredicates<'tcx>
{
let result = bounds.instantiate(self.tcx, substs);
let result = self.normalize_associated_types_in(span, &result.predicates);
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
bounds,
substs,
result);
ty::InstantiatedPredicates {
predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
predicates: result
}
}
@ -4210,8 +4216,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
_ => {}
}
let scheme = self.tcx.lookup_item_type(def.def_id());
let type_predicates = self.tcx.lookup_predicates(def.def_id());
// Now we have to compare the types that the user *actually*
// provided against the types that were *expected*. If the user
@ -4296,6 +4300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let scheme = self.tcx.lookup_item_type(def.def_id());
let type_predicates = self.tcx.lookup_predicates(def.def_id());
assert!(!substs.has_escaping_regions());
assert!(!scheme.ty.has_escaping_regions());

View File

@ -1754,6 +1754,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
//
// we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id);
assert_eq!(trait_predicates.parent, None);
let predicates = trait_predicates.predicates.as_slice().to_vec();
traits::elaborate_predicates(self.tcx, predicates)
.filter_map(|predicate| {

View File

@ -454,6 +454,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
let item_def_id = self.tcx().map.local_def_id(item.id);
let ty_predicates = self.tcx().lookup_predicates(item_def_id);
assert_eq!(ty_predicates.parent, None);
let variances = self.tcx().item_variances(item_def_id);
let mut constrained_parameters: HashSet<_> =

View File

@ -459,35 +459,38 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () {
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)
}
})
.cloned()
.collect()
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
}
}
}).cloned());
results
}
}
@ -568,7 +571,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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 {
@ -634,8 +637,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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);
@ -744,7 +751,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
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);
@ -1187,6 +1195,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
// 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);
@ -1209,6 +1218,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
// 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 {:?} = {:?}",
@ -1327,16 +1337,16 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
// 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,
@ -1619,32 +1629,17 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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());
@ -1662,34 +1657,17 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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,
@ -1757,12 +1735,25 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>(
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>`).
@ -1775,7 +1766,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
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
@ -1793,7 +1784,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
for bound in &param.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());
}
}
@ -1819,17 +1810,17 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
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))
}
}
}
@ -1840,7 +1831,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
for bound in &region_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))
}
}
@ -1853,7 +1844,10 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
}
result
ty::GenericPredicates {
parent: parent,
predicates: predicates
}
}
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,

View File

@ -1348,17 +1348,7 @@ impl Clean<Item> for hir::ImplItem {
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
fn clean(&self, cx: &DocContext) -> Item {
// 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 outer_predicates = cx.tcx().lookup_predicates(self.container_id()).predicates;
let method_start = outer_predicates.len();
assert_eq!(&outer_predicates[..], &self.predicates.predicates[..method_start]);
let method_predicates = ty::GenericPredicates {
predicates: self.predicates.predicates[method_start..].to_vec()
};
let generics = (self.generics, &method_predicates).clean(cx);
let generics = (self.generics, &self.predicates).clean(cx);
let mut decl = (self.def_id, &self.fty.sig).clean(cx);
match self.explicit_self {
ty::ExplicitSelfCategory::ByValue => {

View File

@ -25,7 +25,8 @@ impl Foo for Def {
}
pub fn test<A: Foo, B: Foo>() {
let _array: [u32; <A as Foo>::Y]; //~ error: the parameter type
let _array: [u32; <A as Foo>::Y];
//~^ ERROR the trait bound `A: Foo` is not satisfied
}
fn main() {