Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactor QPath to take an ast::TraitRef
  • Loading branch information
nikomatsakis committed Nov 19, 2014
1 parent cf7df1e commit b64c7b8
Show file tree
Hide file tree
Showing 16 changed files with 122 additions and 190 deletions.
63 changes: 4 additions & 59 deletions src/librustc/middle/resolve.rs
Expand Up @@ -633,6 +633,7 @@ enum TraitReferenceType {
TraitDerivation, // trait T : SomeTrait { ... }
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
TraitObject, // Box<for<'a> SomeTrait>
TraitQPath, // <T as SomeTrait>::
}

impl NameBindings {
Expand Down Expand Up @@ -4532,6 +4533,7 @@ impl<'a> Resolver<'a> {
TraitImplementation => "implement",
TraitDerivation => "derive",
TraitObject => "reference",
TraitQPath => "extract an associated type from",
};

let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
Expand Down Expand Up @@ -4969,65 +4971,8 @@ impl<'a> Resolver<'a> {
}

TyQPath(ref qpath) => {
self.resolve_type(&*qpath.for_type);

let current_module = self.current_module.clone();
let module_path: Vec<_> =
qpath.trait_name
.segments
.iter()
.map(|ps| ps.identifier.name)
.collect();
match self.resolve_module_path(
current_module,
module_path.as_slice(),
UseLexicalScope,
qpath.trait_name.span,
PathSearch) {
Success((ref module, _)) if module.kind.get() ==
TraitModuleKind => {
match self.resolve_definition_of_name_in_module(
(*module).clone(),
qpath.item_name.name,
TypeNS) {
ChildNameDefinition(def, lp) |
ImportNameDefinition(def, lp) => {
match def {
DefAssociatedTy(trait_type_id) => {
let def = DefAssociatedTy(
trait_type_id);
self.record_def(ty.id, (def, lp));
}
_ => {
self.resolve_error(
ty.span,
"not an associated type");
}
}
}
NoNameDefinition => {
self.resolve_error(ty.span,
"unresolved associated \
type");
}
}
}
Success(..) => self.resolve_error(ty.span, "not a trait"),
Indeterminate => {
self.session.span_bug(ty.span,
"indeterminate result when \
resolving associated type")
}
Failed(error) => {
let (span, help) = match error {
Some((span, msg)) => (span, format!("; {}", msg)),
None => (ty.span, String::new()),
};
self.resolve_error(span,
format!("unresolved trait: {}",
help).as_slice())
}
}
self.resolve_type(&*qpath.self_type);
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
}

TyClosure(ref c) | TyProc(ref c) => {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/middle/subst.rs
Expand Up @@ -100,6 +100,10 @@ impl<'tcx> Substs<'tcx> {
regions_is_noop && self.types.is_empty()
}

pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
*self.types.get(ty_param_def.space, ty_param_def.index)
}

pub fn has_regions_escaping_depth(&self, depth: uint) -> bool {
self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
match self.regions {
Expand Down
5 changes: 1 addition & 4 deletions src/librustc/middle/traits/mod.rs
Expand Up @@ -25,6 +25,7 @@ use std::rc::Rc;
use std::slice::Items;
use syntax::ast;
use syntax::codemap::{Span, DUMMY_SP};
use util::common::ErrorReported;

pub use self::fulfill::FulfillmentContext;
pub use self::select::SelectionContext;
Expand Down Expand Up @@ -95,10 +96,6 @@ pub enum ObligationCauseCode<'tcx> {
FieldSized,
}

// An error has already been reported to the user, so no need to continue checking.
#[deriving(Clone,Show)]
pub struct ErrorReported;

pub type Obligations<'tcx> = subst::VecPerParamSpace<Obligation<'tcx>>;

pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/select.rs
Expand Up @@ -17,7 +17,6 @@ use self::Candidate::*;
use self::BuiltinBoundConditions::*;
use self::EvaluationResult::*;

use super::{ErrorReported};
use super::{Obligation, ObligationCause};
use super::{SelectionError, Unimplemented, Overflow,
OutputTypeParameterMismatch};
Expand All @@ -38,6 +37,7 @@ use std::cell::RefCell;
use std::collections::hash_map::HashMap;
use std::rc::Rc;
use syntax::ast;
use util::common::ErrorReported;
use util::ppaux::Repr;

pub struct SelectionContext<'cx, 'tcx:'cx> {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/traits/util.rs
Expand Up @@ -18,9 +18,10 @@ use std::fmt;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::Span;
use util::common::ErrorReported;
use util::ppaux::Repr;

use super::{ErrorReported, Obligation, ObligationCause, VtableImpl,
use super::{Obligation, ObligationCause, VtableImpl,
VtableParam, VtableParamData, VtableImplData};

///////////////////////////////////////////////////////////////////////////
Expand Down
128 changes: 38 additions & 90 deletions src/librustc/middle/typeck/astconv.rs
Expand Up @@ -207,7 +207,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
decl_def_id: ast::DefId,
decl_generics: &ty::Generics<'tcx>,
self_ty: Option<Ty<'tcx>>,
associated_ty: Option<Ty<'tcx>>,
path: &ast::Path)
-> Substs<'tcx>
where AC: AstConv<'tcx>, RS: RegionScope
Expand Down Expand Up @@ -243,7 +242,7 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
};

create_substs_for_ast_path(this, rscope, path.span, decl_def_id,
decl_generics, self_ty, types, regions, associated_ty)
decl_generics, self_ty, types, regions)
}

