Extract out trait_defines_associated_type_named into the AstConv
interface, so that we can perform this query without requiring a full trait def or set of supertraits.
This commit is contained in:
parent
ab8a769c57
commit
4ee002a17c
@ -82,6 +82,9 @@ pub trait AstConv<'tcx> {
|
||||
fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
|
||||
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
|
||||
|
||||
fn trait_defines_associated_type_named(&self, trait_def_id: ast::DefId, name: ast::Name)
|
||||
-> bool;
|
||||
|
||||
/// 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.
|
||||
@ -783,7 +786,7 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
|
||||
// We want to produce `<B as SuperTrait<int>>::T == foo`.
|
||||
|
||||
// Simple case: X is defined in the current trait.
|
||||
if trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
|
||||
if this.trait_defines_associated_type_named(trait_ref.def_id, binding.item_name) {
|
||||
return Ok(ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
trait_ref: trait_ref,
|
||||
@ -812,7 +815,7 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
|
||||
|
||||
let mut candidates: Vec<ty::PolyTraitRef> =
|
||||
traits::supertraits(tcx, trait_ref.to_poly_trait_ref())
|
||||
.filter(|r| trait_defines_associated_type_named(this, r.def_id(), binding.item_name))
|
||||
.filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name))
|
||||
.collect();
|
||||
|
||||
// If converting for an object type, then remove the dummy-ty from `Self` now.
|
||||
@ -1036,7 +1039,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
|
||||
let mut suitable_bounds: Vec<_> =
|
||||
traits::transitive_bounds(tcx, &bounds)
|
||||
.filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
|
||||
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
|
||||
.collect();
|
||||
|
||||
if suitable_bounds.len() == 0 {
|
||||
@ -1090,16 +1093,6 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
(ty, def::DefAssociatedTy(trait_did, item_did))
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(this: &AstConv,
|
||||
trait_def_id: ast::DefId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
|
||||
trait_def.associated_type_names.contains(&assoc_name)
|
||||
}
|
||||
|
||||
fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
|
@ -1248,6 +1248,15 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(&self,
|
||||
trait_def_id: ast::DefId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
|
||||
trait_def.associated_type_names.contains(&assoc_name)
|
||||
}
|
||||
|
||||
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
|
||||
self.infcx().next_ty_var()
|
||||
}
|
||||
|
@ -364,6 +364,19 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(&self,
|
||||
trait_def_id: ast::DefId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
if trait_def_id.krate == ast::LOCAL_CRATE {
|
||||
trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
|
||||
} else {
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
|
||||
trait_def.associated_type_names.contains(&assoc_name)
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
@ -1296,6 +1309,30 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(ccx: &CrateCtxt,
|
||||
trait_node_id: ast::NodeId,
|
||||
assoc_name: ast::Name)
|
||||
-> bool
|
||||
{
|
||||
let item = match ccx.tcx.map.get(trait_node_id) {
|
||||
ast_map::NodeItem(item) => item,
|
||||
_ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
|
||||
};
|
||||
|
||||
let trait_items = match item.node {
|
||||
ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
|
||||
_ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
|
||||
};
|
||||
|
||||
trait_items.iter()
|
||||
.any(|trait_item| {
|
||||
match *trait_item {
|
||||
ast::TypeTraitItem(ref t) => t.ty_param.ident.name == assoc_name,
|
||||
ast::RequiredMethod(..) | ast::ProvidedMethod(..) => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
|
||||
let tcx = ccx.tcx;
|
||||
let trait_def = trait_def_of_item(ccx, it);
|
||||
|
Loading…
x
Reference in New Issue
Block a user