Introduce VecPerParamSpace and use it to represent sets of types and
parameters This involves numerous substeps: 1. Treat Self same as any other parameter. 2. No longer compute offsets for method parameters. 3. Store all generic types (both trait/impl and method) with a method, eliminating odd discrepancies. 4. Stop doing unspeakable things to static methods and instead just use the natural types, now that we can easily add the type parameters from trait into the method's polytype. 5. No doubt some more. It was hard to separate these into distinct commits. Fixes #13564
This commit is contained in:
parent
0422934e24
commit
9153d8ad6c
49 changed files with 2577 additions and 2232 deletions
|
@ -27,6 +27,7 @@ use rustc::metadata::csearch;
|
|||
use rustc::metadata::decoder;
|
||||
use rustc::middle::def;
|
||||
use rustc::middle::subst;
|
||||
use rustc::middle::subst::VecPerParamSpace;
|
||||
use rustc::middle::ty;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
@ -53,6 +54,12 @@ impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
|
||||
fn clean(&self) -> VecPerParamSpace<U> {
|
||||
self.map(|x| x.clean())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clean<U>, U> Clean<U> for Gc<T> {
|
||||
fn clean(&self) -> U {
|
||||
(**self).clean()
|
||||
|
@ -488,17 +495,17 @@ impl Clean<TyParamBound> for ast::TyParamBound {
|
|||
}
|
||||
|
||||
fn external_path(name: &str, substs: &subst::Substs) -> Path {
|
||||
let lifetimes = substs.regions().get_vec(subst::TypeSpace)
|
||||
.iter()
|
||||
.filter_map(|v| v.clean())
|
||||
.collect();
|
||||
let types = substs.types.get_vec(subst::TypeSpace).clean();
|
||||
Path {
|
||||
global: false,
|
||||
segments: vec![PathSegment {
|
||||
name: name.to_string(),
|
||||
lifetimes: match substs.regions {
|
||||
subst::ErasedRegions => Vec::new(),
|
||||
subst::NonerasedRegions(ref v) => {
|
||||
v.iter().filter_map(|v| v.clean()).collect()
|
||||
}
|
||||
},
|
||||
types: substs.tps.clean(),
|
||||
lifetimes: lifetimes,
|
||||
types: types,
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
@ -578,12 +585,8 @@ impl Clean<Vec<TyParamBound>> for ty::ParamBounds {
|
|||
impl Clean<Option<Vec<TyParamBound>>> for subst::Substs {
|
||||
fn clean(&self) -> Option<Vec<TyParamBound>> {
|
||||
let mut v = Vec::new();
|
||||
match self.regions {
|
||||
subst::NonerasedRegions(..) => v.push(RegionBound),
|
||||
subst::ErasedRegions => {}
|
||||
}
|
||||
v.extend(self.tps.iter().map(|t| TraitBound(t.clean())));
|
||||
|
||||
v.extend(self.regions().iter().map(|_| RegionBound));
|
||||
v.extend(self.types.iter().map(|t| TraitBound(t.clean())));
|
||||
if v.len() > 0 {Some(v)} else {None}
|
||||
}
|
||||
}
|
||||
|
@ -617,7 +620,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
|
|||
ty::ReStatic => Some(Lifetime("static".to_string())),
|
||||
ty::ReLateBound(_, ty::BrNamed(_, name)) =>
|
||||
Some(Lifetime(token::get_name(name).get().to_string())),
|
||||
ty::ReEarlyBound(_, _, name) => Some(Lifetime(name.clean())),
|
||||
ty::ReEarlyBound(_, _, _, name) => Some(Lifetime(name.clean())),
|
||||
|
||||
ty::ReLateBound(..) |
|
||||
ty::ReFree(..) |
|
||||
|
@ -638,17 +641,41 @@ pub struct Generics {
|
|||
impl Clean<Generics> for ast::Generics {
|
||||
fn clean(&self) -> Generics {
|
||||
Generics {
|
||||
lifetimes: self.lifetimes.clean().move_iter().collect(),
|
||||
type_params: self.ty_params.clean().move_iter().collect(),
|
||||
lifetimes: self.lifetimes.clean(),
|
||||
type_params: self.ty_params.clean(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Generics> for ty::Generics {
|
||||
fn clean(&self) -> Generics {
|
||||
// In the type space, generics can come in one of multiple
|
||||
// namespaces. This means that e.g. for fn items the type
|
||||
// parameters will live in FnSpace, but for types the
|
||||
// parameters will live in TypeSpace (trait definitions also
|
||||
// define a parameter in SelfSpace). *Method* definitions are
|
||||
// the one exception: they combine the TypeSpace parameters
|
||||
// from the enclosing impl/trait with their own FnSpace
|
||||
// parameters.
|
||||
//
|
||||
// In general, when we clean, we are trying to produce the
|
||||
// "user-facing" generics. Hence we select the most specific
|
||||
// namespace that is occupied, ignoring SelfSpace because it
|
||||
// is implicit.
|
||||
|
||||
let space = {
|
||||
if !self.types.get_vec(subst::FnSpace).is_empty() ||
|
||||
!self.regions.get_vec(subst::FnSpace).is_empty()
|
||||
{
|
||||
subst::FnSpace
|
||||
} else {
|
||||
subst::TypeSpace
|
||||
}
|
||||
};
|
||||
|
||||
Generics {
|
||||
lifetimes: self.region_param_defs.clean(),
|
||||
type_params: self.type_param_defs.clean(),
|
||||
type_params: self.types.get_vec(space).clean(),
|
||||
lifetimes: self.regions.get_vec(space).clean(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1259,8 +1286,13 @@ impl Clean<Type> for ty::t {
|
|||
}
|
||||
ty::ty_tup(ref t) => Tuple(t.iter().map(|t| t.clean()).collect()),
|
||||
|
||||
ty::ty_param(ref p) => Generic(p.def_id),
|
||||
ty::ty_self(did) => Self(did),
|
||||
ty::ty_param(ref p) => {
|
||||
if p.space == subst::SelfSpace {
|
||||
Self(p.def_id)
|
||||
} else {
|
||||
Generic(p.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_infer(..) => fail!("ty_infer"),
|
||||
ty::ty_err => fail!("ty_err"),
|
||||
|
@ -1968,7 +2000,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
|
|||
ast::TyFloat(ast::TyF64) => return Primitive(F64),
|
||||
ast::TyFloat(ast::TyF128) => return Primitive(F128),
|
||||
},
|
||||
def::DefTyParam(i, _) => return Generic(i),
|
||||
def::DefTyParam(_, i, _) => return Generic(i),
|
||||
def::DefTyParamBinder(i) => return TyParamBinder(i),
|
||||
_ => {}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue