diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e94991f6569..af80ce65474f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -192,7 +192,8 @@ impl ImplOrTraitItemId { #[derive(Clone, Debug)] pub struct Method<'tcx> { pub name: ast::Name, - pub generics: ty::Generics<'tcx>, + pub generics: Generics<'tcx>, + pub predicates: GenericPredicates<'tcx>, pub fty: BareFnTy<'tcx>, pub explicit_self: ExplicitSelfCategory, pub vis: ast::Visibility, @@ -206,6 +207,7 @@ pub struct Method<'tcx> { impl<'tcx> Method<'tcx> { pub fn new(name: ast::Name, generics: ty::Generics<'tcx>, + predicates: GenericPredicates<'tcx>, fty: BareFnTy<'tcx>, explicit_self: ExplicitSelfCategory, vis: ast::Visibility, @@ -216,6 +218,7 @@ impl<'tcx> Method<'tcx> { Method { name: name, generics: generics, + predicates: predicates, fty: fty, explicit_self: explicit_self, vis: vis, @@ -710,6 +713,10 @@ pub struct ctxt<'tcx> { pub trait_refs: RefCell>>>, pub trait_defs: RefCell>>>, + /// Maps from the def-id of an item (trait/struct/enum/fn) to its + /// associated predicates. + pub predicates: RefCell>>, + /// Maps from node-id of a trait object cast (like `foo as /// Box`) to the trait reference. pub object_cast_map: ObjectCastMap<'tcx>, @@ -1782,7 +1789,6 @@ impl RegionParameterDef { pub struct Generics<'tcx> { pub types: VecPerParamSpace>, pub regions: VecPerParamSpace, - pub predicates: VecPerParamSpace>, } impl<'tcx> Generics<'tcx> { @@ -1790,10 +1796,13 @@ impl<'tcx> Generics<'tcx> { Generics { types: VecPerParamSpace::empty(), regions: VecPerParamSpace::empty(), - predicates: VecPerParamSpace::empty(), } } + pub fn is_empty(&self) -> bool { + self.types.is_empty() && self.regions.is_empty() + } + pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { !self.types.is_empty_in(space) } @@ -1801,14 +1810,24 @@ impl<'tcx> Generics<'tcx> { pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { !self.regions.is_empty_in(space) } +} - pub fn is_empty(&self) -> bool { - self.types.is_empty() && self.regions.is_empty() +/// Bounds on generics. +#[derive(Clone, Debug)] +pub struct GenericPredicates<'tcx> { + pub predicates: VecPerParamSpace>, +} + +impl<'tcx> GenericPredicates<'tcx> { + pub fn empty() -> GenericPredicates<'tcx> { + GenericPredicates { + predicates: VecPerParamSpace::empty(), + } } - pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) - -> GenericBounds<'tcx> { - GenericBounds { + pub fn instantiate(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) + -> InstantiatedPredicates<'tcx> { + InstantiatedPredicates { predicates: self.predicates.subst(tcx, substs), } } @@ -2022,11 +2041,11 @@ impl<'tcx> Predicate<'tcx> { /// Represents the bounds declared on a particular set of type /// parameters. Should eventually be generalized into a flag list of -/// where clauses. You can obtain a `GenericBounds` list from a -/// `Generics` by using the `to_bounds` method. Note that this method -/// reflects an important semantic invariant of `GenericBounds`: while -/// the bounds in a `Generics` are expressed in terms of the bound type -/// parameters of the impl/trait/whatever, a `GenericBounds` instance +/// where clauses. You can obtain a `InstantiatedPredicates` list from a +/// `GenericPredicates` by using the `instantiate` method. Note that this method +/// reflects an important semantic invariant of `InstantiatedPredicates`: while +/// the `GenericPredicates` are expressed in terms of the bound type +/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance /// represented a set of bounds for some particular instantiation, /// meaning that the generic parameters have been substituted with /// their values. @@ -2035,18 +2054,18 @@ impl<'tcx> Predicate<'tcx> { /// /// struct Foo> { ... } /// -/// Here, the `Generics` for `Foo` would contain a list of bounds like +/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like /// `[[], [U:Bar]]`. Now if there were some particular reference -/// like `Foo`, then the `GenericBounds` would be `[[], +/// like `Foo`, then the `InstantiatedPredicates` would be `[[], /// [uint:Bar]]`. #[derive(Clone, Debug)] -pub struct GenericBounds<'tcx> { +pub struct InstantiatedPredicates<'tcx> { pub predicates: VecPerParamSpace>, } -impl<'tcx> GenericBounds<'tcx> { - pub fn empty() -> GenericBounds<'tcx> { - GenericBounds { predicates: VecPerParamSpace::empty() } +impl<'tcx> InstantiatedPredicates<'tcx> { + pub fn empty() -> InstantiatedPredicates<'tcx> { + InstantiatedPredicates { predicates: VecPerParamSpace::empty() } } pub fn has_escaping_regions(&self) -> bool { @@ -2248,10 +2267,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { /// stray references in a comment or something). We try to reserve the /// "poly" prefix to refer to higher-ranked things, as in /// `PolyTraitRef`. +/// +/// Note that each item also comes with predicates, see +/// `lookup_predicates`. #[derive(Clone, Debug)] pub struct TypeScheme<'tcx> { pub generics: Generics<'tcx>, - pub ty: Ty<'tcx> + pub ty: Ty<'tcx>, } /// As `TypeScheme` but for a trait ref. @@ -2393,6 +2415,7 @@ pub fn mk_ctxt<'tcx>(s: Session, item_substs: RefCell::new(NodeMap()), trait_refs: RefCell::new(NodeMap()), trait_defs: RefCell::new(DefIdMap()), + predicates: RefCell::new(DefIdMap()), object_cast_map: RefCell::new(NodeMap()), map: map, intrinsic_defs: RefCell::new(DefIdMap()), @@ -5378,13 +5401,23 @@ pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>, /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) - -> Rc> { + -> Rc> { memoized(&cx.trait_defs, did, |did: DefId| { assert!(did.krate != ast::LOCAL_CRATE); Rc::new(csearch::get_trait_def(cx, did)) }) } +/// Given the did of a trait, returns its full set of predicates. +pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) + -> GenericPredicates<'tcx> +{ + memoized(&cx.predicates, did, |did: DefId| { + assert!(did.krate != ast::LOCAL_CRATE); + csearch::get_predicates(cx, did) + }) +} + /// Given a reference to a trait, returns the "superbounds" declared /// on the trait, with appropriate substitutions applied. Basically, /// this applies a filter to the where clauses on the trait, returning