Refactor QPath to take an ast::TraitRef
This commit is contained in:
parent
cf7df1e638
commit
b64c7b83dd
16 changed files with 119 additions and 187 deletions
|
@ -633,6 +633,7 @@ enum TraitReferenceType {
|
||||||
TraitDerivation, // trait T : SomeTrait { ... }
|
TraitDerivation, // trait T : SomeTrait { ... }
|
||||||
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
|
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
|
||||||
TraitObject, // Box<for<'a> SomeTrait>
|
TraitObject, // Box<for<'a> SomeTrait>
|
||||||
|
TraitQPath, // <T as SomeTrait>::
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NameBindings {
|
impl NameBindings {
|
||||||
|
@ -4532,6 +4533,7 @@ impl<'a> Resolver<'a> {
|
||||||
TraitImplementation => "implement",
|
TraitImplementation => "implement",
|
||||||
TraitDerivation => "derive",
|
TraitDerivation => "derive",
|
||||||
TraitObject => "reference",
|
TraitObject => "reference",
|
||||||
|
TraitQPath => "extract an associated type from",
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
|
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
|
||||||
|
@ -4969,65 +4971,8 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TyQPath(ref qpath) => {
|
TyQPath(ref qpath) => {
|
||||||
self.resolve_type(&*qpath.for_type);
|
self.resolve_type(&*qpath.self_type);
|
||||||
|
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TyClosure(ref c) | TyProc(ref c) => {
|
TyClosure(ref c) | TyProc(ref c) => {
|
||||||
|
|
|
@ -100,6 +100,10 @@ impl<'tcx> Substs<'tcx> {
|
||||||
regions_is_noop && self.types.is_empty()
|
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 {
|
pub fn has_regions_escaping_depth(&self, depth: uint) -> bool {
|
||||||
self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
|
self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
|
||||||
match self.regions {
|
match self.regions {
|
||||||
|
|
|
@ -25,6 +25,7 @@ use std::rc::Rc;
|
||||||
use std::slice::Items;
|
use std::slice::Items;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::{Span, DUMMY_SP};
|
use syntax::codemap::{Span, DUMMY_SP};
|
||||||
|
use util::common::ErrorReported;
|
||||||
|
|
||||||
pub use self::fulfill::FulfillmentContext;
|
pub use self::fulfill::FulfillmentContext;
|
||||||
pub use self::select::SelectionContext;
|
pub use self::select::SelectionContext;
|
||||||
|
@ -95,10 +96,6 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
FieldSized,
|
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 Obligations<'tcx> = subst::VecPerParamSpace<Obligation<'tcx>>;
|
||||||
|
|
||||||
pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>;
|
pub type Selection<'tcx> = Vtable<'tcx, Obligation<'tcx>>;
|
||||||
|
|
|
@ -17,7 +17,6 @@ use self::Candidate::*;
|
||||||
use self::BuiltinBoundConditions::*;
|
use self::BuiltinBoundConditions::*;
|
||||||
use self::EvaluationResult::*;
|
use self::EvaluationResult::*;
|
||||||
|
|
||||||
use super::{ErrorReported};
|
|
||||||
use super::{Obligation, ObligationCause};
|
use super::{Obligation, ObligationCause};
|
||||||
use super::{SelectionError, Unimplemented, Overflow,
|
use super::{SelectionError, Unimplemented, Overflow,
|
||||||
OutputTypeParameterMismatch};
|
OutputTypeParameterMismatch};
|
||||||
|
@ -38,6 +37,7 @@ use std::cell::RefCell;
|
||||||
use std::collections::hash_map::HashMap;
|
use std::collections::hash_map::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use util::common::ErrorReported;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
pub struct SelectionContext<'cx, 'tcx:'cx> {
|
pub struct SelectionContext<'cx, 'tcx:'cx> {
|
||||||
|
|
|
@ -18,9 +18,10 @@ use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
use util::common::ErrorReported;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
use super::{ErrorReported, Obligation, ObligationCause, VtableImpl,
|
use super::{Obligation, ObligationCause, VtableImpl,
|
||||||
VtableParam, VtableParamData, VtableImplData};
|
VtableParam, VtableParamData, VtableImplData};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -207,7 +207,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||||
decl_def_id: ast::DefId,
|
decl_def_id: ast::DefId,
|
||||||
decl_generics: &ty::Generics<'tcx>,
|
decl_generics: &ty::Generics<'tcx>,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
associated_ty: Option<Ty<'tcx>>,
|
|
||||||
path: &ast::Path)
|
path: &ast::Path)
|
||||||
-> Substs<'tcx>
|
-> Substs<'tcx>
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
|
@ -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,
|
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>(
|
fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||||
|
@ -254,8 +253,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||||
decl_generics: &ty::Generics<'tcx>,
|
decl_generics: &ty::Generics<'tcx>,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
types: Vec<Ty<'tcx>>,
|
types: Vec<Ty<'tcx>>,
|
||||||
regions: Vec<ty::Region>,
|
regions: Vec<ty::Region>)
|
||||||
associated_ty: Option<Ty<'tcx>>)
|
|
||||||
-> Substs<'tcx>
|
-> Substs<'tcx>
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
{
|
{
|
||||||
|
@ -366,9 +364,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||||
substs.types.push(
|
substs.types.push(
|
||||||
AssocSpace,
|
AssocSpace,
|
||||||
this.associated_type_binding(span,
|
this.associated_type_binding(span,
|
||||||
associated_ty,
|
self_ty,
|
||||||
decl_def_id,
|
decl_def_id,
|
||||||
param.def_id))
|
param.def_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return substs;
|
return substs;
|
||||||
|
@ -417,19 +415,17 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
ast_trait_ref: &ast::PolyTraitRef,
|
ast_trait_ref: &ast::PolyTraitRef,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>)
|
||||||
associated_type: Option<Ty<'tcx>>)
|
|
||||||
-> Rc<ty::TraitRef<'tcx>>
|
-> Rc<ty::TraitRef<'tcx>>
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope
|
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,
|
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
ast_trait_ref: &ast::TraitRef,
|
ast_trait_ref: &ast::TraitRef,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>)
|
||||||
associated_type: Option<Ty<'tcx>>)
|
|
||||||
-> Rc<ty::TraitRef<'tcx>>
|
-> Rc<ty::TraitRef<'tcx>>
|
||||||
where AC: AstConv<'tcx>,
|
where AC: AstConv<'tcx>,
|
||||||
RS: RegionScope
|
RS: RegionScope
|
||||||
|
@ -444,8 +440,8 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||||
ast_trait_ref.path.span,
|
ast_trait_ref.path.span,
|
||||||
ast_trait_ref.ref_id) {
|
ast_trait_ref.ref_id) {
|
||||||
def::DefTrait(trait_def_id) => {
|
def::DefTrait(trait_def_id) => {
|
||||||
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
|
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id,
|
||||||
associated_type, &ast_trait_ref.path));
|
self_ty, &ast_trait_ref.path));
|
||||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||||
trait_ref.clone());
|
trait_ref.clone());
|
||||||
trait_ref
|
trait_ref
|
||||||
|
@ -463,7 +459,6 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
trait_def_id: ast::DefId,
|
trait_def_id: ast::DefId,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
associated_type: Option<Ty<'tcx>>,
|
|
||||||
path: &ast::Path)
|
path: &ast::Path)
|
||||||
-> ty::TraitRef<'tcx>
|
-> ty::TraitRef<'tcx>
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
|
@ -493,8 +488,7 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
|
||||||
&trait_def.generics,
|
&trait_def.generics,
|
||||||
self_ty,
|
self_ty,
|
||||||
types,
|
types,
|
||||||
regions,
|
regions);
|
||||||
associated_type);
|
|
||||||
|
|
||||||
ty::TraitRef::new(trait_def_id, substs)
|
ty::TraitRef::new(trait_def_id, substs)
|
||||||
}
|
}
|
||||||
|
@ -517,7 +511,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
did,
|
did,
|
||||||
&generics,
|
&generics,
|
||||||
None,
|
None,
|
||||||
None,
|
|
||||||
path);
|
path);
|
||||||
let ty = decl_ty.subst(tcx, &substs);
|
let ty = decl_ty.subst(tcx, &substs);
|
||||||
TypeAndSubsts { substs: substs, ty: ty }
|
TypeAndSubsts { substs: substs, ty: ty }
|
||||||
|
@ -558,7 +551,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||||
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||||
VecPerParamSpace::params_from_type(region_params))
|
VecPerParamSpace::params_from_type(region_params))
|
||||||
} else {
|
} 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);
|
let ty = decl_ty.subst(tcx, &substs);
|
||||||
|
@ -726,7 +719,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
rscope,
|
rscope,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
None,
|
None,
|
||||||
None,
|
|
||||||
path);
|
path);
|
||||||
let empty_vec = [];
|
let empty_vec = [];
|
||||||
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
|
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
|
||||||
|
@ -750,61 +742,37 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
|
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
trait_path: &ast::Path,
|
ast_ty: &ast::Ty, // the TyQPath
|
||||||
for_ast_type: &ast::Ty,
|
qpath: &ast::QPath)
|
||||||
trait_type_id: ast::DefId,
|
-> Ty<'tcx>
|
||||||
span: Span)
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
-> Ty<'tcx>
|
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope
|
|
||||||
{
|
{
|
||||||
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
|
debug!("qpath_to_ty(ast_ty={})",
|
||||||
trait_path.repr(this.tcx()),
|
ast_ty.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 self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
let for_type = ast_ty_to_ty(this, rscope, for_ast_type);
|
debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
|
||||||
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 trait_ref = ast_path_to_trait_ref(this,
|
let trait_ref = instantiate_trait_ref(this,
|
||||||
rscope,
|
rscope,
|
||||||
trait_did,
|
&*qpath.trait_ref,
|
||||||
None,
|
Some(self_type));
|
||||||
Some(for_type),
|
|
||||||
trait_path);
|
|
||||||
|
|
||||||
debug!("associated_ty_to_ty(trait_ref={})",
|
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
|
||||||
trait_ref.repr(this.tcx()));
|
|
||||||
|
|
||||||
let trait_def = this.get_trait_def(trait_did);
|
let trait_def = this.get_trait_def(trait_ref.def_id);
|
||||||
for type_parameter in trait_def.generics.types.iter() {
|
|
||||||
if type_parameter.def_id == trait_type_id {
|
for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
|
||||||
debug!("associated_ty_to_ty(type_parameter={} substs={})",
|
if ty_param_def.name == qpath.item_name.name {
|
||||||
type_parameter.repr(this.tcx()),
|
debug!("qpath_to_ty: corresponding ty_param_def={}", ty_param_def);
|
||||||
trait_ref.substs.repr(this.tcx()));
|
return trait_ref.substs.type_for_def(ty_param_def);
|
||||||
return *trait_ref.substs.types.get(type_parameter.space,
|
|
||||||
type_parameter.index)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tcx().sess.span_bug(span,
|
|
||||||
|
this.tcx().sess.span_bug(ast_ty.span,
|
||||||
"this associated type didn't get added \
|
"this associated type didn't get added \
|
||||||
as a parameter for some reason")
|
as a parameter for some reason")
|
||||||
}
|
}
|
||||||
|
@ -931,7 +899,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
rscope,
|
rscope,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
None,
|
None,
|
||||||
None,
|
|
||||||
path);
|
path);
|
||||||
let empty_bounds: &[ast::TyParamBound] = &[];
|
let empty_bounds: &[ast::TyParamBound] = &[];
|
||||||
let ast_bounds = match *bounds {
|
let ast_bounds = match *bounds {
|
||||||
|
@ -996,26 +963,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::TyQPath(ref qpath) => {
|
ast::TyQPath(ref qpath) => {
|
||||||
match tcx.def_map.borrow().get(&ast_ty.id) {
|
qpath_to_ty(this, rscope, ast_ty, &**qpath)
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast::TyFixedLengthVec(ref ty, ref e) => {
|
ast::TyFixedLengthVec(ref ty, ref e) => {
|
||||||
match const_eval::eval_const_expr_partial(tcx, &**e) {
|
match const_eval::eval_const_expr_partial(tcx, &**e) {
|
||||||
|
@ -1411,7 +1359,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
|
||||||
|
|
||||||
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
|
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
|
||||||
Some(trait_bound) => {
|
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 => {
|
None => {
|
||||||
this.tcx().sess.span_err(
|
this.tcx().sess.span_err(
|
||||||
|
|
|
@ -684,7 +684,11 @@ fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
ty: Option<Ty<'tcx>>,
|
ty: Option<Ty<'tcx>>,
|
||||||
associated_type_id: ast::DefId,
|
associated_type_id: ast::DefId,
|
||||||
generics: &ty::Generics<'tcx>)
|
generics: &ty::Generics<'tcx>)
|
||||||
-> Ty<'tcx> {
|
-> Ty<'tcx>
|
||||||
|
{
|
||||||
|
debug!("find_associated_type_in_generics(ty={}, associated_type_id={}, generics={}",
|
||||||
|
ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx));
|
||||||
|
|
||||||
let ty = match ty {
|
let ty = match ty {
|
||||||
None => {
|
None => {
|
||||||
tcx.sess.span_bug(span,
|
tcx.sess.span_bug(span,
|
||||||
|
@ -703,20 +707,22 @@ fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
for type_parameter in generics.types.iter() {
|
for type_parameter in generics.types.iter() {
|
||||||
if type_parameter.def_id == associated_type_id
|
if type_parameter.def_id == associated_type_id
|
||||||
&& type_parameter.associated_with == Some(param_id) {
|
&& type_parameter.associated_with == Some(param_id) {
|
||||||
return ty::mk_param_from_def(tcx, type_parameter)
|
return ty::mk_param_from_def(tcx, type_parameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.sess.span_bug(span,
|
tcx.sess.span_err(
|
||||||
"find_associated_type_in_generics(): didn't \
|
span,
|
||||||
find associated type anywhere in the generics \
|
format!("no suitable bound on `{}`",
|
||||||
list")
|
ty.user_string(tcx))[]);
|
||||||
|
ty::mk_err()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
tcx.sess.span_bug(span,
|
tcx.sess.span_err(
|
||||||
"find_associated_type_in_generics(): self type \
|
span,
|
||||||
is not a parameter")
|
"it is currently unsupported to access associated types except \
|
||||||
|
through a type parameter; this restriction will be lifted in time");
|
||||||
|
ty::mk_err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1161,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||||
|
|
||||||
for trait_ref in opt_trait_ref.iter() {
|
for trait_ref in opt_trait_ref.iter() {
|
||||||
astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref,
|
astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref,
|
||||||
Some(selfty), None);
|
Some(selfty));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||||
|
@ -1627,7 +1633,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||||
ccx,
|
ccx,
|
||||||
subst::AssocSpace,
|
subst::AssocSpace,
|
||||||
&associated_type.ty_param,
|
&associated_type.ty_param,
|
||||||
generics.types.len(subst::TypeSpace),
|
generics.types.len(subst::AssocSpace),
|
||||||
&ast_generics.where_clause,
|
&ast_generics.where_clause,
|
||||||
Some(local_def(trait_id)));
|
Some(local_def(trait_id)));
|
||||||
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
|
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
|
||||||
|
@ -2019,7 +2025,6 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||||
astconv::instantiate_poly_trait_ref(this,
|
astconv::instantiate_poly_trait_ref(this,
|
||||||
&ExplicitRscope,
|
&ExplicitRscope,
|
||||||
bound,
|
bound,
|
||||||
Some(param_ty.to_ty(this.tcx())),
|
|
||||||
Some(param_ty.to_ty(this.tcx())))
|
Some(param_ty.to_ty(this.tcx())))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -20,6 +20,10 @@ use syntax::ast;
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::Visitor;
|
||||||
|
|
||||||
|
// An error has already been reported to the user, so no need to continue checking.
|
||||||
|
#[deriving(Clone,Show)]
|
||||||
|
pub struct ErrorReported;
|
||||||
|
|
||||||
pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
|
pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
|
||||||
local_data_key!(depth: uint);
|
local_data_key!(depth: uint);
|
||||||
if !do_it { return f(u); }
|
if !do_it { return f(u); }
|
||||||
|
|
|
@ -706,11 +706,11 @@ pub enum Expr_ {
|
||||||
///
|
///
|
||||||
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
|
/// <Vec<T> as SomeTrait>::SomeAssociatedItem
|
||||||
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
|
/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~
|
||||||
/// for_type trait_name item_name
|
/// self_type trait_name item_name
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub struct QPath {
|
pub struct QPath {
|
||||||
pub for_type: P<Ty>,
|
pub self_type: P<Ty>,
|
||||||
pub trait_name: Path,
|
pub trait_ref: P<TraitRef>,
|
||||||
pub item_name: Ident,
|
pub item_name: Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,10 @@ pub trait Folder {
|
||||||
noop_fold_ty(t, self)
|
noop_fold_ty(t, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
|
||||||
|
noop_fold_qpath(t, self)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_mod(&mut self, m: Mod) -> Mod {
|
fn fold_mod(&mut self, m: Mod) -> Mod {
|
||||||
noop_fold_mod(m, self)
|
noop_fold_mod(m, self)
|
||||||
}
|
}
|
||||||
|
@ -435,12 +439,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
fld.fold_opt_bounds(bounds),
|
fld.fold_opt_bounds(bounds),
|
||||||
id)
|
id)
|
||||||
}
|
}
|
||||||
TyQPath(ref qpath) => {
|
TyQPath(qpath) => {
|
||||||
TyQPath(P(QPath {
|
TyQPath(fld.fold_qpath(qpath))
|
||||||
for_type: fld.fold_ty(qpath.for_type.clone()),
|
|
||||||
trait_name: fld.fold_path(qpath.trait_name.clone()),
|
|
||||||
item_name: fld.fold_ident(qpath.item_name.clone()),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
TyFixedLengthVec(ty, e) => {
|
TyFixedLengthVec(ty, e) => {
|
||||||
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
|
TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
|
||||||
|
@ -456,6 +456,16 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
|
||||||
|
qpath.map(|qpath| {
|
||||||
|
QPath {
|
||||||
|
self_type: fld.fold_ty(qpath.self_type),
|
||||||
|
trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
|
||||||
|
item_name: fld.fold_ident(qpath.item_name),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, view_items, items}: ForeignMod,
|
pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, view_items, items}: ForeignMod,
|
||||||
fld: &mut T) -> ForeignMod {
|
fld: &mut T) -> ForeignMod {
|
||||||
ForeignMod {
|
ForeignMod {
|
||||||
|
|
|
@ -1502,17 +1502,17 @@ impl<'a> Parser<'a> {
|
||||||
} else if self.eat_keyword(keywords::Proc) {
|
} else if self.eat_keyword(keywords::Proc) {
|
||||||
self.parse_proc_type(Vec::new())
|
self.parse_proc_type(Vec::new())
|
||||||
} else if self.token == token::Lt {
|
} else if self.token == token::Lt {
|
||||||
// QUALIFIED PATH
|
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
|
||||||
self.bump();
|
self.bump();
|
||||||
let for_type = self.parse_ty(true);
|
let self_type = self.parse_ty(true);
|
||||||
self.expect_keyword(keywords::As);
|
self.expect_keyword(keywords::As);
|
||||||
let trait_name = self.parse_path(LifetimeAndTypesWithoutColons);
|
let trait_ref = self.parse_trait_ref();
|
||||||
self.expect(&token::Gt);
|
self.expect(&token::Gt);
|
||||||
self.expect(&token::ModSep);
|
self.expect(&token::ModSep);
|
||||||
let item_name = self.parse_ident();
|
let item_name = self.parse_ident();
|
||||||
TyQPath(P(QPath {
|
TyQPath(P(QPath {
|
||||||
for_type: for_type,
|
self_type: self_type,
|
||||||
trait_name: trait_name.path,
|
trait_ref: P(trait_ref),
|
||||||
item_name: item_name,
|
item_name: item_name,
|
||||||
}))
|
}))
|
||||||
} else if self.token == token::ModSep ||
|
} else if self.token == token::ModSep ||
|
||||||
|
|
|
@ -744,10 +744,10 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::TyQPath(ref qpath) => {
|
ast::TyQPath(ref qpath) => {
|
||||||
try!(word(&mut self.s, "<"));
|
try!(word(&mut self.s, "<"));
|
||||||
try!(self.print_type(&*qpath.for_type));
|
try!(self.print_type(&*qpath.self_type));
|
||||||
try!(space(&mut self.s));
|
try!(space(&mut self.s));
|
||||||
try!(self.word_space("as"));
|
try!(self.word_space("as"));
|
||||||
try!(self.print_path(&qpath.trait_name, false));
|
try!(self.print_trait_ref(&*qpath.trait_ref));
|
||||||
try!(word(&mut self.s, ">"));
|
try!(word(&mut self.s, ">"));
|
||||||
try!(word(&mut self.s, "::"));
|
try!(word(&mut self.s, "::"));
|
||||||
try!(self.print_ident(qpath.item_name));
|
try!(self.print_ident(qpath.item_name));
|
||||||
|
|
|
@ -403,8 +403,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyQPath(ref qpath) => {
|
TyQPath(ref qpath) => {
|
||||||
visitor.visit_ty(&*qpath.for_type);
|
visitor.visit_ty(&*qpath.self_type);
|
||||||
visitor.visit_path(&qpath.trait_name, typ.id);
|
visitor.visit_trait_ref(&*qpath.trait_ref);
|
||||||
visitor.visit_ident(typ.span, qpath.item_name);
|
visitor.visit_ident(typ.span, qpath.item_name);
|
||||||
}
|
}
|
||||||
TyFixedLengthVec(ref ty, ref expression) => {
|
TyFixedLengthVec(ref ty, ref expression) => {
|
||||||
|
|
|
@ -20,12 +20,12 @@ fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
|
||||||
|
|
||||||
trait Other {
|
trait Other {
|
||||||
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||||
//~^ ERROR this associated type is not allowed in this context
|
//~^ ERROR no suitable bound on `Self`
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T:Get> Other for T {
|
impl<T:Get> Other for T {
|
||||||
fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
|
fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
|
||||||
//~^ ERROR this associated type is not allowed in this context
|
//~^ ERROR currently unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Grab {
|
trait Grab {
|
||||||
|
|
|
@ -16,7 +16,7 @@ trait Get {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(x: int) -> <int as Get>::Value {}
|
fn get(x: int) -> <int as Get>::Value {}
|
||||||
//~^ ERROR this associated type is not allowed in this context
|
//~^ ERROR unsupported
|
||||||
|
|
||||||
struct Struct {
|
struct Struct {
|
||||||
x: int,
|
x: int,
|
||||||
|
@ -24,7 +24,7 @@ struct Struct {
|
||||||
|
|
||||||
impl Struct {
|
impl Struct {
|
||||||
fn uhoh<T>(foo: <T as Get>::Value) {}
|
fn uhoh<T>(foo: <T as Get>::Value) {}
|
||||||
//~^ ERROR this associated type is not allowed in this context
|
//~^ ERROR no suitable bound on `T`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(associated_types)]
|
||||||
|
|
||||||
|
trait Foo<T> {
|
||||||
|
type Bar;
|
||||||
|
fn get_bar() -> <Self as Foo<T>>::Bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
Loading…
Add table
Add a link
Reference in a new issue