From 15ef2c2e6b94e8430d718a13c9845e33989a50d6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis <niko@alum.mit.edu> Date: Tue, 17 Feb 2015 11:04:25 -0500 Subject: [PATCH] Convert `astconv` to request bounds through the `AstConv` interface rather than poking through the `TypeParameterDef` directly. --- src/librustc/middle/ty.rs | 9 ++++++++- src/librustc_typeck/astconv.rs | 8 ++++++-- src/librustc_typeck/check/mod.rs | 26 +++++++++++++++++++++++++- src/librustc_typeck/collect.rs | 19 ++++++++++++++++--- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 91313633397..275007bf797 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -55,7 +55,7 @@ use middle::region; use middle::resolve_lifetime; use middle::infer; use middle::stability; -use middle::subst::{self, Subst, Substs, VecPerParamSpace}; +use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace}; use middle::traits; use middle::ty; use middle::ty_fold::{self, TypeFoldable, TypeFolder}; @@ -2996,6 +2996,13 @@ impl<'tcx> TyS<'tcx> { _ => None, } } + + pub fn is_param(&self, space: ParamSpace, index: u32) -> bool { + match self.sty { + ty::ty_param(ref data) => data.space == space && data.idx == index, + _ => false, + } + } } pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9e50fdb4c48..d0e194e15d2 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -53,7 +53,7 @@ use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; use middle::privacy::{AllPublic, LastMod}; -use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; +use middle::subst::{FnSpace, ParamSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::traits; use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, @@ -77,6 +77,8 @@ pub trait AstConv<'tcx> { fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>; + fn get_type_parameter_bounds(&self, space: ParamSpace, index: u32) -> Vec<ty::PolyTraitRef<'tcx>>; + /// Return an (optional) substitution to convert bound type parameters that /// are in scope into free ones. This function should only return Some /// within a fn body. @@ -1011,7 +1013,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, // FIXME(#20300) -- search where clauses, not bounds suitable_bounds = - traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds) + traits::transitive_bounds(tcx, + &this.get_type_parameter_bounds(ty_param_def.space, + ty_param_def.index)) .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name)) .collect(); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d7a11b8a515..968d67aca9d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -97,7 +97,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace use middle::traits; use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; -use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty}; +use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::liberate_late_bound_regions; use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; use middle::ty_fold::{TypeFolder, TypeFoldable}; @@ -1218,6 +1218,30 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { Some(&self.inh.param_env.free_substs) } + fn get_type_parameter_bounds(&self, + space: ParamSpace, + index: u32) + -> Vec<ty::PolyTraitRef<'tcx>> + { + self.inh.param_env.caller_bounds + .iter() + .filter_map(|predicate| { + match *predicate { + ty::Predicate::Trait(ref data) => { + if data.0.self_ty().is_param(space, index) { + Some(data.to_poly_trait_ref()) + } else { + None + } + } + _ => { + None + } + } + }) + .collect() + } + fn ty_infer(&self, _span: Span) -> Ty<'tcx> { self.infcx().next_ty_var() } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3ca12959246..6d65d05bf6f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -145,7 +145,6 @@ struct CrateCtxt<'a,'tcx:'a> { tcx: &'a ty::ctxt<'tcx>, } -#[allow(dead_code)] // just temporary, for generics struct ItemCtxt<'a,'tcx:'a> { ccx: &'a CrateCtxt<'a,'tcx>, generics: &'a ty::Generics<'tcx>, @@ -241,6 +240,19 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> { get_trait_def(self.ccx, id) } + fn get_type_parameter_bounds(&self, + param: subst::ParamSpace, + index: u32) + -> Vec<ty::PolyTraitRef<'tcx>> + { + // TODO out of range indices can occur when you have something + // like fn foo<T:U::X,U>() { } + match self.generics.types.opt_get(param, index as usize) { + Some(def) => def.bounds.trait_bounds.clone(), + None => Vec::new(), + } + } + fn ty_infer(&self, span: Span) -> Ty<'tcx> { span_err!(self.tcx().sess, span, E0121, "the type placeholder `_` is not allowed within types on item signatures"); @@ -1596,7 +1608,7 @@ fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // Now create the real type parameters. for (i, param) in types.iter().enumerate() { - let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause); + let def = get_or_create_type_parameter_def(ccx, &result, space, param, i as u32); debug!("ty_generics: def for type param: {:?}, {:?}", def, space); result.types.push(space, def); } @@ -1605,6 +1617,7 @@ fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + generics_so_far: &ty::Generics<'tcx>, space: subst::ParamSpace, param: &ast::TyParam, index: u32, @@ -1619,7 +1632,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let param_ty = ty::ParamTy::new(space, index, param.ident.name); let bounds = compute_bounds(ccx, - &ty::Generics::empty(), + generics_so_far, param_ty.to_ty(ccx.tcx), ¶m.bounds, SizedByDefault::Yes,