fn create_substs_for_ast_path<'tcx,AC,RS>(
Expand All @@ -254,8 +253,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
decl_generics: &ty::Generics<'tcx>,
self_ty: Option<Ty<'tcx>>,
types: Vec<Ty<'tcx>>,
regions: Vec<ty::Region>,
associated_ty: Option<Ty<'tcx>>)
regions: Vec<ty::Region>)
-> Substs<'tcx>
where AC: AstConv<'tcx>, RS: RegionScope
{
Expand Down Expand Up @@ -366,9 +364,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
substs.types.push(
AssocSpace,
this.associated_type_binding(span,
associated_ty,
self_ty,
decl_def_id,
param.def_id))
param.def_id));
}

return substs;
Expand Down Expand Up @@ -417,19 +415,17 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
this: &AC,
rscope: &RS,
ast_trait_ref: &ast::PolyTraitRef,
self_ty: Option<Ty<'tcx>>,
associated_type: Option<Ty<'tcx>>)
self_ty: Option<Ty<'tcx>>)
-> Rc<ty::TraitRef<'tcx>>
where AC: AstConv<'tcx>, RS: RegionScope
{
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, associated_type)
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty)
}

pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
rscope: &RS,
ast_trait_ref: &ast::TraitRef,
self_ty: Option<Ty<'tcx>>,
associated_type: Option<Ty<'tcx>>)
self_ty: Option<Ty<'tcx>>)
-> Rc<ty::TraitRef<'tcx>>
where AC: AstConv<'tcx>,
RS: RegionScope
Expand All @@ -444,8 +440,8 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
ast_trait_ref.path.span,
ast_trait_ref.ref_id) {
def::DefTrait(trait_def_id) => {
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
associated_type, &ast_trait_ref.path));
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id,
self_ty, &ast_trait_ref.path));
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
trait_ref.clone());
trait_ref
Expand All @@ -463,7 +459,6 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
rscope: &RS,
trait_def_id: ast::DefId,
self_ty: Option<Ty<'tcx>>,
associated_type: Option<Ty<'tcx>>,
path: &ast::Path)
-> ty::TraitRef<'tcx>
where AC: AstConv<'tcx>, RS: RegionScope
Expand Down Expand Up @@ -493,8 +488,7 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
&trait_def.generics,
self_ty,
types,
regions,
associated_type);
regions);

ty::TraitRef::new(trait_def_id, substs)
}
Expand All @@ -517,7 +511,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
did,
&generics,
None,
None,
path);
let ty = decl_ty.subst(tcx, &substs);
TypeAndSubsts { substs: substs, ty: ty }
Expand Down Expand Up @@ -558,7 +551,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
Substs::new(VecPerParamSpace::params_from_type(type_params),
VecPerParamSpace::params_from_type(region_params))
} else {
ast_path_substs_for_ty(this, rscope, did, &generics, None, None, path)
ast_path_substs_for_ty(this, rscope, did, &generics, None, path)
};

let ty = decl_ty.subst(tcx, &substs);
Expand Down Expand Up @@ -726,7 +719,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
rscope,
trait_def_id,
None,
None,
path);
let empty_vec = [];
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
Expand All @@ -750,61 +742,37 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
}

fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
rscope: &RS,
trait_path: &ast::Path,
for_ast_type: &ast::Ty,
trait_type_id: ast::DefId,
span: Span)
-> Ty<'tcx>
where AC: AstConv<'tcx>, RS: RegionScope
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
rscope: &RS,
ast_ty: &ast::Ty, // the TyQPath
qpath: &ast::QPath)
-> Ty<'tcx>
where AC: AstConv<'tcx>, RS: RegionScope
{
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
trait_path.repr(this.tcx()),
for_ast_type.repr(this.tcx()),
trait_type_id.repr(this.tcx()));

// Find the trait that this associated type belongs to.
let trait_did = match ty::impl_or_trait_item(this.tcx(),
trait_type_id).container() {
ty::ImplContainer(_) => {
this.tcx().sess.span_bug(span,
"associated_ty_to_ty(): impl associated \
types shouldn't go through this \
function")
}
ty::TraitContainer(trait_id) => trait_id,
};
debug!("qpath_to_ty(ast_ty={})",
ast_ty.repr(this.tcx()));

let for_type = ast_ty_to_ty(this, rscope, for_ast_type);
if !this.associated_types_of_trait_are_valid(for_type, trait_did) {
this.tcx().sess.span_err(span,
"this associated type is not \
allowed in this context");
return ty::mk_err()
}
let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);

debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));

let trait_ref = ast_path_to_trait_ref(this,
let trait_ref = instantiate_trait_ref(this,
rscope,
trait_did,
None,
Some(for_type),
trait_path);

debug!("associated_ty_to_ty(trait_ref={})",
trait_ref.repr(this.tcx()));

let trait_def = this.get_trait_def(trait_did);
for type_parameter in trait_def.generics.types.iter() {
if type_parameter.def_id == trait_type_id {
debug!("associated_ty_to_ty(type_parameter={} substs={})",
type_parameter.repr(this.tcx()),
trait_ref.substs.repr(this.tcx()));
return *trait_ref.substs.types.get(type_parameter.space,
type_parameter.index)
&*qpath.trait_ref,
Some(self_type));

debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));

let trait_def = this.get_trait_def(trait_ref.def_id);

for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
if ty_param_def.name == qpath.item_name.name {
debug!("qpath_to_ty: corresponding ty_param_def={}", ty_param_def);
return trait_ref.substs.type_for_def(ty_param_def);
}
}
this.tcx().sess.span_bug(span,

this.tcx().sess.span_bug(ast_ty.span,
"this associated type didn't get added \
as a parameter for some reason")
}
Expand Down Expand Up @@ -931,7 +899,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
rscope,
trait_def_id,
None,
None,
path);
let empty_bounds: &[ast::TyParamBound] = &[];
let ast_bounds = match *bounds {
Expand Down Expand Up @@ -996,26 +963,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
}
}
ast::TyQPath(ref qpath) => {
match tcx.def_map.borrow().get(&ast_ty.id) {
None => {
tcx.sess.span_bug(ast_ty.span,
"unbound qualified path")
}
Some(&def::DefAssociatedTy(trait_type_id)) => {
associated_ty_to_ty(this,
rscope,
&qpath.trait_name,
&*qpath.for_type,
trait_type_id,
ast_ty.span)
}
Some(_) => {
tcx.sess.span_err(ast_ty.span,
"this qualified path does not name \
an associated type");
ty::mk_err()
}
}
qpath_to_ty(this, rscope, ast_ty, &**qpath)
}
ast::TyFixedLengthVec(ref ty, ref e) => {
match const_eval::eval_const_expr_partial(tcx, &**e) {
Expand Down Expand Up @@ -1411,7 +1359,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(

let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
Some(trait_bound) => {
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None))
}
None => {
this.tcx().sess.span_err(
Expand Down

4 comments on commit b64c7b8

@bors
Copy link
Contributor

@bors bors commented on b64c7b8 Nov 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from pcwalton
at nikomatsakis@b64c7b8

@bors
Copy link
Contributor

@bors bors commented on b64c7b8 Nov 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging nikomatsakis/rust/issue-17388-unbound-path-assoc-type = b64c7b8 into auto

@bors
Copy link
Contributor

@bors bors commented on b64c7b8 Nov 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nikomatsakis/rust/issue-17388-unbound-path-assoc-type = b64c7b8 merged ok, testing candidate = ae7bc845

@bors
Copy link
Contributor

@bors bors commented on b64c7b8 Nov 19, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.