Skip to content

Commit

Permalink
Rework the get_type_parameter_bounds impl to use a trait object
Browse files Browse the repository at this point in the history
and act more generically.
  • Loading branch information
nikomatsakis committed Feb 24, 2015
1 parent 0d9e473 commit 3c782b7
Showing 1 changed file with 79 additions and 31 deletions.
110 changes: 79 additions & 31 deletions src/librustc_typeck/collect.rs
Expand Up @@ -150,9 +150,16 @@ struct CrateCtxt<'a,'tcx:'a> {
stack: RefCell<Vec<AstConvRequest>>,
}

/// Context specific to some particular item. This is what implements
/// AstConv. It has information about the predicates that are defined
/// on the trait. Unfortunately, this predicate information is
/// available in various different forms at various points in the
/// process. So we can't just store a pointer to e.g. the AST or the
/// parsed ty form, we have to wind up keeping both (and making both
/// optional) and extracting what we need from what's available.
struct ItemCtxt<'a,'tcx:'a> {
ccx: &'a CrateCtxt<'a,'tcx>,
generics: &'a ty::Generics<'tcx>,
param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
}

#[derive(Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -216,8 +223,8 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
// Utility types and common code for the above passes.

impl<'a,'tcx> CrateCtxt<'a,'tcx> {
fn icx(&'a self, generics: &'a ty::Generics<'tcx>) -> ItemCtxt<'a,'tcx> {
ItemCtxt { ccx: self, generics: generics }
fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
ItemCtxt { ccx: self, param_bounds: param_bounds }
}

fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
Expand Down Expand Up @@ -319,11 +326,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
}
}

pub trait ToTy<'tcx> {
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
}

impl<'a,'tcx> ToTy<'tcx> for ItemCtxt<'a,'tcx> {
impl<'a,'tcx> ItemCtxt<'a,'tcx> {
fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
ast_ty_to_ty(self, rs, ast_ty)
}
Expand Down Expand Up @@ -354,14 +357,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
{
self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
let def = self.tcx().type_parameter_def(node_id);

// TODO out of range indices can occur when you have something
// like fn foo<T:U::X,U>() { }
match self.generics.types.opt_get(def.space, def.index as usize) {
Some(def) => def.bounds.trait_bounds.clone(),
None => Vec::new(),
}
self.param_bounds.get_type_parameter_bounds(self, span, node_id)
})
}

Expand All @@ -381,6 +377,32 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
}
}


trait GetTypeParameterBounds<'tcx> {
fn get_type_parameter_bounds(&self,
astconv: &AstConv<'tcx>,
span: Span,
node_id: ast::NodeId)
-> Vec<ty::PolyTraitRef<'tcx>>;
}
impl<'tcx> GetTypeParameterBounds<'tcx> for ty::Generics<'tcx> {
fn get_type_parameter_bounds(&self,
astconv: &AstConv<'tcx>,
_span: Span,
node_id: ast::NodeId)
-> Vec<ty::PolyTraitRef<'tcx>>
{
let def = astconv.tcx().type_parameter_def(node_id);

// TODO out of range indices can occur when you have something
// like fn foo<T:U::X,U>() { }
match self.types.opt_get(def.space, def.index as usize) {
Some(def) => def.bounds.trait_bounds.clone(),
None => Vec::new(),
}
}
}

fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
enum_scheme: ty::TypeScheme<'tcx>,
enum_predicates: ty::GenericPredicates<'tcx>,
Expand Down Expand Up @@ -1646,13 +1668,10 @@ fn ty_generic_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
let mut projections = Vec::new();

let trait_ref = astconv::instantiate_poly_trait_ref(
&ccx.icx(generics),
&ExplicitRscope,
poly_trait_ref,
Some(ty),
&mut projections,
);
let trait_ref = conv_poly_trait_ref(&ccx.icx(generics),
ty,
poly_trait_ref,
&mut projections);

result.predicates.push(space, trait_ref.as_predicate());

Expand Down Expand Up @@ -1934,6 +1953,38 @@ fn check_bounds_compatible<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
}

/// Converts a specific TyParamBound from the AST into the
/// appropriate poly-trait-reference.
fn poly_trait_ref_from_bound<'tcx>(astconv: &AstConv<'tcx>,
param_ty: Ty<'tcx>,
bound: &ast::TyParamBound,
projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> Option<ty::PolyTraitRef<'tcx>>
{
match *bound {
ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
Some(conv_poly_trait_ref(astconv, param_ty, tr, projections))
}
ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) |
ast::RegionTyParamBound(_) => {
None
}
}
}

fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
param_ty: Ty<'tcx>,
trait_ref: &ast::PolyTraitRef,
projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
astconv::instantiate_poly_trait_ref(astconv,
&ExplicitRscope,
trait_ref,
Some(param_ty),
projections)
}

fn conv_param_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
generics: &ty::Generics<'tcx>,
span: Span,
Expand All @@ -1952,14 +2003,11 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,

let trait_bounds: Vec<ty::PolyTraitRef> =
trait_bounds.into_iter()
.map(|bound| {
astconv::instantiate_poly_trait_ref(&ccx.icx(generics),
&ExplicitRscope,
bound,
Some(param_ty),
&mut projection_bounds)
})
.collect();
.map(|bound| conv_poly_trait_ref(&ccx.icx(generics),
param_ty,
bound,
&mut projection_bounds))
.collect();

let region_bounds: Vec<ty::Region> =
region_bounds.into_iter()
Expand Down

0 comments on commit 3c782b7

Please sign in to comment.