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:
Niko Matsakis 2014-05-31 18:53:13 -04:00
parent 0422934e24
commit 9153d8ad6c
49 changed files with 2577 additions and 2232 deletions

View file

@ -189,9 +189,7 @@ pub static tag_impls_impl: uint = 0x81;
pub static tag_items_data_item_inherent_impl: uint = 0x82;
pub static tag_items_data_item_extension_impl: uint = 0x83;
pub static tag_region_param_def: uint = 0x84;
pub static tag_region_param_def_ident: uint = 0x85;
pub static tag_region_param_def_def_id: uint = 0x86;
// GAP 0x84, 0x85, 0x86
pub static tag_native_libraries: uint = 0x87;
pub static tag_native_libraries_lib: uint = 0x88;
@ -217,3 +215,9 @@ pub struct LinkMeta {
pub crateid: CrateId,
pub crate_hash: Svh,
}
pub static tag_region_param_def: uint = 0x90;
pub static tag_region_param_def_ident: uint = 0x91;
pub static tag_region_param_def_def_id: uint = 0x92;
pub static tag_region_param_def_space: uint = 0x93;
pub static tag_region_param_def_index: uint = 0x94;

View file

@ -18,6 +18,7 @@ use metadata::decoder;
use middle::lang_items;
use middle::ty;
use middle::typeck;
use middle::subst::VecPerParamSpace;
use serialize::ebml;
use serialize::ebml::reader;
@ -223,8 +224,8 @@ pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
});
let ty = decoder::item_type(def, the_field, tcx, &*cdata);
ty::ty_param_bounds_and_ty {
generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
region_param_defs: Rc::new(Vec::new())},
generics: ty::Generics {types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty()},
ty: ty
}
}
@ -240,7 +241,8 @@ pub fn get_impl_trait(tcx: &ty::ctxt,
// Given a def_id for an impl, return information about its vtables
pub fn get_impl_vtables(tcx: &ty::ctxt,
def: ast::DefId) -> typeck::impl_res {
def: ast::DefId)
-> typeck::vtable_res {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_impl_vtables(&*cdata, def.node, tcx)

View file

@ -23,6 +23,7 @@ use metadata::tydecode::{parse_ty_data, parse_def_id,
parse_bare_fn_ty_data, parse_trait_ref_data};
use middle::lang_items;
use middle::def;
use middle::subst;
use middle::ty::{ImplContainer, TraitContainer};
use middle::ty;
use middle::typeck;
@ -257,21 +258,22 @@ fn item_ty_param_defs(item: ebml::Doc,
tcx: &ty::ctxt,
cdata: Cmd,
tag: uint)
-> Rc<Vec<ty::TypeParameterDef> > {
let mut bounds = Vec::new();
-> subst::VecPerParamSpace<ty::TypeParameterDef> {
let mut bounds = subst::VecPerParamSpace::empty();
reader::tagged_docs(item, tag, |p| {
let bd = parse_type_param_def_data(
p.data, p.start, cdata.cnum, tcx,
|_, did| translate_def_id(cdata, did));
bounds.push(bd);
bounds.push(bd.space, bd);
true
});
Rc::new(bounds)
bounds
}
fn item_region_param_defs(item_doc: ebml::Doc, cdata: Cmd)
-> Rc<Vec<ty::RegionParameterDef> > {
let mut v = Vec::new();
-> subst::VecPerParamSpace<ty::RegionParameterDef>
{
let mut v = subst::VecPerParamSpace::empty();
reader::tagged_docs(item_doc, tag_region_param_def, |rp_doc| {
let ident_str_doc = reader::get_doc(rp_doc,
tag_region_param_def_ident);
@ -280,11 +282,20 @@ fn item_region_param_defs(item_doc: ebml::Doc, cdata: Cmd)
tag_region_param_def_def_id);
let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
let def_id = translate_def_id(cdata, def_id);
v.push(ty::RegionParameterDef { name: ident.name,
def_id: def_id });
let doc = reader::get_doc(rp_doc, tag_region_param_def_space);
let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as uint);
let doc = reader::get_doc(rp_doc, tag_region_param_def_index);
let index = reader::doc_as_u64(doc) as uint;
v.push(space, ty::RegionParameterDef { name: ident.name,
def_id: def_id,
space: space,
index: index });
true
});
Rc::new(v)
v
}
fn enum_variant_ids(item: ebml::Doc, cdata: Cmd) -> Vec<ast::DefId> {
@ -403,8 +414,8 @@ pub fn get_trait_def(cdata: Cmd,
}
ty::TraitDef {
generics: ty::Generics {type_param_defs: tp_defs,
region_param_defs: rp_defs},
generics: ty::Generics {types: tp_defs,
regions: rp_defs},
bounds: bounds,
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
}
@ -422,8 +433,8 @@ pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
let rp_defs = item_region_param_defs(item, cdata);
ty::ty_param_bounds_and_ty {
generics: ty::Generics {type_param_defs: tp_defs,
region_param_defs: rp_defs},
generics: ty::Generics {types: tp_defs,
regions: rp_defs},
ty: t
}
}
@ -440,16 +451,13 @@ pub fn get_impl_trait(cdata: Cmd,
pub fn get_impl_vtables(cdata: Cmd,
id: ast::NodeId,
tcx: &ty::ctxt) -> typeck::impl_res
tcx: &ty::ctxt)
-> typeck::vtable_res
{
let item_doc = lookup_item(id, cdata.data());
let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
let mut decoder = reader::Decoder::new(vtables_doc);
typeck::impl_res {
trait_vtables: decoder.read_vtable_res(tcx, cdata),
self_vtables: decoder.read_vtable_param_res(tcx, cdata)
}
decoder.read_vtable_res(tcx, cdata)
}
@ -802,8 +810,8 @@ pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
ty::Method::new(
name,
ty::Generics {
type_param_defs: type_param_defs,
region_param_defs: rp_defs,
types: type_param_defs,
regions: rp_defs,
},
fty,
explicit_self,

View file

@ -19,6 +19,7 @@ use metadata::common::*;
use metadata::cstore;
use metadata::decoder;
use metadata::tyencode;
use middle::subst::VecPerParamSpace;
use middle::ty::{node_id_to_type, lookup_item_type};
use middle::astencode;
use middle::ty;
@ -128,10 +129,9 @@ fn encode_trait_ref(ebml_w: &mut Encoder,
fn encode_impl_vtables(ebml_w: &mut Encoder,
ecx: &EncodeContext,
vtables: &typeck::impl_res) {
vtables: &typeck::vtable_res) {
ebml_w.start_tag(tag_item_impl_vtables);
astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
astencode::encode_vtable_res(ecx, ebml_w, vtables);
ebml_w.end_tag();
}
@ -148,7 +148,7 @@ pub fn def_to_str(did: DefId) -> String {
fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
ecx: &EncodeContext,
params: &[ty::TypeParameterDef],
params: &VecPerParamSpace<ty::TypeParameterDef>,
tag: uint) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
@ -164,7 +164,7 @@ fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
}
fn encode_region_param_defs(ebml_w: &mut Encoder,
params: &[ty::RegionParameterDef]) {
params: &VecPerParamSpace<ty::RegionParameterDef>) {
for param in params.iter() {
ebml_w.start_tag(tag_region_param_def);
@ -175,6 +175,12 @@ fn encode_region_param_defs(ebml_w: &mut Encoder,
ebml_w.wr_tagged_str(tag_region_param_def_def_id,
def_to_str(param.def_id).as_slice());
ebml_w.wr_tagged_u64(tag_region_param_def_space,
param.space.to_uint() as u64);
ebml_w.wr_tagged_u64(tag_region_param_def_index,
param.index as u64);
ebml_w.end_tag();
}
}
@ -191,9 +197,9 @@ fn encode_item_variances(ebml_w: &mut Encoder,
fn encode_bounds_and_type(ebml_w: &mut Encoder,
ecx: &EncodeContext,
tpt: &ty::ty_param_bounds_and_ty) {
encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
encode_ty_type_param_defs(ebml_w, ecx, &tpt.generics.types,
tag_items_data_item_ty_param_bounds);
encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
encode_region_param_defs(ebml_w, &tpt.generics.regions);
encode_type(ecx, ebml_w, tpt.ty);
}
@ -725,8 +731,7 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
method_ty: &ty::Method) {
encode_def_id(ebml_w, method_ty.def_id);
encode_name(ebml_w, method_ty.ident.name);
encode_ty_type_param_defs(ebml_w, ecx,
method_ty.generics.type_param_defs(),
encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
tag_item_method_tps);
encode_method_fty(ecx, ebml_w, &method_ty.fty);
encode_visibility(ebml_w, method_ty.vis);
@ -770,10 +775,8 @@ fn encode_info_for_method(ecx: &EncodeContext,
}
for &ast_method in ast_method_opt.iter() {
let num_params = tpt.generics.type_param_defs().len();
if num_params > 0u ||
is_default_impl ||
should_inline(ast_method.attrs.as_slice()) {
let any_types = !tpt.generics.types.is_empty();
if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
encode_inlined_item(ecx, ebml_w,
IIMethodRef(local_def(parent_id), false,
&*ast_method));
@ -1125,9 +1128,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_item_variances(ebml_w, ecx, item.id);
let trait_def = ty::lookup_trait_def(tcx, def_id);
encode_ty_type_param_defs(ebml_w, ecx,
trait_def.generics.type_param_defs(),
&trait_def.generics.types,
tag_items_data_item_ty_param_bounds);
encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
encode_region_param_defs(ebml_w, &trait_def.generics.regions);
encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
encode_name(ebml_w, item.ident.name);
encode_attributes(ebml_w, item.attrs.as_slice());

View file

@ -17,6 +17,7 @@
#![allow(non_camel_case_types)]
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty;
use std::rc::Rc;
@ -114,26 +115,45 @@ pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
}
}
fn data_log_string(data: &[u8], pos: uint) -> String {
let mut buf = String::new();
buf.push_str("<<");
for i in range(pos, data.len()) {
let c = data[i];
if c > 0x20 && c <= 0x7F {
buf.push_char(c as char);
} else {
buf.push_char('.');
}
}
buf.push_str(">>");
buf
}
pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
conv: conv_did) -> ty::t {
debug!("parse_ty_data {}", data_log_string(data, pos));
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_ty(&mut st, conv)
}
pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
conv: conv_did) -> ty::BareFnTy {
debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_bare_fn_ty(&mut st, conv)
}
pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
conv: conv_did) -> ty::TraitRef {
debug!("parse_trait_ref_data {}", data_log_string(data, pos));
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_trait_ref(&mut st, conv)
}
pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
conv: conv_did) -> subst::Substs {
debug!("parse_substs_data {}", data_log_string(data, pos));
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_substs(&mut st, conv)
}
@ -162,34 +182,39 @@ fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
}
}
fn parse_substs(st: &mut PState, conv: conv_did) -> subst::Substs {
let regions = parse_region_substs(st, |x,y| conv(x,y));
let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
fn parse_vec_per_param_space<T>(st: &mut PState,
f: |&mut PState| -> T)
-> VecPerParamSpace<T>
{
let mut r = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
assert_eq!(next(st), '[');
let mut params: Vec<ty::t> = Vec::new();
while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
st.pos = st.pos + 1u;
while peek(st) != ']' {
r.push(space, f(st));
}
assert_eq!(next(st), ']');
}
r
}
return subst::Substs {
regions: regions,
self_ty: self_ty,
tps: params
};
fn parse_substs(st: &mut PState, conv: conv_did) -> subst::Substs {
let regions =
parse_region_substs(st, |x,y| conv(x,y));
let types =
parse_vec_per_param_space(st, |st| parse_ty(st, |x,y| conv(x,y)));
return subst::Substs { types: types,
regions: regions };
}
fn parse_region_substs(st: &mut PState, conv: conv_did) -> subst::RegionSubsts {
match next(st) {
'e' => subst::ErasedRegions,
'n' => {
let mut regions = vec!();
while peek(st) != '.' {
let r = parse_region(st, |x,y| conv(x,y));
regions.push(r);
}
assert_eq!(next(st), '.');
subst::NonerasedRegions(regions)
subst::NonerasedRegions(
parse_vec_per_param_space(
st, |st| parse_region(st, |x,y| conv(x,y))))
}
_ => fail!("parse_bound_region: bad input")
}
@ -230,10 +255,12 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
assert_eq!(next(st), '[');
let node_id = parse_uint(st) as ast::NodeId;
assert_eq!(next(st), '|');
let space = parse_param_space(st);
assert_eq!(next(st), '|');
let index = parse_uint(st);
assert_eq!(next(st), '|');
let nm = token::str_to_ident(parse_str(st, ']').as_slice());
ty::ReEarlyBound(node_id, index, nm.name)
ty::ReEarlyBound(node_id, space, index, nm.name)
}
'f' => {
assert_eq!(next(st), '[');
@ -327,11 +354,11 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
'p' => {
let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
debug!("parsed ty_param: did={:?}", did);
return ty::mk_param(st.tcx, parse_uint(st), did);
}
's' => {
let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
return ty::mk_self(st.tcx, did);
let index = parse_uint(st);
assert_eq!(next(st), '|');
let space = parse_param_space(st);
assert_eq!(next(st), '|');
return ty::mk_param(st.tcx, space, index, did);
}
'@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
'~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
@ -395,6 +422,9 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
assert_eq!(next(st), ']');
return ty::mk_struct(st.tcx, did, substs);
}
'e' => {
return ty::mk_err();
}
c => { fail!("unexpected char in type string: {}", c);}
}
}
@ -427,6 +457,10 @@ fn parse_uint(st: &mut PState) -> uint {
};
}
fn parse_param_space(st: &mut PState) -> subst::ParamSpace {
subst::ParamSpace::from_uint(parse_uint(st))
}
fn parse_hex(st: &mut PState) -> uint {
let mut n = 0u;
loop {
@ -546,11 +580,22 @@ pub fn parse_type_param_def_data(data: &[u8], start: uint,
}
fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
let ident = parse_ident(st, ':');
let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
let space = parse_param_space(st);
assert_eq!(next(st), '|');
let index = parse_uint(st);
assert_eq!(next(st), '|');
let bounds = Rc::new(parse_bounds(st, |x,y| conv(x,y)));
let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
ty::TypeParameterDef {
ident: parse_ident(st, ':'),
def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
bounds: Rc::new(parse_bounds(st, |x,y| conv(x,y))),
default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
ident: ident,
def_id: def_id,
space: space,
index: index,
bounds: bounds,
default: default
}
}

View file

@ -18,7 +18,8 @@ use std::collections::HashMap;
use std::io::MemWriter;
use middle::subst;
use middle::ty::param_ty;
use middle::subst::VecPerParamSpace;
use middle::ty::ParamTy;
use middle::ty;
use syntax::abi::Abi;
@ -118,12 +119,23 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
}
}
fn enc_vec_per_param_space<T>(w: &mut MemWriter,
cx: &ctxt,
v: &VecPerParamSpace<T>,
op: |&mut MemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
for t in v.get_vec(space).iter() {
op(w, cx, t);
}
mywrite!(w, "]");
}
}
pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::Substs) {
enc_region_substs(w, cx, &substs.regions);
enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t));
mywrite!(w, "[");
for t in substs.tps.iter() { enc_ty(w, cx, *t); }
mywrite!(w, "]");
enc_vec_per_param_space(w, cx, &substs.types,
|w, cx, &ty| enc_ty(w, cx, ty));
}
fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
@ -133,10 +145,8 @@ fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts)
}
subst::NonerasedRegions(ref regions) => {
mywrite!(w, "n");
for &r in regions.iter() {
enc_region(w, cx, r);
}
mywrite!(w, ".");
enc_vec_per_param_space(w, cx, regions,
|w, cx, &r| enc_region(w, cx, r));
}
}
}
@ -148,9 +158,10 @@ fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
enc_bound_region(w, cx, br);
mywrite!(w, "]");
}
ty::ReEarlyBound(node_id, index, name) => {
mywrite!(w, "B[{}|{}|{}]",
ty::ReEarlyBound(node_id, space, index, name) => {
mywrite!(w, "B[{}|{}|{}|{}]",
node_id,
space.to_uint(),
index,
token::get_name(name));
}
@ -293,18 +304,17 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
ty::ty_infer(_) => {
cx.diag.handler().bug("cannot encode inference variable types");
}
ty::ty_param(param_ty {idx: id, def_id: did}) => {
mywrite!(w, "p{}|{}", (cx.ds)(did), id);
}
ty::ty_self(did) => {
mywrite!(w, "s{}|", (cx.ds)(did));
ty::ty_param(ParamTy {space, idx: id, def_id: did}) => {
mywrite!(w, "p{}|{}|{}|", (cx.ds)(did), id, space.to_uint())
}
ty::ty_struct(def, ref substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_err => fail!("shouldn't encode error type")
ty::ty_err => {
mywrite!(w, "e");
}
}
}
@ -378,7 +388,9 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
}
pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
mywrite!(w, "{}:{}|", token::get_ident(v.ident), (cx.ds)(v.def_id));
mywrite!(w, "{}:{}|{}|{}|",
token::get_ident(v.ident), (cx.ds)(v.def_id),
v.space.to_uint(), v.index);
enc_bounds(w, cx, &*v.bounds);
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
}

View file

@ -25,6 +25,7 @@ use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
RegionParameter};
use metadata::tyencode;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
use middle::{ty, typeck};
use util::ppaux::ty_to_str;
@ -39,7 +40,7 @@ use libc;
use std::io::Seek;
use std::io::MemWriter;
use std::mem;
use std::rc::Rc;
use std::string::String;
use serialize::ebml::reader;
use serialize::ebml;
@ -433,7 +434,7 @@ impl tr for def::Def {
def::DefTrait(did) => def::DefTrait(did.tr(xcx)),
def::DefTy(did) => def::DefTy(did.tr(xcx)),
def::DefPrimTy(p) => def::DefPrimTy(p),
def::DefTyParam(did, v) => def::DefTyParam(did.tr(xcx), v),
def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(xcx), v),
def::DefBinding(nid, bm) => def::DefBinding(xcx.tr_id(nid), bm),
def::DefUse(did) => def::DefUse(did.tr(xcx)),
def::DefUpvar(nid1, def, nid2, nid3) => {
@ -476,13 +477,18 @@ impl tr for ty::AutoRef {
impl tr for ty::Region {
fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::Region {
match *self {
ty::ReLateBound(id, br) => ty::ReLateBound(xcx.tr_id(id),
br.tr(xcx)),
ty::ReEarlyBound(id, index, ident) => ty::ReEarlyBound(xcx.tr_id(id),
index,
ident),
ty::ReScope(id) => ty::ReScope(xcx.tr_id(id)),
ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => *self,
ty::ReLateBound(id, br) => {
ty::ReLateBound(xcx.tr_id(id), br.tr(xcx))
}
ty::ReEarlyBound(id, space, index, ident) => {
ty::ReEarlyBound(xcx.tr_id(id), space, index, ident)
}
ty::ReScope(id) => {
ty::ReScope(xcx.tr_id(id))
}
ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => {
*self
}
ty::ReFree(ref fr) => {
ty::ReFree(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id),
bound_region: fr.bound_region.tr(xcx)})
@ -640,9 +646,10 @@ pub fn encode_vtable_res(ecx: &e::EncodeContext,
// ty::t doesn't work, and there is no way (atm) to have
// hand-written encoding routines combine with auto-generated
// ones. perhaps we should fix this.
ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
Ok(encode_vtable_param_res(ecx, ebml_w, param_tables))
}).unwrap()
encode_vec_per_param_space(
ebml_w, dr,
|ebml_w, param_tables| encode_vtable_param_res(ecx, ebml_w,
param_tables))
}
pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
@ -673,7 +680,7 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
})
}
typeck::vtable_param(pn, bn) => {
ebml_w.emit_enum_variant("vtable_param", 1u, 2u, |ebml_w| {
ebml_w.emit_enum_variant("vtable_param", 1u, 3u, |ebml_w| {
ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
pn.encode(ebml_w)
});
@ -682,11 +689,19 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
})
})
}
typeck::vtable_error => {
ebml_w.emit_enum_variant("vtable_error", 2u, 3u, |_ebml_w| {
Ok(())
})
}
}
}).unwrap()
}
pub trait vtable_decoder_helpers {
fn read_vec_per_param_space<T>(&mut self,
f: |&mut Self| -> T)
-> VecPerParamSpace<T>;
fn read_vtable_res_with_key(&mut self,
tcx: &ty::ctxt,
cdata: &cstore::crate_metadata)
@ -703,6 +718,16 @@ pub trait vtable_decoder_helpers {
}
impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
fn read_vec_per_param_space<T>(&mut self,
f: |&mut reader::Decoder<'a>| -> T)
-> VecPerParamSpace<T>
{
let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
VecPerParamSpace::new(types, selfs, fns)
}
fn read_vtable_res_with_key(&mut self,
tcx: &ty::ctxt,
cdata: &cstore::crate_metadata)
@ -718,10 +743,12 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
}
fn read_vtable_res(&mut self,
tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
-> typeck::vtable_res {
self.read_to_vec(|this| Ok(this.read_vtable_param_res(tcx, cdata)))
.unwrap().move_iter().collect()
tcx: &ty::ctxt,
cdata: &cstore::crate_metadata)
-> typeck::vtable_res
{
self.read_vec_per_param_space(
|this| this.read_vtable_param_res(tcx, cdata))
}
fn read_vtable_param_res(&mut self,
@ -737,7 +764,7 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
self.read_enum("vtable_origin", |this| {
this.read_enum_variant(["vtable_static",
"vtable_param",
"vtable_self"],
"vtable_error"],
|this, i| {
Ok(match i {
0 => {
@ -763,7 +790,9 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
}).unwrap()
)
}
// hard to avoid - user input
2 => {
typeck::vtable_error
}
_ => fail!("bad enum variant")
})
})
@ -771,6 +800,18 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
}
}
// ___________________________________________________________________________
//
fn encode_vec_per_param_space<T>(ebml_w: &mut Encoder,
v: &subst::VecPerParamSpace<T>,
f: |&mut Encoder, &T|) {
for &space in subst::ParamSpace::all().iter() {
ebml_w.emit_from_vec(v.get_vec(space).as_slice(),
|ebml_w, n| Ok(f(ebml_w, n))).unwrap();
}
}
// ______________________________________________________________________
// Encoding and decoding the side tables
@ -827,14 +868,15 @@ impl<'a> ebml_writer_helpers for Encoder<'a> {
self.emit_struct("ty_param_bounds_and_ty", 2, |this| {
this.emit_struct_field("generics", 0, |this| {
this.emit_struct("Generics", 2, |this| {
this.emit_struct_field("type_param_defs", 0, |this| {
this.emit_from_vec(tpbt.generics.type_param_defs(),
|this, type_param_def| {
Ok(this.emit_type_param_def(ecx, type_param_def))
})
this.emit_struct_field("types", 0, |this| {
Ok(encode_vec_per_param_space(
this, &tpbt.generics.types,
|this, def| this.emit_type_param_def(ecx, def)))
});
this.emit_struct_field("region_param_defs", 1, |this| {
tpbt.generics.region_param_defs().encode(this)
this.emit_struct_field("regions", 1, |this| {
Ok(encode_vec_per_param_space(
this, &tpbt.generics.regions,
|this, def| def.encode(this).unwrap()))
})
})
});
@ -1186,21 +1228,16 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
generics: this.read_struct_field("generics", 0, |this| {
this.read_struct("Generics", 2, |this| {
Ok(ty::Generics {
type_param_defs:
this.read_struct_field("type_param_defs",
0,
|this| {
Ok(Rc::new(this.read_to_vec(|this|
Ok(this.read_type_param_def(xcx)))
.unwrap()
.move_iter()
.collect()))
types:
this.read_struct_field("types", 0, |this| {
Ok(this.read_vec_per_param_space(
|this| this.read_type_param_def(xcx)))
}).unwrap(),
region_param_defs:
this.read_struct_field("region_param_defs",
1,
|this| {
Decodable::decode(this)
regions:
this.read_struct_field("regions", 1, |this| {
Ok(this.read_vec_per_param_space(
|this| Decodable::decode(this).unwrap()))
}).unwrap()
})
})

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use middle::subst::ParamSpace;
use syntax::ast;
use syntax::ast_util::local_def;
@ -27,7 +28,7 @@ pub enum Def {
DefTy(ast::DefId),
DefTrait(ast::DefId),
DefPrimTy(ast::PrimTy),
DefTyParam(ast::DefId, uint),
DefTyParam(ParamSpace, ast::DefId, uint),
DefBinding(ast::NodeId, ast::BindingMode),
DefUse(ast::DefId),
DefUpvar(ast::NodeId, // id of closed over var
@ -61,7 +62,7 @@ impl Def {
match *self {
DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
DefVariant(_, id, _) | DefTy(id) | DefTyParam(_, id, _) |
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
id
}

View file

@ -86,12 +86,9 @@ fn check_struct_safe_for_destructor(cx: &mut Context,
span: Span,
struct_did: DefId) {
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
if !struct_tpt.generics.has_type_params() {
let struct_ty = ty::mk_struct(cx.tcx, struct_did, subst::Substs {
regions: subst::NonerasedRegions(Vec::new()),
self_ty: None,
tps: Vec::new()
});
if !struct_tpt.generics.has_type_params(subst::TypeSpace) {
let struct_ty = ty::mk_struct(cx.tcx, struct_did,
subst::Substs::empty());
if !ty::type_is_sendable(cx.tcx, struct_ty) {
cx.tcx.sess.span_err(span,
"cannot implement a destructor on a \
@ -245,51 +242,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
debug!("kind::check_expr({})", expr_to_str(e));
// Handle any kind bounds on type parameters
{
let method_map = cx.tcx.method_map.borrow();
let method = method_map.find(&typeck::MethodCall::expr(e.id));
let item_substs = cx.tcx.item_substs.borrow();
let r = match method {
Some(method) => Some(&method.substs.tps),
None => item_substs.find(&e.id).map(|s| &s.substs.tps)
};
for ts in r.iter() {
let def_map = cx.tcx.def_map.borrow();
let type_param_defs = match e.node {
ExprPath(_) => {
let did = def_map.get_copy(&e.id).def_id();
ty::lookup_item_type(cx.tcx, did).generics.type_param_defs.clone()
}
_ => {
// Type substitutions should only occur on paths and
// method calls, so this needs to be a method call.
// Even though the callee_id may have been the id with
// node_type_substs, e.id is correct here.
match method {
Some(method) => {
ty::method_call_type_param_defs(cx.tcx, method.origin)
}
None => {
cx.tcx.sess.span_bug(e.span,
"non path/method call expr has type substs??");
}
}
}
};
if ts.len() != type_param_defs.len() {
// Fail earlier to make debugging easier
fail!("internal error: in kind::check_expr, length \
mismatch between actual and declared bounds: actual = \
{}, declared = {}",
ts.repr(cx.tcx),
type_param_defs.repr(cx.tcx));
}
for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
check_typaram_bounds(cx, e.span, ty, type_param_def)
}
}
}
check_bounds_on_type_parameters(cx, e);
match e.node {
ExprUnary(UnBox, ref interior) => {
@ -331,6 +284,77 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
visit::walk_expr(cx, e, ());
}
fn check_bounds_on_type_parameters(cx: &mut Context, e: &Expr) {
let method_map = cx.tcx.method_map.borrow();
let method = method_map.find(&typeck::MethodCall::expr(e.id));
// Find the values that were provided (if any)
let item_substs = cx.tcx.item_substs.borrow();
let (types, is_object_call) = match method {
Some(method) => {
let is_object_call = match method.origin {
typeck::MethodObject(..) => true,
typeck::MethodStatic(..) | typeck::MethodParam(..) => false
};
(&method.substs.types, is_object_call)
}
None => {
match item_substs.find(&e.id) {
None => { return; }
Some(s) => { (&s.substs.types, false) }
}
}
};
// Find the relevant type parameter definitions
let def_map = cx.tcx.def_map.borrow();
let type_param_defs = match e.node {
ExprPath(_) => {
let did = def_map.get_copy(&e.id).def_id();
ty::lookup_item_type(cx.tcx, did).generics.types.clone()
}
_ => {
// Type substitutions should only occur on paths and
// method calls, so this needs to be a method call.
// Even though the callee_id may have been the id with
// node_type_substs, e.id is correct here.
match method {
Some(method) => {
ty::method_call_type_param_defs(cx.tcx, method.origin)
}
None => {
cx.tcx.sess.span_bug(e.span,
"non path/method call expr has type substs??");
}
}
}
};
// Check that the value provided for each definition meets the
// kind requirements
for type_param_def in type_param_defs.iter() {
let ty = *types.get(type_param_def.space, type_param_def.index);
// If this is a call to an object method (`foo.bar()` where
// `foo` has a type like `Trait`), then the self type is
// unknown (after all, this is a virtual call). In that case,
// we will have put a ty_err in the substitutions, and we can
// just skip over validating the bounds (because the bounds
// would have been enforced when the object instance was
// created).
if is_object_call && type_param_def.space == subst::SelfSpace {
assert_eq!(type_param_def.index, 0);
assert!(ty::type_is_error(ty));
continue;
}
debug!("type_param_def space={} index={} ty={}",
type_param_def.space, type_param_def.index, ty.repr(cx.tcx));
check_typaram_bounds(cx, e.span, ty, type_param_def)
}
}
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
match ty::get(target_ty).sty {
@ -350,12 +374,10 @@ fn check_ty(cx: &mut Context, aty: &Ty) {
let def_map = cx.tcx.def_map.borrow();
let did = def_map.get_copy(&id).def_id();
let generics = ty::lookup_item_type(cx.tcx, did).generics;
let type_param_defs = generics.type_param_defs();
for (&ty, type_param_def) in
item_substs.substs.tps.iter().zip(
type_param_defs.iter())
{
check_typaram_bounds(cx, aty.span, ty, type_param_def)
for def in generics.types.iter() {
let ty = *item_substs.substs.types.get(def.space,
def.index);
check_typaram_bounds(cx, aty.span, ty, def)
}
}
}
@ -555,7 +577,12 @@ pub fn check_cast_for_escaping_regions(
|ty| {
match ty::get(ty).sty {
ty::ty_param(source_param) => {
if target_params.iter().any(|x| x == &source_param) {
if source_param.space == subst::SelfSpace {
// FIXME (#5723) -- there is no reason that
// Self should be exempt from this check,
// except for historical accident. Bottom
// line, we need proper region bounding.
} else if target_params.iter().any(|x| x == &source_param) {
/* case (2) */
} else {
check_static(cx.tcx, ty, source_span); /* case (3) */

View file

@ -17,6 +17,7 @@ use middle::def::*;
use middle::lang_items::LanguageItems;
use middle::lint::{UnnecessaryQualification, UnusedImports};
use middle::pat_util::pat_bindings;
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use syntax::ast::*;
@ -227,22 +228,17 @@ enum FallbackSuggestion {
}
enum TypeParameters<'a> {
NoTypeParameters, //< No type parameters.
HasTypeParameters(&'a Generics, //< Type parameters.
NodeId, //< ID of the enclosing item
NoTypeParameters,
HasTypeParameters(
// Type parameters.
&'a Generics,
// The index to start numbering the type parameters at.
// This is zero if this is the outermost set of type
// parameters, or equal to the number of outer type
// parameters. For example, if we have:
//
// impl I<T> {
// fn method<U>() { ... }
// }
//
// The index at the method site will be 1, because the
// outer T had index 0.
uint,
// Identifies the things that these parameters
// were declared on (type, fn, etc)
ParamSpace,
// ID of the enclosing item.
NodeId,
// The kind of the rib used for type parameters.
RibKind)
@ -1532,8 +1528,8 @@ impl<'a> Resolver<'a> {
self.with_type_parameter_rib(
HasTypeParameters(generics,
FnSpace,
foreign_item.id,
0,
NormalRibKind),
f);
}
@ -3439,7 +3435,7 @@ impl<'a> Resolver<'a> {
// If the def is a ty param, and came from the parent
// item, it's ok
match def {
DefTyParam(did, _) if {
DefTyParam(_, did, _) if {
self.def_map.borrow().find(&did.node).map(|x| *x)
== Some(DefTyParamBinder(item_id))
} => {
@ -3574,8 +3570,8 @@ impl<'a> Resolver<'a> {
// but maybe it's okay since the first time will signal an
// error if there is one? -- tjc
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
item.id,
0,
ItemRibKind),
|this| {
visit::walk_item(this, item, ());
@ -3584,8 +3580,8 @@ impl<'a> Resolver<'a> {
ItemTy(_, ref generics) => {
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
item.id,
0,
ItemRibKind),
|this| {
visit::walk_item(this, item, ());
@ -3615,8 +3611,8 @@ impl<'a> Resolver<'a> {
// Create a new rib for the trait-wide type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
item.id,
0,
NormalRibKind),
|this| {
this.resolve_type_parameters(&generics.ty_params);
@ -3636,8 +3632,8 @@ impl<'a> Resolver<'a> {
ast::Required(ref ty_m) => {
this.with_type_parameter_rib
(HasTypeParameters(&ty_m.generics,
FnSpace,
item.id,
generics.ty_params.len(),
MethodRibKind(item.id, Required)),
|this| {
@ -3656,8 +3652,7 @@ impl<'a> Resolver<'a> {
ast::Provided(ref m) => {
this.resolve_method(MethodRibKind(item.id,
Provided(m.id)),
&**m,
generics.ty_params.len())
&**m)
}
}
}
@ -3687,7 +3682,7 @@ impl<'a> Resolver<'a> {
ForeignItemFn(_, ref generics) => {
this.with_type_parameter_rib(
HasTypeParameters(
generics, foreign_item.id, 0,
generics, FnSpace, foreign_item.id,
ItemRibKind),
|this| visit::walk_foreign_item(this,
&**foreign_item,
@ -3708,8 +3703,8 @@ impl<'a> Resolver<'a> {
Some(fn_decl),
HasTypeParameters
(generics,
FnSpace,
item.id,
0,
ItemRibKind),
block);
}
@ -3730,7 +3725,7 @@ impl<'a> Resolver<'a> {
type_parameters: TypeParameters,
f: |&mut Resolver|) {
match type_parameters {
HasTypeParameters(generics, node_id, initial_index,
HasTypeParameters(generics, space, node_id,
rib_kind) => {
let function_type_rib = Rib::new(rib_kind);
@ -3739,9 +3734,9 @@ impl<'a> Resolver<'a> {
let ident = type_parameter.ident;
debug!("with_type_parameter_rib: {} {}", node_id,
type_parameter.id);
let def_like = DlDef(DefTyParam
(local_def(type_parameter.id),
index + initial_index));
let def_like = DlDef(DefTyParam(space,
local_def(type_parameter.id),
index));
// Associate this type parameter with
// the item that bound it
self.record_def(type_parameter.id,
@ -3897,8 +3892,8 @@ impl<'a> Resolver<'a> {
fields: &[StructField]) {
// If applicable, create a rib for the type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
id,
0,
ItemRibKind),
|this| {
// Resolve the type parameters.
@ -3948,13 +3943,11 @@ impl<'a> Resolver<'a> {
// to be NormalRibKind?
fn resolve_method(&mut self,
rib_kind: RibKind,
method: &Method,
outer_type_parameter_count: uint) {
method: &Method) {
let method_generics = &method.generics;
let type_parameters =
HasTypeParameters(method_generics,
let type_parameters = HasTypeParameters(method_generics,
FnSpace,
method.id,
outer_type_parameter_count,
rib_kind);
self.resolve_function(rib_kind, Some(method.decl), type_parameters, method.body);
@ -3998,10 +3991,9 @@ impl<'a> Resolver<'a> {
self_type: &Ty,
methods: &[Gc<Method>]) {
// If applicable, create a rib for the type parameters.
let outer_type_parameter_count = generics.ty_params.len();
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
id,
0,
NormalRibKind),
|this| {
// Resolve the type parameters.
@ -4016,8 +4008,7 @@ impl<'a> Resolver<'a> {
for method in methods.iter() {
// We also need a new scope for the method-specific type parameters.
this.resolve_method(MethodRibKind(id, Provided(method.id)),
&**method,
outer_type_parameter_count);
&**method);
}
});
});

View file

@ -18,7 +18,7 @@
*/
use driver::session::Session;
use util::nodemap::NodeMap;
use middle::subst;
use syntax::ast;
use syntax::codemap::Span;
use syntax::owned_slice::OwnedSlice;
@ -27,10 +27,24 @@ use syntax::parse::token;
use syntax::print::pprust::{lifetime_to_str};
use syntax::visit;
use syntax::visit::Visitor;
use util::nodemap::NodeMap;
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
pub enum DefRegion {
DefStaticRegion,
DefEarlyBoundRegion(/* space */ subst::ParamSpace,
/* index */ uint,
/* lifetime decl */ ast::NodeId),
DefLateBoundRegion(/* binder_id */ ast::NodeId,
/* depth */ uint,
/* lifetime decl */ ast::NodeId),
DefFreeRegion(/* block scope */ ast::NodeId,
/* lifetime decl */ ast::NodeId),
}
// maps the id of each lifetime reference to the lifetime decl
// that it corresponds to
pub type NamedRegionMap = NodeMap<ast::DefRegion>;
pub type NamedRegionMap = NodeMap<DefRegion>;
// Returns an instance of some type that implements std::fmt::Show
fn lifetime_show(lt_name: &ast::Name) -> token::InternedString {
@ -45,7 +59,7 @@ struct LifetimeContext<'a> {
enum ScopeChain<'a> {
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
EarlyScope(uint, &'a Vec<ast::Lifetime>, Scope<'a>),
EarlyScope(subst::ParamSpace, &'a Vec<ast::Lifetime>, Scope<'a>),
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
/// lifetimes introduced by the declaration binder_id.
LateScope(ast::NodeId, &'a Vec<ast::Lifetime>, Scope<'a>),
@ -86,7 +100,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
ast::ItemImpl(ref generics, _, _, _) |
ast::ItemTrait(ref generics, _, _, _) => {
self.check_lifetime_names(&generics.lifetimes);
EarlyScope(0, &generics.lifetimes, &root)
EarlyScope(subst::TypeSpace, &generics.lifetimes, &root)
}
};
debug!("entering scope {:?}", scope);
@ -152,33 +166,13 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
lifetime_ref: &ast::Lifetime,
scope: Scope<'a>) {
if lifetime_ref.name == special_idents::statik.name {
self.insert_lifetime(lifetime_ref, ast::DefStaticRegion);
self.insert_lifetime(lifetime_ref, DefStaticRegion);
return;
}
self.resolve_lifetime_ref(lifetime_ref, scope);
}
}
impl<'a> ScopeChain<'a> {
fn count_early_params(&self) -> uint {
/*!
* Counts the number of early-bound parameters that are in
* scope. Used when checking methods: the early-bound
* lifetime parameters declared on the method are assigned
* indices that come after the indices from the type. Given
* something like `impl<'a> Foo { ... fn bar<'b>(...) }`
* then `'a` gets index 0 and `'b` gets index 1.
*/
match *self {
RootScope => 0,
EarlyScope(base, lifetimes, _) => base + lifetimes.len(),
LateScope(_, _, s) => s.count_early_params(),
BlockScope(_, _) => 0,
}
}
}
impl<'a> LifetimeContext<'a> {
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
fn visit_fn_decl(&mut self,
@ -212,14 +206,11 @@ impl<'a> LifetimeContext<'a> {
self.check_lifetime_names(&generics.lifetimes);
let early_count = scope.count_early_params();
let referenced_idents = free_lifetimes(&generics.ty_params);
debug!("pushing fn scope id={} due to fn item/method\
referenced_idents={:?} \
early_count={}",
referenced_idents={:?}",
n,
referenced_idents.iter().map(lifetime_show).collect::<Vec<token::InternedString>>(),
early_count);
referenced_idents.iter().map(lifetime_show).collect::<Vec<token::InternedString>>());
if referenced_idents.is_empty() {
let scope1 = LateScope(n, &generics.lifetimes, scope);
walk(self, &scope1)
@ -227,7 +218,7 @@ impl<'a> LifetimeContext<'a> {
let (early, late) = generics.lifetimes.clone().partition(
|l| referenced_idents.iter().any(|&i| i == l.name));
let scope1 = EarlyScope(early_count, &early, scope);
let scope1 = EarlyScope(subst::FnSpace, &early, scope);
let scope2 = LateScope(n, &late, &scope1);
walk(self, &scope2);
@ -256,11 +247,10 @@ impl<'a> LifetimeContext<'a> {
break;
}
EarlyScope(base, lifetimes, s) => {
EarlyScope(space, lifetimes, s) => {
match search_lifetimes(lifetimes, lifetime_ref) {
Some((offset, decl_id)) => {
let index = base + offset;
let def = ast::DefEarlyBoundRegion(index, decl_id);
Some((index, decl_id)) => {
let def = DefEarlyBoundRegion(space, index, decl_id);
self.insert_lifetime(lifetime_ref, def);
return;
}
@ -274,7 +264,7 @@ impl<'a> LifetimeContext<'a> {
LateScope(binder_id, lifetimes, s) => {
match search_lifetimes(lifetimes, lifetime_ref) {
Some((_index, decl_id)) => {
let def = ast::DefLateBoundRegion(binder_id, depth, decl_id);
let def = DefLateBoundRegion(binder_id, depth, decl_id);
self.insert_lifetime(lifetime_ref, def);
return;
}
@ -325,7 +315,7 @@ impl<'a> LifetimeContext<'a> {
match search_result {
Some((_depth, decl_id)) => {
let def = ast::DefFreeRegion(scope_id, decl_id);
let def = DefFreeRegion(scope_id, decl_id);
self.insert_lifetime(lifetime_ref, def);
}
@ -374,7 +364,7 @@ impl<'a> LifetimeContext<'a> {
fn insert_lifetime(&mut self,
lifetime_ref: &ast::Lifetime,
def: ast::DefRegion) {
def: DefRegion) {
if lifetime_ref.id == ast::DUMMY_NODE_ID {
self.sess.span_bug(lifetime_ref.span,
"lifetime reference not renumbered, \

View file

@ -231,7 +231,7 @@ impl <'l> DxrVisitor<'l> {
def::DefTyParamBinder(_) |
def::DefLabel(_) |
def::DefStaticMethod(_, _, _) |
def::DefTyParam(_, _) |
def::DefTyParam(..) |
def::DefUse(_) |
def::DefMethod(_, _) |
def::DefPrimTy(_) => {

View file

@ -15,10 +15,80 @@ use middle::ty_fold;
use middle::ty_fold::{TypeFoldable, TypeFolder};
use util::ppaux::Repr;
use std::iter::Chain;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
use std::vec::Vec;
use syntax::codemap::Span;
use syntax::codemap::{Span, DUMMY_SP};
///////////////////////////////////////////////////////////////////////////
// HomogeneousTuple3 trait
//
// This could be moved into standard library at some point.
trait HomogeneousTuple3<T> {
fn len(&self) -> uint;
fn as_slice<'a>(&'a self) -> &'a [T];
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
fn iter<'a>(&'a self) -> Items<'a, T>;
fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T>;
fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
}
impl<T> HomogeneousTuple3<T> for (T, T, T) {
fn len(&self) -> uint {
3
}
fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe {
let ptr: *T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe {
let ptr: *T = mem::transmute(self);
let slice = raw::Slice { data: ptr, len: 3 };
mem::transmute(slice)
}
}
fn iter<'a>(&'a self) -> Items<'a, T> {
let slice: &'a [T] = self.as_slice();
slice.iter()
}
fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> {
self.as_mut_slice().mut_iter()
}
fn get<'a>(&'a self, index: uint) -> Option<&'a T> {
self.as_slice().get(index)
}
fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> {
Some(&mut self.as_mut_slice()[index]) // wrong: fallible
}
}
///////////////////////////////////////////////////////////////////////////
/**
* A substitution mapping type/region parameters to new values. We
* identify each in-scope parameter by an *index* and a *parameter
* space* (which indices where the parameter is defined; see
* `ParamSpace`).
*/
#[deriving(Clone, PartialEq, Eq, Hash)]
pub struct Substs {
pub types: VecPerParamSpace<ty::t>,
pub regions: RegionSubsts,
}
/**
* Represents the values to use when substituting lifetime parameters.
@ -27,46 +97,49 @@ use syntax::codemap::Span;
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum RegionSubsts {
ErasedRegions,
NonerasedRegions(Vec<ty::Region>)
}
/**
* The type `Substs` represents the kinds of things that can be substituted to
* convert a polytype into a monotype. Note however that substituting bound
* regions other than `self` is done through a different mechanism:
*
* - `tps` represents the type parameters in scope. They are indexed
* according to the order in which they were declared.
*
* - `self_r` indicates the region parameter `self` that is present on nominal
* types (enums, structs) declared as having a region parameter. `self_r`
* should always be none for types that are not region-parameterized and
* Some(_) for types that are. The only bound region parameter that should
* appear within a region-parameterized type is `self`.
*
* - `self_ty` is the type to which `self` should be remapped, if any. The
* `self` type is rather funny in that it can only appear on traits and is
* always substituted away to the implementing type for a trait. */
#[deriving(Clone, PartialEq, Eq, Hash)]
pub struct Substs {
pub self_ty: Option<ty::t>,
pub tps: Vec<ty::t>,
pub regions: RegionSubsts,
NonerasedRegions(VecPerParamSpace<ty::Region>)
}
impl Substs {
pub fn new(t: VecPerParamSpace<ty::t>,
r: VecPerParamSpace<ty::Region>)
-> Substs
{
Substs { types: t, regions: NonerasedRegions(r) }
}
pub fn new_type(t: Vec<ty::t>,
r: Vec<ty::Region>)
-> Substs
{
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
}
pub fn new_trait(t: Vec<ty::t>,
r: Vec<ty::Region>,
s: ty::t)
-> Substs
{
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
}
pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
{
Substs { types: t, regions: ErasedRegions }
}
pub fn empty() -> Substs {
Substs {
self_ty: None,
tps: Vec::new(),
regions: NonerasedRegions(Vec::new())
types: VecPerParamSpace::empty(),
regions: NonerasedRegions(VecPerParamSpace::empty()),
}
}
pub fn trans_empty() -> Substs {
Substs {
self_ty: None,
tps: Vec::new(),
types: VecPerParamSpace::empty(),
regions: ErasedRegions
}
}
@ -74,16 +147,251 @@ impl Substs {
pub fn is_noop(&self) -> bool {
let regions_is_noop = match self.regions {
ErasedRegions => false, // may be used to canonicalize
NonerasedRegions(ref regions) => regions.is_empty()
NonerasedRegions(ref regions) => regions.is_empty(),
};
self.tps.len() == 0u &&
regions_is_noop &&
self.self_ty.is_none()
regions_is_noop && self.types.is_empty()
}
pub fn self_ty(&self) -> ty::t {
self.self_ty.unwrap()
pub fn self_ty(&self) -> Option<ty::t> {
self.types.get_self().map(|&t| t)
}
pub fn with_self_ty(&self, self_ty: ty::t) -> Substs {
assert!(self.self_ty().is_none());
let mut s = (*self).clone();
s.types.push(SelfSpace, self_ty);
s
}
pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace<ty::Region> {
/*!
* Since ErasedRegions are only to be used in trans, most of
* the compiler can use this method to easily access the set
* of region substitutions.
*/
match self.regions {
ErasedRegions => fail!("Erased regions only expected in trans"),
NonerasedRegions(ref r) => r
}
}
pub fn mut_regions<'a>(&'a mut self) -> &'a mut VecPerParamSpace<ty::Region> {
/*!
* Since ErasedRegions are only to be used in trans, most of
* the compiler can use this method to easily access the set
* of region substitutions.
*/
match self.regions {
ErasedRegions => fail!("Erased regions only expected in trans"),
NonerasedRegions(ref mut r) => r
}
}
pub fn with_method_from(self, substs: &Substs) -> Substs {
self.with_method((*substs.types.get_vec(FnSpace)).clone(),
(*substs.regions().get_vec(FnSpace)).clone())
}
pub fn with_method(self,
m_types: Vec<ty::t>,
m_regions: Vec<ty::Region>)
-> Substs
{
let Substs { types, regions } = self;
let types = types.with_vec(FnSpace, m_types);
let regions = regions.map(m_regions,
|r, m_regions| r.with_vec(FnSpace, m_regions));
Substs { types: types, regions: regions }
}
}
impl RegionSubsts {
fn map<A>(self,
a: A,
op: |VecPerParamSpace<ty::Region>, A| -> VecPerParamSpace<ty::Region>)
-> RegionSubsts {
match self {
ErasedRegions => ErasedRegions,
NonerasedRegions(r) => NonerasedRegions(op(r, a))
}
}
}
///////////////////////////////////////////////////////////////////////////
// ParamSpace
#[deriving(PartialOrd, Ord, PartialEq, Eq,
Clone, Hash, Encodable, Decodable, Show)]
pub enum ParamSpace {
TypeSpace, // Type parameters attached to a type definition, trait, or impl
SelfSpace, // Self parameter on a trait
FnSpace, // Type parameters attached to a method or fn
}
impl ParamSpace {
pub fn all() -> [ParamSpace, ..3] {
[TypeSpace, SelfSpace, FnSpace]
}
pub fn to_uint(self) -> uint {
match self {
TypeSpace => 0,
SelfSpace => 1,
FnSpace => 2,
}
}
pub fn from_uint(u: uint) -> ParamSpace {
match u {
0 => TypeSpace,
1 => SelfSpace,
2 => FnSpace,
_ => fail!("Invalid ParamSpace: {}", u)
}
}
}
/**
* Vector of things sorted by param space. Used to keep
* the set of things declared on the type, self, or method
* distinct.
*/
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
pub struct VecPerParamSpace<T> {
vecs: (Vec<T>, Vec<T>, Vec<T>)
}
impl<T> VecPerParamSpace<T> {
pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace {
vecs: (Vec::new(), Vec::new(), Vec::new())
}
}
pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
VecPerParamSpace::empty().with_vec(TypeSpace, types)
}
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
VecPerParamSpace {
vecs: (t, s, f)
}
}
pub fn sort(t: Vec<T>, space: |&T| -> ParamSpace) -> VecPerParamSpace<T> {
let mut result = VecPerParamSpace::empty();
for t in t.move_iter() {
result.push(space(&t), t);
}
result
}
pub fn push(&mut self, space: ParamSpace, value: T) {
self.get_mut_vec(space).push(value);
}
pub fn get_self<'a>(&'a self) -> Option<&'a T> {
let v = self.get_vec(SelfSpace);
assert!(v.len() <= 1);
if v.len() == 0 { None } else { Some(v.get(0)) }
}
pub fn len(&self, space: ParamSpace) -> uint {
self.get_vec(space).len()
}
pub fn get_vec<'a>(&'a self, space: ParamSpace) -> &'a Vec<T> {
self.vecs.get(space as uint).unwrap()
}
pub fn get_mut_vec<'a>(&'a mut self, space: ParamSpace) -> &'a mut Vec<T> {
self.vecs.get_mut(space as uint).unwrap()
}
pub fn opt_get<'a>(&'a self,
space: ParamSpace,
index: uint)
-> Option<&'a T> {
let v = self.get_vec(space);
if index < v.len() { Some(v.get(index)) } else { None }
}
pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
self.get_vec(space).get(index)
}
pub fn get_mut<'a>(&'a mut self,
space: ParamSpace,
index: uint) -> &'a mut T {
self.get_mut_vec(space).get_mut(index)
}
pub fn iter<'a>(&'a self) -> Chain<Items<'a,T>,
Chain<Items<'a,T>,
Items<'a,T>>> {
let (ref r, ref s, ref f) = self.vecs;
r.iter().chain(s.iter().chain(f.iter()))
}
pub fn all_vecs(&self, pred: |&Vec<T>| -> bool) -> bool {
self.vecs.iter().all(pred)
}
pub fn all(&self, pred: |&T| -> bool) -> bool {
self.iter().all(pred)
}
pub fn any(&self, pred: |&T| -> bool) -> bool {
self.iter().any(pred)
}
pub fn is_empty(&self) -> bool {
self.all_vecs(|v| v.is_empty())
}
pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
VecPerParamSpace::new(self.vecs.ref0().iter().map(|p| pred(p)).collect(),
self.vecs.ref1().iter().map(|p| pred(p)).collect(),
self.vecs.ref2().iter().map(|p| pred(p)).collect())
}
pub fn map_rev<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
/*!
* Executes the map but in reverse order. For hacky reasons, we rely
* on this in table.
*
* FIXME(#5527) -- order of eval becomes irrelevant with newer
* trait reform, which features an idempotent algorithm that
* can be run to a fixed point
*/
let mut fns: Vec<U> = self.vecs.ref2().iter().rev().map(|p| pred(p)).collect();
// NB: Calling foo.rev().map().rev() causes the calls to map
// to occur in the wrong order. This was somewhat surprising
// to me, though it makes total sense.
fns.reverse();
let mut selfs: Vec<U> = self.vecs.ref1().iter().rev().map(|p| pred(p)).collect();
selfs.reverse();
let mut tys: Vec<U> = self.vecs.ref0().iter().rev().map(|p| pred(p)).collect();
tys.reverse();
VecPerParamSpace::new(tys, selfs, fns)
}
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
self.vecs
}
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
-> VecPerParamSpace<T>
{
assert!(self.get_vec(space).is_empty());
*self.get_mut_vec(space) = vec;
self
}
}
@ -149,10 +457,10 @@ impl<'a> TypeFolder for SubstFolder<'a> {
// the specialized routine
// `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
match r {
ty::ReEarlyBound(_, i, _) => {
ty::ReEarlyBound(_, space, i, _) => {
match self.substs.regions {
ErasedRegions => ty::ReStatic,
NonerasedRegions(ref regions) => *regions.get(i),
NonerasedRegions(ref regions) => *regions.get(space, i),
}
}
_ => r
@ -173,52 +481,11 @@ impl<'a> TypeFolder for SubstFolder<'a> {
let t1 = match ty::get(t).sty {
ty::ty_param(p) => {
// FIXME -- This...really shouldn't happen. We should
// never be substituting without knowing what's in
// scope and knowing that the indices will line up!
if p.idx < self.substs.tps.len() {
*self.substs.tps.get(p.idx)
} else {
let root_msg = match self.root_ty {
Some(root) => format!(" in the substitution of `{}`",
root.repr(self.tcx)),
None => "".to_string()
};
let m = format!("can't use type parameters from outer \
function{}; try using a local type \
parameter instead",
root_msg);
match self.span {
Some(span) => {
self.tcx.sess.span_err(span, m.as_slice())
check(self, t, self.substs.types.opt_get(p.space, p.idx))
}
None => self.tcx.sess.err(m.as_slice())
_ => {
ty_fold::super_fold_ty(self, t)
}
ty::mk_err()
}
}
ty::ty_self(_) => {
match self.substs.self_ty {
Some(ty) => ty,
None => {
let root_msg = match self.root_ty {
Some(root) => format!(" in the substitution of `{}`",
root.repr(self.tcx)),
None => "".to_string()
};
let m = format!("missing `Self` type param{}",
root_msg);
match self.span {
Some(span) => {
self.tcx.sess.span_err(span, m.as_slice())
}
None => self.tcx.sess.err(m.as_slice())
}
ty::mk_err()
}
}
}
_ => ty_fold::super_fold_ty(self, t)
};
assert_eq!(depth + 1, self.ty_stack_depth);
@ -227,6 +494,24 @@ impl<'a> TypeFolder for SubstFolder<'a> {
self.root_ty = None;
}
t1
return t1;
fn check(this: &SubstFolder,
source_ty: ty::t,
opt_ty: Option<&ty::t>)
-> ty::t {
match opt_ty {
Some(t) => *t,
None => {
let span = this.span.unwrap_or(DUMMY_SP);
this.tcx().sess.span_bug(
span,
format!("Type parameter {} out of range \
when substituting (root type={})",
source_ty.repr(this.tcx()),
this.root_ty.repr(this.tcx())).as_slice());
}
}
}
}
}

View file

@ -457,11 +457,11 @@ pub fn get_res_dtor(ccx: &CrateContext,
did
};
if !substs.tps.is_empty() || !substs.self_ty.is_none() {
if !substs.types.is_empty() {
assert_eq!(did.krate, ast::LOCAL_CRATE);
let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, substs);
let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None, None);
let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None);
val
} else if did.krate == ast::LOCAL_CRATE {

View file

@ -23,7 +23,7 @@ use lib::llvm::llvm;
use metadata::csearch;
use middle::def;
use middle::subst;
use middle::subst::Subst;
use middle::subst::{Subst, VecPerParamSpace};
use middle::trans::base;
use middle::trans::base::*;
use middle::trans::build::*;
@ -198,12 +198,10 @@ fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
fn resolve_default_method_vtables(bcx: &Block,
impl_id: ast::DefId,
method: &ty::Method,
substs: &subst::Substs,
impl_vtables: typeck::vtable_res)
-> (typeck::vtable_res, typeck::vtable_param_res)
-> typeck::vtable_res
{
// Get the vtables that the impl implements the trait at
let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
@ -211,22 +209,19 @@ fn resolve_default_method_vtables(bcx: &Block,
// trait_vtables under.
let param_substs = param_substs {
substs: (*substs).clone(),
vtables: impl_vtables.clone(),
self_vtables: None
vtables: impl_vtables.clone()
};
let mut param_vtables = resolve_vtables_under_param_substs(
bcx.tcx(), &param_substs, impl_res.trait_vtables.as_slice());
bcx.tcx(), &param_substs, &impl_res);
// Now we pull any vtables for parameters on the actual method.
let num_method_vtables = method.generics.type_param_defs().len();
let num_impl_type_parameters = impl_vtables.len() - num_method_vtables;
param_vtables.push_all(impl_vtables.tailn(num_impl_type_parameters));
param_vtables
.get_mut_vec(subst::FnSpace)
.push_all(
impl_vtables.get_vec(subst::FnSpace).as_slice());
let self_vtables = resolve_param_vtables_under_param_substs(
bcx.tcx(), &param_substs, impl_res.self_vtables.as_slice());
(param_vtables, self_vtables)
param_vtables
}
@ -236,7 +231,8 @@ pub fn trans_fn_ref_with_vtables(
node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A
substs: subst::Substs, // values for fn's ty params
vtables: typeck::vtable_res) // vtables for the call
-> ValueRef {
-> ValueRef
{
/*!
* Translates a reference to a fn/method item, monomorphizing and
* inlining as it goes.
@ -264,7 +260,7 @@ pub fn trans_fn_ref_with_vtables(
substs.repr(tcx),
vtables.repr(tcx));
assert!(substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
// Polytype of the function item (may have type params)
let fn_tpt = ty::lookup_item_type(tcx, def_id);
@ -280,9 +276,9 @@ pub fn trans_fn_ref_with_vtables(
// We need to do a bunch of special handling for default methods.
// We need to modify the def_id and our substs in order to monomorphize
// the function.
let (is_default, def_id, substs, self_vtables, vtables) =
let (is_default, def_id, substs, vtables) =
match ty::provided_source(tcx, def_id) {
None => (false, def_id, substs, None, vtables),
None => (false, def_id, substs, vtables),
Some(source_id) => {
// There are two relevant substitutions when compiling
// default methods. First, there is the substitution for
@ -305,7 +301,7 @@ pub fn trans_fn_ref_with_vtables(
// Compute the first substitution
let first_subst = make_substs_for_receiver_types(
tcx, impl_id, &*trait_ref, &*method);
tcx, &*trait_ref, &*method);
// And compose them
let new_substs = first_subst.subst(tcx, &substs);
@ -318,16 +314,14 @@ pub fn trans_fn_ref_with_vtables(
first_subst.repr(tcx), new_substs.repr(tcx),
vtables.repr(tcx));
let (param_vtables, self_vtables) =
resolve_default_method_vtables(bcx, impl_id,
&*method, &substs, vtables);
let param_vtables =
resolve_default_method_vtables(bcx, impl_id, &substs, vtables);
debug!("trans_fn_with_vtables - default method: \
self_vtable = {}, param_vtables = {}",
self_vtables.repr(tcx), param_vtables.repr(tcx));
param_vtables = {}",
param_vtables.repr(tcx));
(true, source_id,
new_substs, Some(self_vtables), param_vtables)
(true, source_id, new_substs, param_vtables)
}
};
@ -345,7 +339,7 @@ pub fn trans_fn_ref_with_vtables(
// intrinsic, or is a default method. In particular, if we see an
// intrinsic that is inlined from a different crate, we want to reemit the
// intrinsic instead of trying to call it in the other crate.
let must_monomorphise = if substs.tps.len() > 0 || is_default {
let must_monomorphise = if !substs.types.is_empty() || is_default {
true
} else if def_id.krate == ast::LOCAL_CRATE {
let map_node = session::expect(
@ -375,8 +369,7 @@ pub fn trans_fn_ref_with_vtables(
let (val, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs,
vtables, self_vtables,
opt_ref_id);
vtables, opt_ref_id);
let mut val = val;
if must_cast && node != ExprId(0) {
// Monotype of the REFERENCE to the function (type params
@ -498,7 +491,7 @@ pub fn trans_lang_call<'a>(
did,
0,
subst::Substs::empty(),
Vec::new())
VecPerParamSpace::empty())
},
ArgVals(args),
dest)

View file

@ -181,25 +181,18 @@ pub type ExternMap = HashMap<String, ValueRef>;
pub struct param_substs {
pub substs: subst::Substs,
pub vtables: typeck::vtable_res,
pub self_vtables: Option<typeck::vtable_param_res>
}
impl param_substs {
pub fn empty() -> param_substs {
param_substs {
substs: subst::Substs::trans_empty(),
vtables: Vec::new(),
self_vtables: None
vtables: subst::VecPerParamSpace::empty(),
}
}
pub fn validate(&self) {
for t in self.substs.tps.iter() {
assert!(!ty::type_needs_infer(*t));
}
for t in self.substs.self_ty.iter() {
assert!(!ty::type_needs_infer(*t));
}
assert!(self.substs.types.all(|t| !ty::type_needs_infer(*t)));
}
}
@ -738,7 +731,7 @@ pub fn node_id_substs(bcx: &Block,
}
};
if !substs.tps.iter().all(|t| !ty::type_needs_infer(*t)) {
if substs.types.any(|t| ty::type_needs_infer(*t)) {
bcx.sess().bug(
format!("type parameters for node {:?} include inference types: \
{}",
@ -752,14 +745,14 @@ pub fn node_id_substs(bcx: &Block,
pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
-> typeck::vtable_res {
bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
}).unwrap_or_else(|| Vec::new())
resolve_vtables_in_fn_ctxt(bcx.fcx, vts)
}).unwrap_or_else(|| subst::VecPerParamSpace::empty())
}
// Apply the typaram substitutions in the FunctionContext to some
// vtables. This should eliminate any vtable_params.
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
vts: &[typeck::vtable_param_res])
vts: &typeck::vtable_res)
-> typeck::vtable_res {
resolve_vtables_under_param_substs(fcx.ccx.tcx(),
fcx.param_substs,
@ -768,20 +761,21 @@ pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
vts: &[typeck::vtable_param_res])
-> typeck::vtable_res {
vts.iter().map(|ds| {
vts: &typeck::vtable_res)
-> typeck::vtable_res
{
vts.map(|ds| {
resolve_param_vtables_under_param_substs(tcx,
param_substs,
ds.as_slice())
}).collect()
ds)
})
}
pub fn resolve_param_vtables_under_param_substs(
tcx: &ty::ctxt,
pub fn resolve_param_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
ds: &[typeck::vtable_origin])
-> typeck::vtable_param_res {
ds: &typeck::vtable_param_res)
-> typeck::vtable_param_res
{
ds.iter().map(|d| {
resolve_vtable_under_param_substs(tcx,
param_substs,
@ -794,17 +788,20 @@ pub fn resolve_param_vtables_under_param_substs(
pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
vt: &typeck::vtable_origin)
-> typeck::vtable_origin {
-> typeck::vtable_origin
{
match *vt {
typeck::vtable_static(trait_id, ref vtable_substs, ref sub) => {
let vtable_substs = vtable_substs.substp(tcx, param_substs);
typeck::vtable_static(
trait_id, vtable_substs,
resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
trait_id,
vtable_substs,
resolve_vtables_under_param_substs(tcx, param_substs, sub))
}
typeck::vtable_param(n_param, n_bound) => {
find_vtable(tcx, param_substs, n_param, n_bound)
}
typeck::vtable_error => typeck::vtable_error
}
}
@ -816,12 +813,8 @@ pub fn find_vtable(tcx: &ty::ctxt,
debug!("find_vtable(n_param={:?}, n_bound={}, ps={})",
n_param, n_bound, ps.repr(tcx));
let param_bounds = match n_param {
typeck::param_self => ps.self_vtables.as_ref().expect("self vtables missing"),
typeck::param_numbered(n) => {
ps.vtables.get(n)
}
};
let param_bounds = ps.vtables.get(n_param.space,
n_param.index);
param_bounds.get(n_bound).clone()
}

View file

@ -520,10 +520,11 @@ impl TypeMap {
// Maybe check that there is no self type here
if substs.tps.len() > 0 {
let tps = substs.types.get_vec(subst::TypeSpace);
if tps.len() > 0 {
output.push_char('<');
for &type_parameter in substs.tps.iter() {
for &type_parameter in tps.iter() {
let param_type_id = type_map.get_unique_type_id_of_type(cx, type_parameter);
let param_type_id = type_map.get_unique_type_id_as_string(param_type_id);
output.push_str(param_type_id.as_slice());
@ -1209,7 +1210,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
file_metadata: DIFile,
name_to_append_suffix_to: &mut String)
-> DIArray {
let self_type = param_substs.substs.self_ty;
let self_type = param_substs.substs.self_ty();
// Only true for static default methods:
let has_self_type = self_type.is_some();
@ -1263,7 +1264,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
}
// Handle other generic parameters
let actual_types = &param_substs.substs.tps;
let actual_types = param_substs.substs.types.get_vec(subst::FnSpace);
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
let actual_type = *actual_types.get(index);
// Add actual type name to <...> clause of function name
@ -2733,13 +2734,11 @@ fn trait_metadata(cx: &CrateContext,
let ident_string = token::get_name(last.name());
let mut name = ppaux::trait_store_to_str(cx.tcx(), trait_store);
name.push_str(ident_string.get());
// Add type and region parameters
let name = ppaux::parameterized(cx.tcx(),
name.as_slice(),
&substs.regions,
substs.tps.as_slice(),
def_id,
true);
let trait_def = ty::lookup_trait_def(cx.tcx(), def_id);
let name = ppaux::parameterized(cx.tcx(), name.as_slice(),
substs, &trait_def.generics);
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);

View file

@ -125,11 +125,11 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
if is_provided { return local_def(mth.id); }
let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
let num_type_params =
impl_tpt.generics.type_param_defs().len() +
mth.generics.ty_params.len();
let unparameterized =
impl_tpt.generics.types.is_empty() &&
mth.generics.ty_params.is_empty();
if num_type_params == 0 {
if unparameterized {
let llfn = get_item_val(ccx, mth.id);
trans_fn(ccx, &*mth.decl, &*mth.body, llfn,
&param_substs::empty(), mth.id, []);

View file

@ -14,6 +14,7 @@ use arena::TypedArena;
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
use lib::llvm::{ValueRef, Pointer, Array, Struct};
use lib;
use middle::subst::FnSpace;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
@ -295,7 +296,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
RetVoid(bcx);
}
"size_of" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty) as uint));
}
@ -305,7 +306,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
// if the value is non-immediate. Note that, with
// intrinsics, there are no argument cleanups to
// concern ourselves with, so we can use an rvalue datum.
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let mode = appropriate_rvalue_mode(ccx, tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty,
@ -314,17 +315,17 @@ pub fn trans_intrinsic(ccx: &CrateContext,
RetVoid(bcx);
}
"min_align_of" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty) as uint));
}
"pref_align_of"=> {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty) as uint));
}
"get_tydesc" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let static_ti = get_tydesc(ccx, tp_ty);
glue::lazily_emit_visit_glue(ccx, &*static_ti);
@ -339,7 +340,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
"type_id" => {
let hash = ty::hash_crate_independent(
ccx.tcx(),
*substs.substs.tps.get(0),
*substs.substs.types.get(FnSpace, 0),
&ccx.link_meta.crate_hash);
// NB: This needs to be kept in lockstep with the TypeId struct in
// libstd/unstable/intrinsics.rs
@ -354,7 +355,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
}
}
"init" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
match bcx.fcx.llretptr.get() {
Some(ptr) => { Store(bcx, C_null(lltp_ty), ptr); RetVoid(bcx); }
@ -364,7 +365,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
}
"uninit" => {
// Do nothing, this is effectively a no-op
let retty = *substs.substs.tps.get(0);
let retty = *substs.substs.types.get(FnSpace, 0);
if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) {
unsafe {
Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
@ -377,8 +378,8 @@ pub fn trans_intrinsic(ccx: &CrateContext,
RetVoid(bcx);
}
"transmute" => {
let (in_type, out_type) = (*substs.substs.tps.get(0),
*substs.substs.tps.get(1));
let (in_type, out_type) = (*substs.substs.types.get(FnSpace, 0),
*substs.substs.types.get(FnSpace, 1));
let llintype = type_of::type_of(ccx, in_type);
let llouttype = type_of::type_of(ccx, out_type);
@ -447,11 +448,11 @@ pub fn trans_intrinsic(ccx: &CrateContext,
}
}
"needs_drop" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
Ret(bcx, C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)));
}
"owns_managed" => {
let tp_ty = *substs.substs.tps.get(0);
let tp_ty = *substs.substs.types.get(FnSpace, 0);
Ret(bcx, C_bool(ccx, ty::type_contents(ccx.tcx(), tp_ty).owns_managed()));
}
"visit_tydesc" => {
@ -468,19 +469,26 @@ pub fn trans_intrinsic(ccx: &CrateContext,
Ret(bcx, lladdr);
}
"copy_nonoverlapping_memory" => {
copy_intrinsic(bcx, false, false, *substs.substs.tps.get(0))
copy_intrinsic(bcx, false, false, *substs.substs.types.get(FnSpace, 0))
}
"copy_memory" => {
copy_intrinsic(bcx, true, false, *substs.substs.tps.get(0))
copy_intrinsic(bcx, true, false, *substs.substs.types.get(FnSpace, 0))
}
"set_memory" => {
memset_intrinsic(bcx, false, *substs.substs.tps.get(0))
memset_intrinsic(bcx, false, *substs.substs.types.get(FnSpace, 0))
}
"volatile_copy_nonoverlapping_memory" =>
copy_intrinsic(bcx, false, true, *substs.substs.tps.get(0)),
"volatile_copy_memory" => copy_intrinsic(bcx, true, true, *substs.substs.tps.get(0)),
"volatile_set_memory" => memset_intrinsic(bcx, true, *substs.substs.tps.get(0)),
"volatile_copy_nonoverlapping_memory" => {
copy_intrinsic(bcx, false, true, *substs.substs.types.get(FnSpace, 0))
}
"volatile_copy_memory" => {
copy_intrinsic(bcx, true, true, *substs.substs.types.get(FnSpace, 0))
}
"volatile_set_memory" => {
memset_intrinsic(bcx, true, *substs.substs.types.get(FnSpace, 0))
}
"ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"),
"ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"),

View file

@ -155,22 +155,6 @@ pub fn trans_static_method_callee(bcx: &Block,
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
// When we translate a static fn defined in a trait like:
//
// trait<T1...Tn> Trait {
// fn foo<M1...Mn>(...) {...}
// }
//
// this winds up being translated as something like:
//
// fn foo<T1...Tn,self: Trait<T1...Tn>,M1...Mn>(...) {...}
//
// So when we see a call to this function foo, we have to figure
// out which impl the `Trait<T1...Tn>` bound on the type `self` was
// bound to.
let bound_index = ty::lookup_trait_def(bcx.tcx(), trait_id).
generics.type_param_defs().len();
let mname = if method_id.krate == ast::LOCAL_CRATE {
match bcx.tcx().map.get(method_id.node) {
ast_map::NodeTraitMethod(method) => {
@ -189,18 +173,19 @@ pub fn trans_static_method_callee(bcx: &Block,
name={}", method_id, expr_id, token::get_name(mname));
let vtable_key = MethodCall::expr(expr_id);
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, ccx.tcx.vtable_map.borrow()
.get(&vtable_key).as_slice());
let vtbls = resolve_vtables_in_fn_ctxt(
bcx.fcx,
ccx.tcx.vtable_map.borrow().get(&vtable_key));
match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
assert!(rcvr_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
match *vtbls.get_self().unwrap().get(0) {
typeck::vtable_static(impl_did, ref rcvr_substs, ref rcvr_origins) => {
assert!(rcvr_substs.types.all(|t| !ty::type_needs_infer(*t)));
let mth_id = method_with_name(ccx, impl_did, mname);
let (callee_substs, callee_origins) =
combine_impl_and_methods_tps(
bcx, mth_id, ExprId(expr_id),
rcvr_substs, rcvr_origins);
bcx, ExprId(expr_id),
(*rcvr_substs).clone(), (*rcvr_origins).clone());
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id),
callee_substs,
@ -252,8 +237,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
// those from the impl and those from the method:
let (callee_substs, callee_origins) =
combine_impl_and_methods_tps(
bcx, mth_id, MethodCall(method_call),
rcvr_substs, rcvr_origins);
bcx, MethodCall(method_call), rcvr_substs, rcvr_origins);
// translate the function
let llfn = trans_fn_ref_with_vtables(bcx,
@ -265,13 +249,17 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
Callee { bcx: bcx, data: Fn(llfn) }
}
typeck::vtable_param(..) => {
fail!("vtable_param left in monomorphized function's vtable substs");
bcx.tcx().sess.bug(
"vtable_param left in monomorphized function's vtable substs");
}
typeck::vtable_error => {
bcx.tcx().sess.bug(
"vtable_error left in monomorphized function's vtable substs");
}
}
}
fn combine_impl_and_methods_tps(bcx: &Block,
mth_did: ast::DefId,
node: ExprOrMethodCall,
rcvr_substs: subst::Substs,
rcvr_origins: typeck::vtable_res)
@ -295,38 +283,33 @@ fn combine_impl_and_methods_tps(bcx: &Block,
*/
let ccx = bcx.ccx();
let method = ty::method(ccx.tcx(), mth_did);
let n_m_tps = method.generics.type_param_defs().len();
let node_substs = node_id_substs(bcx, node);
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
let rcvr_self_ty = rcvr_substs.self_ty;
let mut tps = rcvr_substs.tps;
{
let start = node_substs.tps.len() - n_m_tps;
tps.extend(node_substs.tps.move_iter().skip(start));
}
debug!("n_m_tps={:?}", n_m_tps);
debug!("tps={}", tps.repr(ccx.tcx()));
// Now, do the same work for the vtables. The vtables might not
// exist, in which case we need to make them.
let vtable_key = match node {
ExprId(id) => MethodCall::expr(id),
MethodCall(method_call) => method_call
};
let mut vtables = rcvr_origins;
let vt = node_vtables(bcx, vtable_key);
let start = vt.len() - n_m_tps;
vtables.extend(vt.move_iter().skip(start));
let node_substs = node_id_substs(bcx, node);
let node_vtables = node_vtables(bcx, vtable_key);
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
// Break apart the type parameters from the node and type
// parameters from the receiver.
let (_, _, node_method) = node_substs.types.split();
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.clone().split();
assert!(rcvr_method.is_empty());
let ty_substs = subst::Substs {
tps: tps,
regions: subst::ErasedRegions,
self_ty: rcvr_self_ty
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
};
// Now do the same work for the vtables.
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_origins.split();
let (_, _, node_method) = node_vtables.split();
assert!(rcvr_method.is_empty());
let vtables = subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method);
(ty_substs, vtables)
}
@ -426,7 +409,12 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
fn get_vtable(bcx: &Block,
self_ty: ty::t,
origins: typeck::vtable_param_res)
-> ValueRef {
-> ValueRef
{
debug!("get_vtable(self_ty={}, origins={})",
self_ty.repr(bcx.tcx()),
origins.repr(bcx.tcx()));
let ccx = bcx.ccx();
let _icx = push_ctxt("meth::get_vtable");
@ -503,8 +491,9 @@ fn emit_vtable_methods(bcx: &Block,
debug!("(making impl vtable) emitting method {} at subst {}",
m.repr(tcx),
substs.repr(tcx));
if m.generics.has_type_params() ||
ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
if m.generics.has_type_params(subst::FnSpace) ||
ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone()))
{
debug!("(making impl vtable) method has self or type params: {}",
token::get_ident(ident));
C_null(Type::nil(ccx).ptr_to())
@ -551,7 +540,7 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
let vtable_map = ccx.tcx.vtable_map.borrow();
resolve_param_vtables_under_param_substs(ccx.tcx(),
bcx.fcx.param_substs,
vtable_map.get(&MethodCall::expr(id)).get(0).as_slice())
vtable_map.get(&MethodCall::expr(id)).get_self().unwrap())
};
let vtable = get_vtable(bcx, v_ty, origins);
let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);

View file

@ -33,32 +33,27 @@ pub fn monomorphic_fn(ccx: &CrateContext,
fn_id: ast::DefId,
real_substs: &subst::Substs,
vtables: typeck::vtable_res,
self_vtables: Option<typeck::vtable_param_res>,
ref_id: Option<ast::NodeId>)
-> (ValueRef, bool) {
debug!("monomorphic_fn(\
fn_id={}, \
real_substs={}, \
vtables={}, \
self_vtable={}, \
ref_id={:?})",
fn_id.repr(ccx.tcx()),
real_substs.repr(ccx.tcx()),
vtables.repr(ccx.tcx()),
self_vtables.repr(ccx.tcx()),
ref_id);
assert!(real_substs.tps.iter().all(|t| {
assert!(real_substs.types.all(|t| {
!ty::type_needs_infer(*t) && !ty::type_has_params(*t)
}));
let _icx = push_ctxt("monomorphic_fn");
let substs_iter = real_substs.self_ty.iter().chain(real_substs.tps.iter());
let param_ids: Vec<ty::t> = substs_iter.map(|t| *t).collect();
let hash_id = MonoId {
def: fn_id,
params: param_ids
params: real_substs.types.clone()
};
match ccx.monomorphized.borrow().find(&hash_id) {
@ -73,7 +68,6 @@ pub fn monomorphic_fn(ccx: &CrateContext,
let psubsts = param_substs {
substs: (*real_substs).clone(),
vtables: vtables,
self_vtables: self_vtables
};
debug!("monomorphic_fn(\
@ -87,10 +81,6 @@ pub fn monomorphic_fn(ccx: &CrateContext,
let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
let llitem_ty = tpt.ty;
// We need to do special handling of the substitutions if we are
// calling a static provided method. This is sort of unfortunate.
let mut is_static_provided = None;
let map_node = session::expect(
ccx.sess(),
ccx.tcx.map.find(fn_id.node),
@ -108,55 +98,11 @@ pub fn monomorphic_fn(ccx: &CrateContext,
return (get_item_val(ccx, fn_id.node), true);
}
}
ast_map::NodeTraitMethod(method) => {
match *method {
ast::Provided(m) => {
// If this is a static provided method, indicate that
// and stash the number of params on the method.
if m.explicit_self.node == ast::SelfStatic {
is_static_provided = Some(m.generics.ty_params.len());
}
}
_ => {}
}
}
_ => {}
}
debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
let mono_ty = match is_static_provided {
None => llitem_ty.subst(ccx.tcx(), real_substs),
Some(num_method_ty_params) => {
// Static default methods are a little unfortunate, in
// that the "internal" and "external" type of them differ.
// Internally, the method body can refer to Self, but the
// externally visible type of the method has a type param
// inserted in between the trait type params and the
// method type params. The substs that we are given are
// the proper substs *internally* to the method body, so
// we have to use those when compiling it.
//
// In order to get the proper substitution to use on the
// type of the method, we pull apart the substitution and
// stick a substitution for the self type in.
// This is a bit unfortunate.
let idx = real_substs.tps.len() - num_method_ty_params;
let mut tps = Vec::new();
tps.push_all(real_substs.tps.slice(0, idx));
tps.push(real_substs.self_ty.unwrap());
tps.push_all(real_substs.tps.tailn(idx));
let substs = subst::Substs { regions: subst::ErasedRegions,
self_ty: None,
tps: tps };
debug!("static default: changed substitution to {}",
substs.repr(ccx.tcx()));
llitem_ty.subst(ccx.tcx(), &substs)
}
};
let mono_ty = llitem_ty.subst(ccx.tcx(), real_substs);
ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1);
@ -306,7 +252,7 @@ pub struct MonoParamId {
#[deriving(PartialEq, Eq, Hash)]
pub struct MonoId {
pub def: ast::DefId,
pub params: Vec<ty::t>
pub params: subst::VecPerParamSpace<ty::t>
}
pub fn make_vtable_id(_ccx: &CrateContext,
@ -316,7 +262,7 @@ pub fn make_vtable_id(_ccx: &CrateContext,
&typeck::vtable_static(impl_id, ref substs, _) => {
MonoId {
def: impl_id,
params: substs.tps.iter().map(|subst| *subst).collect()
params: substs.types.clone()
}
}

View file

@ -366,7 +366,6 @@ impl<'a, 'b> Reflector<'a, 'b> {
let extra = vec!(self.c_uint(p.idx));
self.visit("param", extra.as_slice())
}
ty::ty_self(..) => self.leaf("self")
}
}

View file

@ -15,7 +15,6 @@ use middle::trans::adt;
use middle::trans::common::*;
use middle::trans::foreign;
use middle::ty;
use util::ppaux;
use util::ppaux::Repr;
use middle::trans::type_::Type;
@ -152,7 +151,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
}
}
ty::ty_self(_) | ty::ty_infer(..) | ty::ty_param(..) |
ty::ty_infer(..) | ty::ty_param(..) |
ty::ty_err(..) | ty::ty_vec(_, None) | ty::ty_str => {
cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
ty::get(t).sty).as_slice())
@ -205,7 +204,8 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let name = llvm_type_name(cx, an_enum, did, substs.tps.as_slice());
let tps = substs.types.get_vec(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
ty::ty_box(typ) => {
@ -260,17 +260,14 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
let name = llvm_type_name(cx,
a_struct,
did,
substs.tps.as_slice());
let tps = substs.types.get_vec(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
}
ty::ty_vec(_, None) => cx.sess().bug("type_of with unsized ty_vec"),
ty::ty_str => cx.sess().bug("type_of with unsized (bare) ty_str"),
ty::ty_self(..) => cx.sess().unimpl("type_of with ty_self"),
ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
ty::ty_err(..) => cx.sess().bug("type_of with ty_err")
@ -301,19 +298,17 @@ pub enum named_ty { a_struct, an_enum }
pub fn llvm_type_name(cx: &CrateContext,
what: named_ty,
did: ast::DefId,
tps: &[ty::t])
-> String {
tps: &Vec<ty::t>)
-> String
{
let name = match what {
a_struct => { "struct" }
an_enum => { "enum" }
};
let tstr = ppaux::parameterized(cx.tcx(),
ty::item_path_str(cx.tcx(),
did).as_slice(),
&subst::ErasedRegions,
tps,
did,
false);
let base = ty::item_path_str(cx.tcx(), did);
let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
let tstr = format!("{}<{}>", base, strings);
if did.krate == 0 {
format!("{}.{}", name, tstr)
} else {

View file

@ -24,7 +24,7 @@ use middle::freevars;
use middle::resolve;
use middle::resolve_lifetime;
use middle::subst;
use middle::subst::{Subst, Substs};
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::ty;
use middle::typeck;
use middle::typeck::MethodCall;
@ -58,7 +58,6 @@ use syntax::codemap::Span;
use syntax::parse::token;
use syntax::parse::token::InternedString;
use syntax::{ast, ast_map};
use syntax::owned_slice::OwnedSlice;
use syntax::util::small_vector::SmallVector;
use std::collections::enum_set::{EnumSet, CLike};
@ -190,9 +189,8 @@ pub enum ast_ty_to_ty_cache_entry {
#[deriving(Clone, PartialEq, Decodable, Encodable)]
pub struct ItemVariances {
pub self_param: Option<Variance>,
pub type_params: OwnedSlice<Variance>,
pub region_params: OwnedSlice<Variance>
pub types: VecPerParamSpace<Variance>,
pub regions: VecPerParamSpace<Variance>,
}
#[deriving(Clone, PartialEq, Decodable, Encodable, Show)]
@ -455,7 +453,8 @@ pub struct FnSig {
}
#[deriving(Clone, PartialEq, Eq, Hash)]
pub struct param_ty {
pub struct ParamTy {
pub space: subst::ParamSpace,
pub idx: uint,
pub def_id: DefId
}
@ -466,7 +465,10 @@ pub enum Region {
// Region bound in a type or fn declaration which will be
// substituted 'early' -- that is, at the same time when type
// parameters are substituted.
ReEarlyBound(/* param id */ ast::NodeId, /*index*/ uint, ast::Name),
ReEarlyBound(/* param id */ ast::NodeId,
subst::ParamSpace,
/*index*/ uint,
ast::Name),
// Region bound in a function scope, which will be substituted when the
// function is called. The first argument must be the `binder_id` of
@ -713,10 +715,7 @@ pub enum sty {
ty_struct(DefId, Substs),
ty_tup(Vec<t>),
ty_param(param_ty), // type parameter
ty_self(DefId), /* special, implicit `self` type parameter;
* def_id is the id of the trait */
ty_param(ParamTy), // type parameter
ty_infer(InferTy), // something used only during inference/typeck
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
@ -734,7 +733,7 @@ pub struct TyTrait {
#[deriving(PartialEq, Eq, Hash)]
pub struct TraitRef {
pub def_id: DefId,
pub substs: Substs
pub substs: Substs,
}
#[deriving(Clone, PartialEq)]
@ -964,6 +963,8 @@ impl fmt::Show for IntVarValue {
pub struct TypeParameterDef {
pub ident: ast::Ident,
pub def_id: ast::DefId,
pub space: subst::ParamSpace,
pub index: uint,
pub bounds: Rc<ParamBounds>,
pub default: Option<ty::t>
}
@ -972,29 +973,26 @@ pub struct TypeParameterDef {
pub struct RegionParameterDef {
pub name: ast::Name,
pub def_id: ast::DefId,
pub space: subst::ParamSpace,
pub index: uint,
}
/// Information about the type/lifetime parameters associated with an item.
/// Analogous to ast::Generics.
/// Information about the type/lifetime parameters associated with an
/// item or method. Analogous to ast::Generics.
#[deriving(Clone)]
pub struct Generics {
/// List of type parameters declared on the item.
pub type_param_defs: Rc<Vec<TypeParameterDef>>,
/// List of region parameters declared on the item.
/// For a fn or method, only includes *early-bound* lifetimes.
pub region_param_defs: Rc<Vec<RegionParameterDef>>,
pub types: VecPerParamSpace<TypeParameterDef>,
pub regions: VecPerParamSpace<RegionParameterDef>,
}
impl Generics {
pub fn has_type_params(&self) -> bool {
!self.type_param_defs.is_empty()
pub fn empty() -> Generics {
Generics { types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty() }
}
pub fn type_param_defs<'a>(&'a self) -> &'a [TypeParameterDef] {
self.type_param_defs.as_slice()
}
pub fn region_param_defs<'a>(&'a self) -> &'a [RegionParameterDef] {
self.region_param_defs.as_slice()
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
!self.types.get_vec(space).is_empty()
}
}
@ -1018,11 +1016,8 @@ pub struct ParameterEnvironment {
/// parameters in the same way, this only has an affect on regions.
pub free_substs: Substs,
/// Bound on the Self parameter
pub self_param_bound: Option<Rc<TraitRef>>,
/// Bounds on each numbered type parameter
pub type_param_bounds: Vec<ParamBounds>,
/// Bounds on the various type parameters
pub bounds: VecPerParamSpace<ParamBounds>,
}
/// A polytype.
@ -1162,7 +1157,10 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
}
fn sflags(substs: &Substs) -> uint {
let mut f = 0u;
for tt in substs.tps.iter() { f |= get(*tt).flags; }
let mut i = substs.types.iter();
for tt in i {
f |= get(*tt).flags;
}
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref regions) => {
@ -1185,9 +1183,14 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
// so we're doing it this way.
&ty_bot => flags |= has_ty_bot as uint,
&ty_err => flags |= has_ty_err as uint,
&ty_param(_) => flags |= has_params as uint,
&ty_param(ref p) => {
if p.space == subst::SelfSpace {
flags |= has_self as uint;
} else {
flags |= has_params as uint;
}
}
&ty_infer(_) => flags |= needs_infer as uint,
&ty_self(_) => flags |= has_self as uint,
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
}
@ -1455,10 +1458,16 @@ pub fn mk_float_var(cx: &ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
pub fn mk_infer(cx: &ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
pub fn mk_self(cx: &ctxt, did: ast::DefId) -> t { mk_t(cx, ty_self(did)) }
pub fn mk_param(cx: &ctxt, space: subst::ParamSpace, n: uint, k: DefId) -> t {
mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
}
pub fn mk_param(cx: &ctxt, n: uint, k: DefId) -> t {
mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
pub fn mk_self_type(cx: &ctxt, did: ast::DefId) -> t {
mk_param(cx, subst::SelfSpace, 0, did)
}
pub fn mk_param_from_def(cx: &ctxt, def: &TypeParameterDef) -> t {
mk_param(cx, def.space, def.index, def.def_id)
}
pub fn walk_ty(ty: t, f: |t|) {
@ -1471,15 +1480,17 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
}
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_self(_) |
ty_infer(_) | ty_param(_) | ty_err => {}
ty_str | ty_infer(_) | ty_param(_) | ty_err => {
}
ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
ty_trait(box TyTrait { ref substs, .. }) => {
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
for subty in (*substs).types.iter() {
maybe_walk_ty(*subty, |x| f(x));
}
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
ty_bare_fn(ref ft) => {
@ -1533,8 +1544,7 @@ pub fn type_needs_subst(ty: t) -> bool {
}
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
tref.substs.self_ty.iter().any(|&t| type_is_error(t)) ||
tref.substs.tps.iter().any(|&t| type_is_error(t))
tref.substs.types.any(|&t| type_is_error(t))
}
pub fn type_is_ty_var(ty: t) -> bool {
@ -1548,7 +1558,7 @@ pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
pub fn type_is_self(ty: t) -> bool {
match get(ty).sty {
ty_self(..) => true,
ty_param(ref p) => p.space == subst::SelfSpace,
_ => false
}
}
@ -2103,16 +2113,6 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
tp_def.bounds.trait_bounds.as_slice())
}
ty_self(def_id) => {
// FIXME(#4678)---self should just be a ty param
// Self may be bounded if the associated trait has builtin kinds
// for supertraits. If so we can use those bounds.
let trait_def = lookup_trait_def(cx, def_id);
let traits = [trait_def.trait_ref.clone()];
kind_bounds_to_contents(cx, trait_def.bounds, traits)
}
ty_infer(_) => {
// This occurs during coherence, but shouldn't occur at other
// times.
@ -2292,7 +2292,6 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
ty_infer(_) |
ty_err |
ty_param(_) |
ty_self(_) |
ty_vec(_, None) => {
false
}
@ -2688,6 +2687,14 @@ pub fn ty_region(tcx: &ctxt,
}
}
pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
-> ty::Region
{
ty::ReFree(ty::FreeRegion { scope_id: free_id,
bound_region: ty::BrNamed(def.def_id,
def.name) })
}
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
pub fn pat_ty(cx: &ctxt, pat: &ast::Pat) -> t {
@ -2937,27 +2944,16 @@ impl AutoRef {
}
pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
-> Rc<Vec<TypeParameterDef>> {
-> VecPerParamSpace<TypeParameterDef> {
match origin {
typeck::MethodStatic(did) => {
// n.b.: When we encode impl methods, the bounds
// that we encode include both the impl bounds
// and then the method bounds themselves...
ty::lookup_item_type(tcx, did).generics.type_param_defs
ty::lookup_item_type(tcx, did).generics.types.clone()
}
typeck::MethodParam(typeck::MethodParam {
trait_id: trt_id,
typeck::MethodParam(typeck::MethodParam{trait_id: trt_id,
method_num: n_mth, ..}) |
typeck::MethodObject(typeck::MethodObject {
trait_id: trt_id,
typeck::MethodObject(typeck::MethodObject{trait_id: trt_id,
method_num: n_mth, ..}) => {
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
let trait_type_param_defs =
Vec::from_slice(lookup_trait_def(tcx, trt_id).generics.type_param_defs());
Rc::new(trait_type_param_defs.append(
ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs()))
ty::trait_method(tcx, trt_id, n_mth).generics.types.clone()
}
}
}
@ -3176,7 +3172,7 @@ pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
/// Returns a vector containing the indices of all type parameters that appear
/// in `ty`. The vector may contain duplicates. Probably should be converted
/// to a bitset or some other representation.
pub fn param_tys_in_type(ty: t) -> Vec<param_ty> {
pub fn param_tys_in_type(ty: t) -> Vec<ParamTy> {
let mut rslt = Vec::new();
walk_ty(ty, |ty| {
match get(ty).sty {
@ -3214,8 +3210,13 @@ pub fn ty_sort_str(cx: &ctxt, t: t) -> String {
ty_infer(TyVar(_)) => "inferred type".to_string(),
ty_infer(IntVar(_)) => "integral variable".to_string(),
ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
ty_param(_) => "type parameter".to_string(),
ty_self(_) => "self".to_string(),
ty_param(ref p) => {
if p.space == subst::SelfSpace {
"Self".to_string()
} else {
"type parameter".to_string()
}
}
ty_err => "type error".to_string(),
}
}
@ -3821,7 +3822,7 @@ pub fn lookup_item_type(cx: &ctxt,
pub fn lookup_impl_vtables(cx: &ctxt,
did: ast::DefId)
-> typeck::impl_res {
-> typeck::vtable_res {
lookup_locally_or_in_crate_store(
"impl_vtables", did, &mut *cx.impl_vtables.borrow_mut(),
|| csearch::get_impl_vtables(cx, did) )
@ -4103,8 +4104,7 @@ pub fn normalize_ty(cx: &ctxt, t: t) -> t {
substs: &subst::Substs)
-> subst::Substs {
subst::Substs { regions: subst::ErasedRegions,
self_ty: substs.self_ty.fold_with(self),
tps: substs.tps.fold_with(self) }
types: substs.types.fold_with(self) }
}
fn fold_sig(&mut self,
@ -4252,11 +4252,7 @@ pub fn visitor_object_ty(tcx: &ctxt,
Ok(id) => id,
Err(s) => { return Err(s); }
};
let substs = Substs {
regions: subst::NonerasedRegions(Vec::new()),
self_ty: None,
tps: Vec::new()
};
let substs = Substs::empty();
let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs });
Ok((trait_ref.clone(),
mk_trait(tcx,
@ -4582,10 +4578,6 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
hash!(p.idx);
did(&mut state, p.def_id);
}
ty_self(d) => {
byte!(21);
did(&mut state, d);
}
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
}
@ -4607,11 +4599,7 @@ impl Variance {
pub fn construct_parameter_environment(
tcx: &ctxt,
self_bound: Option<Rc<TraitRef>>,
item_type_params: &[TypeParameterDef],
method_type_params: &[TypeParameterDef],
item_region_params: &[RegionParameterDef],
method_region_params: &[RegionParameterDef],
generics: &ty::Generics,
free_id: ast::NodeId)
-> ParameterEnvironment
{
@ -4621,75 +4609,76 @@ pub fn construct_parameter_environment(
// Construct the free substs.
//
// map Self => Self
let self_ty = self_bound.as_ref().map(|t| ty::mk_self(tcx, t.def_id));
// map A => A
let num_item_type_params = item_type_params.len();
let num_method_type_params = method_type_params.len();
let num_type_params = num_item_type_params + num_method_type_params;
let type_params = Vec::from_fn(num_type_params, |i| {
let def_id = if i < num_item_type_params {
item_type_params[i].def_id
} else {
method_type_params[i - num_item_type_params].def_id
};
ty::mk_param(tcx, i, def_id)
});
// map T => T
let mut types = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_types_from_defs(tcx, &mut types, space,
generics.types.get_vec(space));
}
// map bound 'a => free 'a
let region_params = {
fn push_region_params(mut accum: Vec<ty::Region>,
free_id: ast::NodeId,
region_params: &[RegionParameterDef])
-> Vec<ty::Region> {
for r in region_params.iter() {
accum.push(
ty::ReFree(ty::FreeRegion {
scope_id: free_id,
bound_region: ty::BrNamed(r.def_id, r.name)}));
let mut regions = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_region_params(&mut regions, space, free_id,
generics.regions.get_vec(space));
}
accum
}
let t = push_region_params(vec!(), free_id, item_region_params);
push_region_params(t, free_id, method_region_params)
};
let free_substs = Substs {
self_ty: self_ty,
tps: type_params,
regions: subst::NonerasedRegions(region_params)
types: types,
regions: subst::NonerasedRegions(regions)
};
//
// Compute the bounds on Self and the type parameters.
//
let self_bound_substd = self_bound.map(|b| b.subst(tcx, &free_substs));
let type_param_bounds_substd = Vec::from_fn(num_type_params, |i| {
if i < num_item_type_params {
(*item_type_params[i].bounds).subst(tcx, &free_substs)
} else {
let j = i - num_item_type_params;
(*method_type_params[j].bounds).subst(tcx, &free_substs)
let mut bounds = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_bounds_from_defs(tcx, &mut bounds, space, &free_substs,
generics.types.get_vec(space));
}
});
debug!("construct_parameter_environment: free_id={} \
free_subst={} \
self_param_bound={} \
type_param_bound={}",
bounds={}",
free_id,
free_substs.repr(tcx),
self_bound_substd.repr(tcx),
type_param_bounds_substd.repr(tcx));
bounds.repr(tcx));
ty::ParameterEnvironment {
return ty::ParameterEnvironment {
free_substs: free_substs,
self_param_bound: self_bound_substd,
type_param_bounds: type_param_bounds_substd,
bounds: bounds
};
fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
space: subst::ParamSpace,
free_id: ast::NodeId,
region_params: &Vec<RegionParameterDef>)
{
for r in region_params.iter() {
regions.push(space, ty::free_region_from_def(free_id, r));
}
}
fn push_types_from_defs(tcx: &ty::ctxt,
types: &mut subst::VecPerParamSpace<ty::t>,
space: subst::ParamSpace,
defs: &Vec<TypeParameterDef>) {
for (i, def) in defs.iter().enumerate() {
let ty = ty::mk_param(tcx, space, i, def.def_id);
types.push(space, ty);
}
}
fn push_bounds_from_defs(tcx: &ty::ctxt,
bounds: &mut subst::VecPerParamSpace<ParamBounds>,
space: subst::ParamSpace,
free_substs: &subst::Substs,
defs: &Vec<TypeParameterDef>) {
for def in defs.iter() {
let b = (*def.bounds).subst(tcx, free_substs);
bounds.push(space, b);
}
}
}

View file

@ -11,6 +11,7 @@
// Generalized type folding mechanism.
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty;
use middle::typeck;
use std::rc::Rc;
@ -127,6 +128,12 @@ impl<T:TypeFoldable> TypeFoldable for OwnedSlice<T> {
}
}
impl<T:TypeFoldable> TypeFoldable for VecPerParamSpace<T> {
fn fold_with<F:TypeFolder>(&self, folder: &mut F) -> VecPerParamSpace<T> {
self.map(|t| t.fold_with(folder))
}
}
impl TypeFoldable for ty::TraitStore {
fn fold_with<F:TypeFolder>(&self, folder: &mut F) -> ty::TraitStore {
folder.fold_trait_store(*self)
@ -212,16 +219,10 @@ impl TypeFoldable for typeck::vtable_origin {
typeck::vtable_param(n, b) => {
typeck::vtable_param(n, b)
}
typeck::vtable_error => {
typeck::vtable_error
}
}
}
impl TypeFoldable for typeck::impl_res {
fn fold_with<F:TypeFolder>(&self, folder: &mut F) -> typeck::impl_res {
typeck::impl_res {
trait_vtables: self.trait_vtables.fold_with(folder),
self_vtables: self.self_vtables.fold_with(folder),
}
}
}
@ -245,6 +246,8 @@ impl TypeFoldable for ty::TypeParameterDef {
ty::TypeParameterDef {
ident: self.ident,
def_id: self.def_id,
space: self.space,
index: self.index,
bounds: self.bounds.fold_with(folder),
default: self.default.fold_with(folder),
}
@ -260,8 +263,8 @@ impl TypeFoldable for ty::RegionParameterDef {
impl TypeFoldable for ty::Generics {
fn fold_with<F:TypeFolder>(&self, folder: &mut F) -> ty::Generics {
ty::Generics {
type_param_defs: self.type_param_defs.fold_with(folder),
region_param_defs: self.region_param_defs.fold_with(folder)
types: self.types.fold_with(folder),
regions: self.regions.fold_with(folder),
}
}
}
@ -291,8 +294,7 @@ pub fn super_fold_substs<T:TypeFolder>(this: &mut T,
};
subst::Substs { regions: regions,
self_ty: substs.self_ty.fold_with(this),
tps: substs.tps.fold_with(this) }
types: substs.types.fold_with(this) }
}
pub fn super_fold_sig<T:TypeFolder>(this: &mut T,
@ -390,7 +392,7 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char | ty::ty_str |
ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_err | ty::ty_infer(_) |
ty::ty_param(..) | ty::ty_self(_) => {
ty::ty_param(..) => {
(*sty).clone()
}
}

View file

@ -52,6 +52,7 @@
use middle::const_eval;
use middle::def;
use middle::lang_items::FnMutTraitLangItem;
use rl = middle::resolve_lifetime;
use middle::subst::{Subst, Substs};
use middle::subst;
use middle::ty::ty_param_substs_and_ty;
@ -85,20 +86,20 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
}
Some(&ast::DefStaticRegion) => {
Some(&rl::DefStaticRegion) => {
ty::ReStatic
}
Some(&ast::DefLateBoundRegion(binder_id, _, id)) => {
Some(&rl::DefLateBoundRegion(binder_id, _, id)) => {
ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id),
lifetime.name))
}
Some(&ast::DefEarlyBoundRegion(index, id)) => {
ty::ReEarlyBound(id, index, lifetime.name)
Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
ty::ReEarlyBound(id, space, index, lifetime.name)
}
Some(&ast::DefFreeRegion(scope_id, id)) => {
Some(&rl::DefFreeRegion(scope_id, id)) => {
ty::ReFree(ty::FreeRegion {
scope_id: scope_id,
bound_region: ty::BrNamed(ast_util::local_def(id),
@ -163,10 +164,21 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
let tcx = this.tcx();
// ast_path_substs() is only called to convert paths that are
// known to refer to traits, types, or structs. In these cases,
// all type parameters defined for the item being referenced will
// be in the TypeSpace or SelfSpace.
//
// Note: in the case of traits, the self parameter is also
// defined, but we don't currently create a `type_param_def` for
// `Self` because it is implicit.
assert!(decl_generics.regions.all(|d| d.space == subst::TypeSpace));
assert!(decl_generics.types.all(|d| d.space != subst::FnSpace));
// If the type is parameterized by the this region, then replace this
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
let expected_num_region_params = decl_generics.region_param_defs().len();
let expected_num_region_params = decl_generics.regions.len(subst::TypeSpace);
let supplied_num_region_params = path.segments.last().unwrap().lifetimes.len();
let regions = if expected_num_region_params == supplied_num_region_params {
path.segments.last().unwrap().lifetimes.iter().map(
@ -192,9 +204,10 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
};
// Convert the type parameters supplied by the user.
let ty_param_defs = decl_generics.types.get_vec(subst::TypeSpace);
let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count();
let formal_ty_param_count = decl_generics.type_param_defs().len();
let required_ty_param_count = decl_generics.type_param_defs().iter()
let formal_ty_param_count = ty_param_defs.len();
let required_ty_param_count = ty_param_defs.iter()
.take_while(|x| x.default.is_none())
.count();
if supplied_ty_param_count < required_ty_param_count {
@ -233,39 +246,31 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
.map(|a_t| ast_ty_to_ty(this, rscope, &**a_t))
.collect();
let mut substs = subst::Substs {
regions: subst::NonerasedRegions(regions),
self_ty: self_ty,
tps: tps
};
let mut substs = subst::Substs::new_type(tps, regions);
for param in decl_generics.type_param_defs()
.slice_from(supplied_ty_param_count).iter() {
let ty = param.default.unwrap().subst_spanned(tcx, &substs, Some(path.span));
substs.tps.push(ty);
match self_ty {
None => {
// If no self-type is provided, it's still possible that
// one was declared, because this could be an object type.
}
Some(ty) => {
// If a self-type is provided, one should have been
// "declared" (in other words, this should be a
// trait-ref).
assert!(decl_generics.types.get_self().is_some());
substs.types.push(subst::SelfSpace, ty);
}
}
for param in ty_param_defs.slice_from(supplied_ty_param_count).iter() {
let default = param.default.unwrap();
let default = default.subst_spanned(tcx, &substs, Some(path.span));
substs.types.push(subst::TypeSpace, default);
}
substs
}
pub fn ast_path_to_substs_and_ty<AC:AstConv,
RS:RegionScope>(
this: &AC,
rscope: &RS,
did: ast::DefId,
path: &ast::Path)
-> ty_param_substs_and_ty {
let tcx = this.tcx();
let ty::ty_param_bounds_and_ty {
generics: generics,
ty: decl_ty
} = this.get_item_ty(did);
let substs = ast_path_substs(this, rscope, &generics, None, path);
let ty = decl_ty.subst(tcx, &substs);
ty_param_substs_and_ty { substs: substs, ty: ty }
}
pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
@ -286,12 +291,14 @@ pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
path: &ast::Path)
-> ty_param_substs_and_ty
{
// Look up the polytype of the item and then substitute the provided types
// for any type/region parameters.
let ty::ty_param_substs_and_ty {
substs: substs,
ty: ty
} = ast_path_to_substs_and_ty(this, rscope, did, path);
let tcx = this.tcx();
let ty::ty_param_bounds_and_ty {
generics: generics,
ty: decl_ty
} = this.get_item_ty(did);
let substs = ast_path_substs(this, rscope, &generics, None, path);
let ty = decl_ty.subst(tcx, &substs);
ty_param_substs_and_ty { substs: substs, ty: ty }
}
@ -521,8 +528,10 @@ pub fn trait_ref_for_unboxed_function<AC:AstConv,
RS:RegionScope>(
this: &AC,
rscope: &RS,
unboxed_function: &ast::UnboxedFnTy)
-> ty::TraitRef {
unboxed_function: &ast::UnboxedFnTy,
self_ty: Option<ty::t>)
-> ty::TraitRef
{
let fn_mut_trait_did = this.tcx()
.lang_items
.require(FnMutTraitLangItem)
@ -538,11 +547,14 @@ pub fn trait_ref_for_unboxed_function<AC:AstConv,
let output_type = ast_ty_to_ty(this,
rscope,
&*unboxed_function.decl.output);
let substs = subst::Substs {
self_ty: None,
tps: vec!(input_tuple, output_type),
regions: subst::NonerasedRegions(Vec::new()),
};
let mut substs = subst::Substs::new_type(vec!(input_tuple, output_type),
Vec::new());
match self_ty {
Some(s) => substs.types.push(subst::SelfSpace, s),
None => ()
}
ty::TraitRef {
def_id: fn_mut_trait_did,
substs: substs,
@ -590,7 +602,8 @@ fn mk_pointer<AC:AstConv,
substs
} = trait_ref_for_unboxed_function(this,
rscope,
&**unboxed_function);
&**unboxed_function,
None);
return ty::mk_trait(this.tcx(),
def_id,
substs,
@ -801,9 +814,9 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
def::DefTy(did) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty
}
def::DefTyParam(id, n) => {
def::DefTyParam(space, id, n) => {
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
ty::mk_param(tcx, n, id)
ty::mk_param(tcx, space, n, id)
}
def::DefSelfTy(id) => {
// n.b.: resolve guarantees that the this type only appears in a
@ -811,7 +824,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
// substs
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
let did = ast_util::local_def(id);
ty::mk_self(tcx, did)
ty::mk_self_type(tcx, did)
}
def::DefMod(id) => {
tcx.sess.span_fatal(ast_ty.span,
@ -891,7 +904,9 @@ pub fn ty_of_method<AC:AstConv>(
fn_style: ast::FnStyle,
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf,
decl: &ast::FnDecl) -> ty::BareFnTy {
decl: &ast::FnDecl)
-> ty::BareFnTy
{
ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
untransformed_self_ty: untransformed_self_ty,
explicit_self: explicit_self

View file

@ -127,7 +127,7 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
// Check to see whether this is an enum or a struct.
match *structure_of(pcx.fcx, pat.span, expected) {
ty::ty_enum(_, ref expected_substs) => {
ty::ty_enum(expected_def_id, ref expected_substs) => {
// Lookup the enum and variant def ids:
let v_def = lookup_def(pcx.fcx, pat.span, pat.id);
match v_def.variant_def_ids() {
@ -150,18 +150,15 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
arg_types = {
let vinfo =
ty::enum_variant_with_id(tcx, enm, var);
let var_tpt = ty::lookup_item_type(tcx, var);
vinfo.args.iter().map(|t| {
if var_tpt.generics.type_param_defs().len() ==
expected_substs.tps.len()
{
t.subst(tcx, expected_substs)
if enm == expected_def_id {
vinfo.args.iter()
.map(|t| t.subst(tcx, expected_substs))
.collect()
} else {
vinfo.args.iter()
.map(|_| ty::mk_err())
.collect()
}
else {
*t // In this case, an error was already signaled
// anyway
}
}).collect()
};
kind_name = "variant";
@ -569,11 +566,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
fields.as_slice(),
etc,
supplied_def_id,
&subst::Substs {
self_ty: None,
tps: Vec::new(),
regions: subst::ErasedRegions,
});
&subst::Substs::empty());
}
_ => () // Error, but we're already in an error case
}

View file

@ -91,7 +91,7 @@ use middle::typeck::infer;
use middle::typeck::MethodCallee;
use middle::typeck::{MethodOrigin, MethodParam};
use middle::typeck::{MethodStatic, MethodObject};
use middle::typeck::{param_numbered, param_self, param_index};
use middle::typeck::{param_index};
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use util::common::indenter;
use util::ppaux;
@ -235,7 +235,8 @@ fn construct_transformed_self_ty_for_object(
trait_def_id: ast::DefId,
rcvr_substs: &subst::Substs,
method_ty: &ty::Method)
-> ty::t {
-> ty::t
{
/*!
* This is a bit tricky. We have a match against a trait method
* being invoked on an object, and we want to generate the
@ -257,9 +258,13 @@ fn construct_transformed_self_ty_for_object(
* match below.
*/
let substs = subst::Substs {regions: rcvr_substs.regions.clone(),
self_ty: None,
tps: rcvr_substs.tps.clone()};
let mut obj_substs = rcvr_substs.clone();
// The subst we get in has Err as the "Self" type. For an object
// type, we don't put any type into the Self paramspace, so let's
// make a copy of rcvr_substs that has the Self paramspace empty.
obj_substs.types.get_mut_vec(subst::SelfSpace).pop().unwrap();
match method_ty.explicit_self {
ast::SelfStatic => {
tcx.sess.span_bug(span, "static method for object type receiver");
@ -271,13 +276,13 @@ fn construct_transformed_self_ty_for_object(
let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
match ty::get(transformed_self_ty).sty {
ty::ty_rptr(r, mt) => { // must be SelfRegion
let r = r.subst(tcx, &substs); // handle Early-Bound lifetime
ty::mk_trait(tcx, trait_def_id, substs,
let r = r.subst(tcx, rcvr_substs); // handle Early-Bound lifetime
ty::mk_trait(tcx, trait_def_id, obj_substs,
RegionTraitStore(r, mt.mutbl),
ty::empty_builtin_bounds())
}
ty::ty_uniq(_) => { // must be SelfUniq
ty::mk_trait(tcx, trait_def_id, substs,
ty::mk_trait(tcx, trait_def_id, obj_substs,
UniqTraitStore,
ty::empty_builtin_bounds())
}
@ -456,11 +461,6 @@ impl<'a> LookupContext<'a> {
ty_param(p) => {
self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
}
ty_self(..) => {
// Call is of the form "self.foo()" and appears in one
// of a trait's default method implementations.
self.push_inherent_candidates_from_self(self_ty, restrict_to);
}
_ => { /* No bound methods in these types */ }
}
@ -516,10 +516,7 @@ impl<'a> LookupContext<'a> {
//
// `confirm_candidate()` also relies upon this substitution
// for Self. (fix)
let rcvr_substs = subst::Substs {
self_ty: Some(ty::mk_err()),
..(*substs).clone()
};
let rcvr_substs = substs.with_self_ty(ty::mk_err());
let trait_ref = Rc::new(TraitRef {
def_id: did,
substs: rcvr_substs.clone()
@ -552,35 +549,27 @@ impl<'a> LookupContext<'a> {
fn push_inherent_candidates_from_param(&mut self,
rcvr_ty: ty::t,
restrict_to: Option<DefId>,
param_ty: param_ty) {
param_ty: ParamTy) {
debug!("push_inherent_candidates_from_param(param_ty={:?})",
param_ty);
let i = param_ty.idx;
match self.fcx.inh.param_env.type_param_bounds.as_slice().get(i) {
Some(b) => self.push_inherent_candidates_from_bounds(
rcvr_ty, b.trait_bounds.as_slice(), restrict_to,
param_numbered(param_ty.idx)),
None => {}
}
}
fn push_inherent_candidates_from_self(&mut self,
rcvr_ty: ty::t,
restrict_to: Option<DefId>) {
debug!("push_inherent_candidates_from_self()");
self.push_inherent_candidates_from_bounds(
rcvr_ty,
[self.fcx.inh.param_env.self_param_bound.clone().unwrap()],
param_ty.space,
param_ty.idx,
restrict_to,
param_self)
param_index { space: param_ty.space, index: param_ty.idx });
}
fn push_inherent_candidates_from_bounds(&mut self,
self_ty: ty::t,
bounds: &[Rc<TraitRef>],
space: subst::ParamSpace,
index: uint,
restrict_to: Option<DefId>,
param: param_index) {
let bounds =
self.fcx.inh.param_env.bounds.get(space, index).trait_bounds
.as_slice();
self.push_inherent_candidates_from_bounds_inner(bounds,
|trait_ref, m, method_num, bound_num| {
match restrict_to {
@ -937,7 +926,7 @@ impl<'a> LookupContext<'a> {
ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
ty_infer(IntVar(_)) |
ty_infer(FloatVar(_)) |
ty_self(_) | ty_param(..) | ty_nil | ty_bot | ty_bool |
ty_param(..) | ty_nil | ty_bot | ty_bool |
ty_char | ty_int(..) | ty_uint(..) |
ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) | ty_tup(..) |
ty_str | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
@ -1093,7 +1082,8 @@ impl<'a> LookupContext<'a> {
}
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
-> MethodCallee {
-> MethodCallee
{
// This method performs two sets of substitutions, one after the other:
// 1. Substitute values for any type/lifetime parameters from the impl and
// method declaration into the method type. This is the function type
@ -1117,8 +1107,8 @@ impl<'a> LookupContext<'a> {
// If they were not explicitly supplied, just construct fresh
// variables.
let num_supplied_tps = self.supplied_tps.len();
let num_method_tps = candidate.method_ty.generics.type_param_defs().len();
let m_substs = {
let num_method_tps = candidate.method_ty.generics.types.len(subst::FnSpace);
let m_types = {
if num_supplied_tps == 0u {
self.fcx.infcx().next_ty_vars(num_method_tps)
} else if num_method_tps == 0u {
@ -1129,37 +1119,23 @@ impl<'a> LookupContext<'a> {
} else if num_supplied_tps != num_method_tps {
tcx.sess.span_err(
self.span,
"incorrect number of type \
parameters given for this method");
"incorrect number of type parameters given for this method");
self.fcx.infcx().next_ty_vars(num_method_tps)
} else {
Vec::from_slice(self.supplied_tps)
}
};
// Determine values for the early-bound lifetime parameters.
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
//
// FIXME -- permit users to manually specify lifetimes
let mut all_regions: Vec<Region> = match candidate.rcvr_substs.regions {
subst::NonerasedRegions(ref v) => {
v.iter().map(|r| r.clone()).collect()
}
subst::ErasedRegions => tcx.sess.span_bug(self.span, "ErasedRegions")
};
let m_regions =
self.fcx.infcx().region_vars_for_defs(
self.span,
candidate.method_ty.generics.region_param_defs.as_slice());
for &r in m_regions.iter() {
all_regions.push(r);
}
candidate.method_ty.generics.regions.get_vec(subst::FnSpace));
// Construct the full set of type parameters for the method,
// which is equal to the class tps + the method tps.
let all_substs = subst::Substs {
tps: candidate.rcvr_substs.tps.clone().append(m_substs.as_slice()),
regions: subst::NonerasedRegions(all_regions),
self_ty: candidate.rcvr_substs.self_ty,
};
let all_substs = candidate.rcvr_substs.clone().with_method(m_types, m_regions);
let ref bare_fn_ty = candidate.method_ty.fty;
@ -1285,7 +1261,8 @@ impl<'a> LookupContext<'a> {
check_for_self_ty(sig.output);
}
if candidate.method_ty.generics.has_type_params() { // reason (b) above
if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
// reason (b) above
self.tcx().sess.span_err(
self.span,
"cannot call a generic method through an object");

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
use middle::ty;
use middle::ty::{AutoAddEnv, AutoDerefRef, AutoObject, param_ty};
use middle::ty::{AutoAddEnv, AutoDerefRef, AutoObject, ParamTy};
use middle::ty_fold::TypeFolder;
use middle::typeck::astconv::AstConv;
use middle::typeck::check::{FnCtxt, impl_self_ty};
@ -20,11 +20,11 @@ use middle::typeck::infer::fixup_err_to_str;
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer;
use middle::typeck::{vtable_origin, vtable_res, vtable_param_res};
use middle::typeck::{vtable_static, vtable_param, impl_res};
use middle::typeck::{param_numbered, param_self, param_index};
use middle::typeck::{vtable_static, vtable_param, vtable_error};
use middle::typeck::{param_index};
use middle::typeck::MethodCall;
use middle::subst;
use middle::subst::Subst;
use middle::subst::{Subst, VecPerParamSpace};
use util::common::indenter;
use util::ppaux;
use util::ppaux::Repr;
@ -76,38 +76,32 @@ impl<'a> VtableContext<'a> {
fn lookup_vtables(vcx: &VtableContext,
span: Span,
type_param_defs: &[ty::TypeParameterDef],
type_param_defs: &VecPerParamSpace<ty::TypeParameterDef>,
substs: &subst::Substs,
is_early: bool) -> vtable_res {
debug!("lookup_vtables(span={:?}, \
is_early: bool)
-> VecPerParamSpace<vtable_param_res>
{
debug!("lookup_vtables(\
type_param_defs={}, \
substs={}",
span,
type_param_defs.repr(vcx.tcx()),
substs.repr(vcx.tcx()));
// We do this backwards for reasons discussed above.
assert_eq!(substs.tps.len(), type_param_defs.len());
let mut result: Vec<vtable_param_res> =
substs.tps.iter()
.rev()
.zip(type_param_defs.iter().rev())
.map(|(ty, def)|
let result = type_param_defs.map_rev(|def| {
let ty = *substs.types.get(def.space, def.index);
lookup_vtables_for_param(vcx, span, Some(substs),
&*def.bounds, *ty, is_early))
.collect();
result.reverse();
&*def.bounds, ty, is_early)
});
assert_eq!(substs.tps.len(), result.len());
debug!("lookup_vtables result(\
span={:?}, \
type_param_defs={}, \
substs={}, \
result={})",
span,
type_param_defs.repr(vcx.tcx()),
substs.repr(vcx.tcx()),
result.repr(vcx.tcx()));
result
}
@ -117,9 +111,15 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
substs: Option<&subst::Substs>,
type_param_bounds: &ty::ParamBounds,
ty: ty::t,
is_early: bool) -> vtable_param_res {
is_early: bool)
-> vtable_param_res {
let tcx = vcx.tcx();
debug!("lookup_vtables_for_param(ty={}, type_param_bounds={}, is_early={})",
ty.repr(vcx.tcx()),
type_param_bounds.repr(vcx.tcx()),
is_early);
// ty is the value supplied for the type parameter A...
let mut param_result = Vec::new();
@ -130,6 +130,10 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
// ...and here trait_ref is each bound that was declared on A,
// expressed in terms of the type parameters.
debug!("matching ty={} trait_ref={}",
ty.repr(vcx.tcx()),
trait_ref.repr(vcx.tcx()));
ty::populate_implementations_for_trait_if_necessary(tcx,
trait_ref.def_id);
@ -157,11 +161,9 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
});
debug!("lookup_vtables_for_param result(\
span={:?}, \
type_param_bounds={}, \
ty={}, \
result={})",
span,
type_param_bounds.repr(vcx.tcx()),
ty.repr(vcx.tcx()),
param_result.repr(vcx.tcx()));
@ -216,10 +218,11 @@ fn lookup_vtable(vcx: &VtableContext,
ty: ty::t,
trait_ref: Rc<ty::TraitRef>,
is_early: bool)
-> Option<vtable_origin> {
-> Option<vtable_origin>
{
debug!("lookup_vtable(ty={}, trait_ref={})",
vcx.infcx.ty_to_str(ty),
vcx.infcx.trait_ref_to_str(&*trait_ref));
ty.repr(vcx.tcx()),
trait_ref.repr(vcx.tcx()));
let _i = indenter();
let ty = match fixup_ty(vcx, span, ty, is_early) {
@ -230,32 +233,24 @@ fn lookup_vtable(vcx: &VtableContext,
// The type has unconstrained type variables in it, so we can't
// do early resolution on it. Return some completely bogus vtable
// information: we aren't storing it anyways.
return Some(vtable_param(param_self, 0));
return Some(vtable_error);
}
};
if ty::type_is_error(ty) {
return Some(vtable_error);
}
// If the type is self or a param, we look at the trait/supertrait
// bounds to see if they include the trait we are looking for.
let vtable_opt = match ty::get(ty).sty {
ty::ty_param(param_ty {idx: n, ..}) => {
let env_bounds = &vcx.param_env.type_param_bounds;
if env_bounds.len() > n {
let type_param_bounds: &[Rc<ty::TraitRef>] =
env_bounds.get(n).trait_bounds.as_slice();
ty::ty_param(ParamTy {space, idx: n, ..}) => {
let env_bounds = &vcx.param_env.bounds;
let type_param_bounds = &env_bounds.get(space, n).trait_bounds;
lookup_vtable_from_bounds(vcx, span,
type_param_bounds,
param_numbered(n),
trait_ref.clone())
} else {
None
}
}
ty::ty_self(_) => {
let self_param_bound = vcx.param_env.self_param_bound.clone().unwrap();
lookup_vtable_from_bounds(vcx, span,
[self_param_bound],
param_self,
type_param_bounds.as_slice(),
param_index { space: space,
index: n },
trait_ref.clone())
}
@ -373,8 +368,8 @@ fn search_for_vtable(vcx: &VtableContext,
// Now, in the previous example, for_ty is bound to
// the type self_ty, and substs is bound to [T].
debug!("The self ty is {} and its substs are {}",
vcx.infcx.ty_to_str(for_ty),
vcx.infcx.tys_to_str(substs.tps.as_slice()));
for_ty.repr(tcx),
substs.types.repr(tcx));
// Next, we unify trait_ref -- the type that we want to cast
// to -- with of_trait_ref -- the trait that im implements. At
@ -386,12 +381,13 @@ fn search_for_vtable(vcx: &VtableContext,
// some value of U) with some_trait<T>. This would fail if T
// and U weren't compatible.
debug!("(checking vtable) {}2 relating trait \
ty {} to of_trait_ref {}", "#",
let of_trait_ref = of_trait_ref.subst(tcx, &substs);
debug!("(checking vtable) num 2 relating trait \
ty {} to of_trait_ref {}",
vcx.infcx.trait_ref_to_str(&*trait_ref),
vcx.infcx.trait_ref_to_str(&*of_trait_ref));
let of_trait_ref = of_trait_ref.subst(tcx, &substs);
relate_trait_refs(vcx, span, of_trait_ref, trait_ref.clone());
@ -404,11 +400,12 @@ fn search_for_vtable(vcx: &VtableContext,
// process of looking up bounds might constrain some of them.
let im_generics =
ty::lookup_item_type(tcx, impl_did).generics;
let subres = lookup_vtables(vcx, span,
im_generics.type_param_defs(), &substs,
let subres = lookup_vtables(vcx,
span,
&im_generics.types,
&substs,
is_early);
// substs might contain type variables, so we call
// fixup_substs to resolve them.
let substs_f = match fixup_substs(vcx, span,
@ -419,15 +416,15 @@ fn search_for_vtable(vcx: &VtableContext,
None => {
assert!(is_early);
// Bail out with a bogus answer
return Some(vtable_param(param_self, 0));
return Some(vtable_error);
}
};
debug!("The fixed-up substs are {} - \
they will be unified with the bounds for \
the target ty, {}",
vcx.infcx.tys_to_str(substs_f.tps.as_slice()),
vcx.infcx.trait_ref_to_str(&*trait_ref));
substs_f.types.repr(tcx),
trait_ref.repr(tcx));
// Next, we unify the fixed-up substitutions for the impl self
// ty with the substitutions from the trait type that we're
@ -515,7 +512,7 @@ fn connect_trait_tps(vcx: &VtableContext,
}
fn insert_vtables(fcx: &FnCtxt, vtable_key: MethodCall, vtables: vtable_res) {
debug!("insert_vtables(vtable_key={}, vtables={:?})",
debug!("insert_vtables(vtable_key={}, vtables={})",
vtable_key, vtables.repr(fcx.tcx()));
fcx.inh.vtable_map.borrow_mut().insert(vtable_key, vtables);
}
@ -560,12 +557,20 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
};
let vcx = fcx.vtable_context();
// Take the type parameters from the object
// type, but set the Self type (which is
// unknown, for the object type) to be the type
// we are casting from.
let mut target_types = target_substs.types.clone();
assert!(target_types.get_self().is_none());
target_types.push(subst::SelfSpace, typ);
let target_trait_ref = Rc::new(ty::TraitRef {
def_id: target_def_id,
substs: subst::Substs {
tps: target_substs.tps.clone(),
regions: target_substs.regions.clone(),
self_ty: Some(typ)
types: target_types
}
});
@ -582,7 +587,9 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
is_early);
if !is_early {
insert_vtables(fcx, MethodCall::expr(ex.id), vec!(vtables));
let mut r = VecPerParamSpace::empty();
r.push(subst::SelfSpace, vtables);
insert_vtables(fcx, MethodCall::expr(ex.id), r);
}
// Now, if this is &trait, we need to link the
@ -632,10 +639,10 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
debug!("early resolve expr: def {:?} {:?}, {:?}, {}", ex.id, did, def,
fcx.infcx().ty_to_str(item_ty.ty));
debug!("early_resolve_expr: looking up vtables for type params {}",
item_ty.generics.type_param_defs().repr(fcx.tcx()));
item_ty.generics.types.repr(fcx.tcx()));
let vcx = fcx.vtable_context();
let vtbls = lookup_vtables(&vcx, ex.span,
item_ty.generics.type_param_defs(),
&item_ty.generics.types,
&item_substs.substs, is_early);
if !is_early {
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
@ -657,7 +664,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
let substs = fcx.method_ty_substs(ex.id);
let vcx = fcx.vtable_context();
let vtbls = lookup_vtables(&vcx, ex.span,
type_param_defs.as_slice(),
&type_param_defs,
&substs, is_early);
if !is_early {
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
@ -689,8 +696,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
ty::method_call_type_param_defs(cx.tcx, method.origin);
let vcx = fcx.vtable_context();
let vtbls = lookup_vtables(&vcx, ex.span,
type_param_defs.deref()
.as_slice(),
&type_param_defs,
&method.substs, is_early);
if !is_early {
insert_vtables(fcx, method_call, vtbls);
@ -726,64 +732,84 @@ pub fn resolve_impl(tcx: &ty::ctxt,
impl_item: &ast::Item,
impl_generics: &ty::Generics,
impl_trait_ref: &ty::TraitRef) {
/*!
* The situation is as follows. We have some trait like:
*
* trait Foo<A:Clone> : Bar {
* fn method() { ... }
* }
*
* and an impl like:
*
* impl<B:Clone> Foo<B> for int { ... }
*
* We want to validate that the various requirements of the trait
* are met:
*
* A:Clone, Self:Bar
*
* But of course after substituting the types from the impl:
*
* B:Clone, int:Bar
*
* We store these results away as the "impl_res" for use by the
* default methods.
*/
debug!("resolve_impl(impl_item.id={})",
impl_item.id);
let param_env = ty::construct_parameter_environment(
tcx,
None,
impl_generics.type_param_defs(),
[],
impl_generics.region_param_defs(),
[],
let param_env = ty::construct_parameter_environment(tcx,
impl_generics,
impl_item.id);
// The impl_trait_ref in our example above would be
// `Foo<B> for int`
let impl_trait_ref = impl_trait_ref.subst(tcx, &param_env.free_substs);
debug!("impl_trait_ref={}", impl_trait_ref.repr(tcx));
let infcx = &infer::new_infer_ctxt(tcx);
let vcx = VtableContext { infcx: infcx, param_env: &param_env };
// First, check that the impl implements any trait bounds
// on the trait.
// Resolve the vtables for the trait reference on the impl. This
// serves many purposes, best explained by example. Imagine we have:
//
// trait A<T:B> : C { fn x(&self) { ... } }
//
// and
//
// impl A<int> for uint { ... }
//
// In that case, the trait ref will be `A<int> for uint`. Resolving
// this will first check that the various types meet their requirements:
//
// 1. Because of T:B, int must implement the trait B
// 2. Because of the supertrait C, uint must implement the trait C.
//
// Simultaneously, the result of this resolution (`vtbls`), is precisely
// the set of vtable information needed to compile the default method
// `x()` adapted to the impl. (After all, a default method is basically
// the same as:
//
// fn default_x<T:B, Self:A>(...) { .. .})
let trait_def = ty::lookup_trait_def(tcx, impl_trait_ref.def_id);
let vtbls = lookup_vtables(&vcx, impl_item.span,
trait_def.generics.type_param_defs(),
let vtbls = lookup_vtables(&vcx,
impl_item.span,
&trait_def.generics.types,
&impl_trait_ref.substs,
false);
// Now, locate the vtable for the impl itself. The real
// purpose of this is to check for supertrait impls,
// but that falls out of doing this.
let param_bounds = ty::ParamBounds {
builtin_bounds: ty::empty_builtin_bounds(),
trait_bounds: vec!(Rc::new(impl_trait_ref))
};
let t = ty::node_id_to_type(tcx, impl_item.id);
let t = t.subst(tcx, &param_env.free_substs);
debug!("=== Doing a self lookup now.");
// Right now, we don't have any place to store this.
// We will need to make one so we can use this information
// for compiling default methods that refer to supertraits.
let self_vtable_res =
lookup_vtables_for_param(&vcx, impl_item.span, None,
&param_bounds, t, false);
infcx.resolve_regions_and_report_errors();
let res = impl_res {
trait_vtables: vtbls,
self_vtables: self_vtable_res
};
let res = writeback::resolve_impl_res(infcx, impl_item.span, &res);
let vtbls = writeback::resolve_impl_res(infcx, impl_item.span, &vtbls);
let impl_def_id = ast_util::local_def(impl_item.id);
debug!("impl_vtables for {} are {}",
impl_def_id.repr(tcx),
res.repr(tcx));
vtbls.repr(tcx));
tcx.impl_vtables.borrow_mut().insert(impl_def_id, res);
tcx.impl_vtables.borrow_mut().insert(impl_def_id, vtbls);
}
/// Resolve vtables for a method call after typeck has finished.
@ -791,15 +817,14 @@ pub fn resolve_impl(tcx: &ty::ctxt,
pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId,
substs: &subst::Substs) -> vtable_res {
let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
let type_param_defs = &*generics.type_param_defs;
let vcx = VtableContext {
infcx: &infer::new_infer_ctxt(tcx),
param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], [], id)
param_env: &ty::construct_parameter_environment(tcx, &ty::Generics::empty(), id)
};
lookup_vtables(&vcx,
tcx.map.span(id),
type_param_defs.as_slice(),
&generics.types,
substs,
false)
}

View file

@ -14,7 +14,6 @@
use middle::def;
use middle::pat_util;
use middle::subst;
use middle::ty;
use middle::ty_fold::{TypeFolder,TypeFoldable};
use middle::typeck::astconv::AstConv;
@ -22,8 +21,8 @@ use middle::typeck::check::FnCtxt;
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::resolve_type;
use middle::typeck::infer;
use middle::typeck::impl_res;
use middle::typeck::{MethodCall, MethodCallee};
use middle::typeck::vtable_res;
use middle::typeck::write_substs_to_tcx;
use middle::typeck::write_ty_to_tcx;
use util::ppaux::Repr;
@ -66,13 +65,13 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
pub fn resolve_impl_res(infcx: &infer::InferCtxt,
span: Span,
impl_res: &impl_res)
-> impl_res {
vtable_res: &vtable_res)
-> vtable_res {
let errors = Cell::new(false); // nobody cares
let mut resolver = Resolver::from_infcx(infcx,
&errors,
ResolvingImplRes(span));
impl_res.resolve_in(&mut resolver)
vtable_res.resolve_in(&mut resolver)
}
///////////////////////////////////////////////////////////////////////////
@ -285,22 +284,12 @@ impl<'cx> WritebackCx<'cx> {
debug!("writeback::resolve_method_map_entry(call={:?}, entry={})",
method_call,
method.repr(self.tcx()));
let mut new_method = MethodCallee {
let new_method = MethodCallee {
origin: method.origin,
ty: self.resolve(&method.ty, reason),
substs: self.resolve(&method.substs, reason),
};
// Wack. For some reason I don't quite know, we always
// hard-code the self-ty and regions to these
// values. Changing this causes downstream errors I
// don't feel like investigating right now (in
// particular, self_ty is set to mk_err in some cases,
// probably for invocations on objects, and this
// causes encoding failures). -nmatsakis
new_method.substs.self_ty = None;
new_method.substs.regions = subst::ErasedRegions;
self.tcx().method_map.borrow_mut().insert(
method_call,
new_method);

View file

@ -24,7 +24,7 @@ use middle::ty::{ImplContainer, lookup_item_type};
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
use middle::ty::type_is_ty_var;
use middle::subst::Subst;
@ -43,7 +43,7 @@ use syntax::ast;
use syntax::ast_map::NodeItem;
use syntax::ast_map;
use syntax::ast_util::{local_def};
use syntax::codemap::Span;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::parse::token;
use syntax::visit;
@ -81,7 +81,7 @@ fn get_base_type(inference_context: &InferCtxt,
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
ty_infer(..) | ty_param(..) | ty_self(..) | ty_err |
ty_infer(..) | ty_param(..) | ty_err |
ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
debug!("(getting base type) no base type; found {:?}",
get(original_type).sty);
@ -338,7 +338,8 @@ impl<'a> CoherenceChecker<'a> {
// Creates default method IDs and performs type substitutions for an impl
// and trait pair. Then, for each provided method in the trait, inserts a
// `ProvidedMethodInfo` instance into the `provided_method_sources` map.
fn instantiate_default_methods(&self, impl_id: DefId,
fn instantiate_default_methods(&self,
impl_id: DefId,
trait_ref: &ty::TraitRef,
all_methods: &mut Vec<DefId>) {
let tcx = self.crate_context.tcx;
@ -360,6 +361,7 @@ impl<'a> CoherenceChecker<'a> {
Rc::new(subst_receiver_types_in_method_ty(
tcx,
impl_id,
&impl_poly_type,
trait_ref,
new_did,
&**trait_method,
@ -368,17 +370,11 @@ impl<'a> CoherenceChecker<'a> {
debug!("new_method_ty={}", new_method_ty.repr(tcx));
all_methods.push(new_did);
// construct the polytype for the method based on the method_ty
let new_generics = ty::Generics {
type_param_defs:
Rc::new(Vec::from_slice(impl_poly_type.generics.type_param_defs()).append(
new_method_ty.generics.type_param_defs())),
region_param_defs:
Rc::new(Vec::from_slice(impl_poly_type.generics.region_param_defs()).append(
new_method_ty.generics.region_param_defs()))
};
// construct the polytype for the method based on the
// method_ty. it will have all the generics from the
// impl, plus its own.
let new_polytype = ty::ty_param_bounds_and_ty {
generics: new_generics,
generics: new_method_ty.generics.clone(),
ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone())
};
debug!("new_polytype={}", new_polytype.repr(tcx));
@ -503,21 +499,11 @@ impl<'a> CoherenceChecker<'a> {
// Converts a polytype to a monotype by replacing all parameters with
// type variables. Returns the monotype and the type variables created.
fn universally_quantify_polytype(&self, polytype: ty_param_bounds_and_ty)
-> UniversalQuantificationResult {
let region_parameters =
polytype.generics.region_param_defs().iter()
.map(|d| self.inference_context.next_region_var(
infer::BoundRegionInCoherence(d.name)))
.collect();
let bounds_count = polytype.generics.type_param_defs().len();
let type_parameters = self.inference_context.next_ty_vars(bounds_count);
let substitutions = subst::Substs {
regions: subst::NonerasedRegions(region_parameters),
self_ty: None,
tps: type_parameters
};
-> UniversalQuantificationResult
{
let substitutions =
self.inference_context.fresh_substs_for_type(DUMMY_SP,
&polytype.generics);
let monotype = polytype.ty.subst(self.crate_context.tcx, &substitutions);
UniversalQuantificationResult {
@ -731,69 +717,67 @@ impl<'a> CoherenceChecker<'a> {
}
pub fn make_substs_for_receiver_types(tcx: &ty::ctxt,
impl_id: ast::DefId,
trait_ref: &ty::TraitRef,
method: &ty::Method)
-> subst::Substs {
-> subst::Substs
{
/*!
* Substitutes the values for the receiver's type parameters
* that are found in method, leaving the method's type parameters
* intact. This is in fact a mildly complex operation,
* largely because of the hokey way that we concatenate the
* receiver and method generics.
* intact.
*/
let impl_polytype = ty::lookup_item_type(tcx, impl_id);
let num_impl_tps = impl_polytype.generics.type_param_defs().len();
let num_impl_regions = impl_polytype.generics.region_param_defs().len();
let meth_tps: Vec<ty::t> =
method.generics.type_param_defs().iter().enumerate()
.map(|(i, t)| ty::mk_param(tcx, i + num_impl_tps, t.def_id))
method.generics.types.get_vec(subst::FnSpace)
.iter()
.map(|def| ty::mk_param_from_def(tcx, def))
.collect();
let meth_regions: Vec<ty::Region> =
method.generics.region_param_defs().iter().enumerate()
.map(|(i, l)| ty::ReEarlyBound(l.def_id.node, i + num_impl_regions, l.name))
method.generics.regions.get_vec(subst::FnSpace)
.iter()
.map(|def| ty::ReEarlyBound(def.def_id.node, def.space,
def.index, def.name))
.collect();
let mut combined_tps = trait_ref.substs.tps.clone();
combined_tps.push_all_move(meth_tps);
let combined_regions = match &trait_ref.substs.regions {
&subst::ErasedRegions =>
fail!("make_substs_for_receiver_types: unexpected ErasedRegions"),
&subst::NonerasedRegions(ref rs) => {
let mut rs = rs.clone();
rs.push_all_move(meth_regions);
subst::NonerasedRegions(rs)
}
};
subst::Substs {
regions: combined_regions,
self_ty: trait_ref.substs.self_ty,
tps: combined_tps
}
trait_ref.substs.clone().with_method(meth_tps, meth_regions)
}
fn subst_receiver_types_in_method_ty(tcx: &ty::ctxt,
impl_id: ast::DefId,
impl_poly_type: &ty::ty_param_bounds_and_ty,
trait_ref: &ty::TraitRef,
new_def_id: ast::DefId,
method: &ty::Method,
provided_source: Option<ast::DefId>)
-> ty::Method {
-> ty::Method
{
let combined_substs = make_substs_for_receiver_types(tcx, trait_ref, method);
let combined_substs = make_substs_for_receiver_types(
tcx, impl_id, trait_ref, method);
debug!("subst_receiver_types_in_method_ty: combined_substs={}",
combined_substs.repr(tcx));
let mut method_generics = method.generics.subst(tcx, &combined_substs);
// replace the type parameters declared on the trait with those
// from the impl
for &space in [subst::TypeSpace, subst::SelfSpace].iter() {
*method_generics.types.get_mut_vec(space) =
impl_poly_type.generics.types.get_vec(space).clone();
*method_generics.regions.get_mut_vec(space) =
impl_poly_type.generics.regions.get_vec(space).clone();
}
debug!("subst_receiver_types_in_method_ty: method_generics={}",
method_generics.repr(tcx));
let method_fty = method.fty.subst(tcx, &combined_substs);
debug!("subst_receiver_types_in_method_ty: method_ty={}",
method.fty.repr(tcx));
ty::Method::new(
method.ident,
// method types *can* appear in the generic bounds
method.generics.subst(tcx, &combined_substs),
// method types *can* appear in the fty
method.fty.subst(tcx, &combined_substs),
method_generics,
method_fty,
method.explicit_self,
method.vis,
new_def_id,

View file

@ -36,7 +36,7 @@ use middle::def;
use middle::lang_items::SizedTraitLangItem;
use middle::resolve_lifetime;
use middle::subst;
use middle::subst::{Subst, Substs};
use middle::subst::{Substs};
use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
use middle::ty::{ty_param_bounds_and_ty};
use middle::ty;
@ -191,36 +191,35 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
}
}
pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
pub fn ensure_trait_methods(ccx: &CrateCtxt,
trait_id: ast::NodeId,
trait_def: &ty::TraitDef) {
let tcx = ccx.tcx;
match tcx.map.get(trait_id) {
ast_map::NodeItem(item) => {
match item.node {
ast::ItemTrait(ref generics, _, _, ref ms) => {
let trait_ty_generics = ty_generics_for_type(ccx, generics);
ast::ItemTrait(_, _, _, ref ms) => {
// For each method, construct a suitable ty::Method and
// store it into the `tcx.methods` table:
for m in ms.iter() {
let ty_method = Rc::new(match m {
&ast::Required(ref m) => {
ty_method_of_trait_method(
ccx, trait_id, &trait_ty_generics,
ccx, trait_id, &trait_def.generics,
&m.id, &m.ident, &m.explicit_self,
&m.generics, &m.fn_style, &*m.decl)
}
&ast::Provided(ref m) => {
ty_method_of_trait_method(
ccx, trait_id, &trait_ty_generics,
ccx, trait_id, &trait_def.generics,
&m.id, &m.ident, &m.explicit_self,
&m.generics, &m.fn_style, &*m.decl)
}
});
if ty_method.explicit_self == ast::SelfStatic {
make_static_method_ty(ccx, trait_id, &*ty_method,
&trait_ty_generics);
make_static_method_ty(ccx, &*ty_method);
}
tcx.methods.borrow_mut().insert(ty_method.def_id,
@ -249,129 +248,12 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
_ => { /* Ignore things that aren't traits */ }
}
fn make_static_method_ty(ccx: &CrateCtxt,
trait_id: ast::NodeId,
m: &ty::Method,
trait_ty_generics: &ty::Generics) {
// If declaration is
//
// trait Trait<'a,'b,'c,a,b,c> {
// fn foo<'d,'e,'f,d,e,f>(...) -> Self;
// }
//
// and we will create a function like
//
// fn foo<'a,'b,'c, // First the lifetime params from trait
// 'd,'e,'f, // Then lifetime params from `foo()`
// a,b,c, // Then type params from trait
// D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
// E,F,G // Then type params from `foo()`, offset by 1
// >(...) -> D' {}
//
// Note that `Self` is replaced with an explicit type
// parameter D that is sandwiched in between the trait params
// and the method params, and thus the indices of the method
// type parameters are offset by 1 (that is, the method
// parameters are mapped from d, e, f to E, F, and G). The
// choice of this ordering is somewhat arbitrary.
//
// Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
// This implies that the lifetime parameters that were inherited
// from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
// bound, since they appear in a trait bound.
//
// Also, this system is rather a hack that should be replaced
// with a more uniform treatment of Self (which is partly
// underway).
// build up a subst that shifts all of the parameters over
// by one and substitute in a new type param for self
let tcx = ccx.tcx;
let dummy_defid = ast::DefId {krate: 0, node: 0};
// Represents [A',B',C']
let num_trait_bounds = trait_ty_generics.type_param_defs().len();
let non_shifted_trait_tps = Vec::from_fn(num_trait_bounds, |i| {
ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
});
// Represents [D']
let self_param = ty::mk_param(tcx, num_trait_bounds,
dummy_defid);
// Represents [E',F',G']
let num_method_bounds = m.generics.type_param_defs().len();
let shifted_method_tps = Vec::from_fn(num_method_bounds, |i| {
ty::mk_param(tcx, i + num_trait_bounds + 1,
m.generics.type_param_defs()[i].def_id)
});
// Convert the regions 'a, 'b, 'c defined on the trait into
// bound regions on the fn. Note that because these appear in the
// bound for `Self` they must be early bound.
let new_early_region_param_defs = trait_ty_generics.region_param_defs.clone();
let rps_from_trait =
trait_ty_generics.region_param_defs().iter().
enumerate().
map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.name)).
collect();
// build up the substitution from
// 'a,'b,'c => 'a,'b,'c
// A,B,C => A',B',C'
// Self => D'
// D,E,F => E',F',G'
let substs = subst::Substs {
regions: subst::NonerasedRegions(rps_from_trait),
self_ty: Some(self_param),
tps: non_shifted_trait_tps.append(shifted_method_tps.as_slice())
};
// create the type of `foo`, applying the substitution above
let ty = ty::mk_bare_fn(tcx, m.fty.clone()).subst(tcx, &substs);
// create the type parameter definitions for `foo`, applying
// the substitution to any traits that appear in their bounds.
// add in the type parameters from the trait
let mut new_type_param_defs = Vec::new();
let substd_type_param_defs =
trait_ty_generics.type_param_defs.subst(tcx, &substs);
new_type_param_defs.push_all(substd_type_param_defs.as_slice());
// add in the "self" type parameter
let self_trait_def = get_trait_def(ccx, local_def(trait_id));
let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
new_type_param_defs.push(ty::TypeParameterDef {
ident: special_idents::self_,
def_id: dummy_defid,
bounds: Rc::new(ty::ParamBounds {
builtin_bounds: ty::empty_builtin_bounds(),
trait_bounds: vec!(self_trait_ref)
}),
default: None
});
// add in the type parameters from the method
let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
new_type_param_defs.push_all(substd_type_param_defs.as_slice());
debug!("static method {} type_param_defs={} ty={}, substs={}",
m.def_id.repr(tcx),
new_type_param_defs.repr(tcx),
ty.repr(tcx),
substs.repr(tcx));
tcx.tcache.borrow_mut().insert(m.def_id,
fn make_static_method_ty(ccx: &CrateCtxt, m: &ty::Method) {
ccx.tcx.tcache.borrow_mut().insert(
m.def_id,
ty_param_bounds_and_ty {
generics: ty::Generics {
type_param_defs: Rc::new(new_type_param_defs),
region_param_defs: new_early_region_param_defs
},
ty: ty
});
generics: m.generics.clone(),
ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
}
fn ty_method_of_trait_method(this: &CrateCtxt,
@ -384,12 +266,13 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
m_fn_style: &ast::FnStyle,
m_decl: &ast::FnDecl) -> ty::Method
{
let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));
let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty,
*m_explicit_self, m_decl);
let num_trait_type_params = trait_generics.type_param_defs().len();
let ty_generics = ty_generics_for_fn_or_method(this, m_generics,
num_trait_type_params);
let ty_generics =
ty_generics_for_fn_or_method(this,
m_generics,
(*trait_generics).clone());
ty::Method::new(
*m_ident,
ty_generics,
@ -404,54 +287,6 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
}
}
pub fn ensure_supertraits(ccx: &CrateCtxt,
id: ast::NodeId,
sp: codemap::Span,
ast_trait_refs: &[ast::TraitRef],
sized: ast::Sized)
-> ty::BuiltinBounds
{
let tcx = ccx.tcx;
// Called only the first time trait_def_of_item is called.
// Supertraits are ensured at the same time.
assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
let self_ty = ty::mk_self(ccx.tcx, local_def(id));
let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
let mut bounds = ty::empty_builtin_bounds();
for ast_trait_ref in ast_trait_refs.iter() {
let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
// FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
// builtin trait, so that the trait's node id appears in the tcx trait_ref
// map. This is only needed for metadata; see the similar fixme in encoder.rs.
let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
// FIXME(#5527) Could have same trait multiple times
if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) {
// This means a trait inherited from the same supertrait more
// than once.
tcx.sess.span_err(sp, "duplicate supertrait in trait declaration");
break;
} else {
ty_trait_refs.push(trait_ref);
}
}
}
if sized == ast::StaticSize {
match tcx.lang_items.require(SizedTraitLangItem) {
Ok(def_id) => {
ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
}
Err(s) => tcx.sess.err(s.as_slice()),
};
}
tcx.supertraits.borrow_mut().insert(local_def(id), Rc::new(ty_trait_refs));
bounds
}
pub fn convert_field(ccx: &CrateCtxt,
struct_generics: &ty::Generics,
v: &ast::StructField,
@ -490,7 +325,6 @@ fn convert_methods(ccx: &CrateCtxt,
ms: &[Gc<ast::Method>],
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
rcvr_ast_generics: &ast::Generics,
rcvr_visibility: ast::Visibility)
{
let tcx = ccx.tcx;
@ -500,14 +334,11 @@ fn convert_methods(ccx: &CrateCtxt,
tcx.sess.span_err(m.span, "duplicate method in trait impl");
}
let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
num_rcvr_ty_params);
let mty = Rc::new(ty_of_method(ccx,
container,
&**m,
untransformed_rcvr_ty,
rcvr_ast_generics,
rcvr_ty_generics,
rcvr_visibility));
let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
debug!("method {} (id {}) has type {}",
@ -516,17 +347,8 @@ fn convert_methods(ccx: &CrateCtxt,
fty.repr(ccx.tcx));
tcx.tcache.borrow_mut().insert(
local_def(m.id),
// n.b.: the type of a method is parameterized by both
// the parameters on the receiver and those on the method
// itself
ty_param_bounds_and_ty {
generics: ty::Generics {
type_param_defs: Rc::new(Vec::from_slice(rcvr_ty_generics.type_param_defs())
.append(m_ty_generics.type_param_defs())),
region_param_defs: Rc::new(Vec::from_slice(rcvr_ty_generics.region_param_defs())
.append(m_ty_generics.region_param_defs())),
},
generics: mty.generics.clone(),
ty: fty
});
@ -539,8 +361,9 @@ fn convert_methods(ccx: &CrateCtxt,
container: MethodContainer,
m: &ast::Method,
untransformed_rcvr_ty: ty::t,
rcvr_generics: &ast::Generics,
rcvr_visibility: ast::Visibility) -> ty::Method
rcvr_ty_generics: &ty::Generics,
rcvr_visibility: ast::Visibility)
-> ty::Method
{
let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
untransformed_rcvr_ty,
@ -552,19 +375,17 @@ fn convert_methods(ccx: &CrateCtxt,
// foo(); }`).
let method_vis = m.vis.inherit_from(rcvr_visibility);
let num_rcvr_type_params = rcvr_generics.ty_params.len();
let m_ty_generics =
ty_generics_for_fn_or_method(ccx, &m.generics, num_rcvr_type_params);
ty::Method::new(
m.ident,
ty_generics_for_fn_or_method(ccx, &m.generics,
(*rcvr_ty_generics).clone());
ty::Method::new(m.ident,
m_ty_generics,
fty,
m.explicit_self.node,
method_vis,
local_def(m.id),
container,
None
)
None)
}
}
@ -634,32 +455,30 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
ms.as_slice(),
selfty,
&ty_generics,
generics,
parent_visibility);
for trait_ref in opt_trait_ref.iter() {
instantiate_trait_ref(ccx, trait_ref, selfty);
}
},
ast::ItemTrait(ref generics, _, _, ref trait_methods) => {
ast::ItemTrait(_, _, _, ref trait_methods) => {
let trait_def = trait_def_of_item(ccx, it);
// Run convert_methods on the provided methods.
let (_, provided_methods) =
split_trait_methods(trait_methods.as_slice());
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id));
convert_methods(ccx,
TraitContainer(local_def(it.id)),
provided_methods.as_slice(),
untransformed_rcvr_ty,
&trait_def.generics,
generics,
it.vis);
// We need to do this *after* converting methods, since
// convert_methods produces a tcache entry that is wrong for
// static trait methods. This is somewhat unfortunate.
ensure_trait_methods(ccx, it.id);
ensure_trait_methods(ccx, it.id, &*trait_def);
},
ast::ItemStruct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
@ -770,7 +589,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
};
tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);
let substs = mk_item_substs(ccx, &tpt.generics, None);
let substs = mk_item_substs(ccx, &tpt.generics);
let selfty = ty::mk_struct(tcx, local_def(id), substs);
// If this struct is enum-like or tuple-like, create the type of its
@ -873,32 +692,124 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
_ => {}
}
match it.node {
let (generics, sized, supertraits) = match it.node {
ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
let self_ty = ty::mk_self(tcx, def_id);
let ty_generics = ty_generics_for_type(ccx, generics);
let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
let bounds = ensure_supertraits(ccx,
it.id,
it.span,
supertraits.as_slice(),
sized);
let trait_def = Rc::new(ty::TraitDef {
generics: ty_generics,
bounds: bounds,
trait_ref: Rc::new(ty::TraitRef {
def_id: def_id,
substs: substs
})
});
tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
trait_def
(generics, sized, supertraits)
}
ref s => {
tcx.sess.span_bug(
it.span,
format!("trait_def_of_item invoked on {:?}", s).as_slice());
}
};
let substs = mk_trait_substs(ccx, it.id, generics);
let ty_generics = ty_generics_for_trait(ccx,
it.id,
&substs,
generics);
let builtin_bounds =
ensure_supertraits(ccx, it.id, it.span, supertraits, sized);
let substs = mk_item_substs(ccx, &ty_generics);
let trait_def = Rc::new(ty::TraitDef {
generics: ty_generics,
bounds: builtin_bounds,
trait_ref: Rc::new(ty::TraitRef {
def_id: def_id,
substs: substs
})
});
tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
return trait_def;
fn mk_trait_substs(ccx: &CrateCtxt,
trait_id: ast::NodeId,
generics: &ast::Generics)
-> subst::Substs
{
// Creates a no-op substitution for the trait's type parameters.
let regions =
generics.lifetimes
.iter()
.enumerate()
.map(|(i, def)| ty::ReEarlyBound(def.id,
subst::TypeSpace,
i, def.name))
.collect();
let types =
generics.ty_params
.iter()
.enumerate()
.map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
i, local_def(def.id)))
.collect();
let self_ty =
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
subst::Substs::new_trait(types, regions, self_ty)
}
fn ensure_supertraits(ccx: &CrateCtxt,
id: ast::NodeId,
sp: codemap::Span,
ast_trait_refs: &Vec<ast::TraitRef>,
sized: ast::Sized)
-> ty::BuiltinBounds
{
let tcx = ccx.tcx;
// Called only the first time trait_def_of_item is called.
// Supertraits are ensured at the same time.
assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
let self_ty = ty::mk_self_type(ccx.tcx, local_def(id));
let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
let mut bounds = ty::empty_builtin_bounds();
for ast_trait_ref in ast_trait_refs.iter() {
let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
// FIXME(#8559): Need to instantiate the trait_ref whether
// or not it's a builtin trait, so that the trait's node
// id appears in the tcx trait_ref map. This is only
// needed for metadata; see the similar fixme in
// encoder.rs.
let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
// FIXME(#5527) Could have same trait multiple times
if ty_trait_refs.iter().any(
|other_trait| other_trait.def_id == trait_ref.def_id)
{
// This means a trait inherited from the same
// supertrait more than once.
tcx.sess.span_err(sp, "duplicate supertrait in \
trait declaration");
break;
} else {
ty_trait_refs.push(trait_ref);
}
}
}
if sized == ast::StaticSize {
match tcx.lang_items.require(SizedTraitLangItem) {
Ok(def_id) => {
ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
}
Err(s) => tcx.sess.err(s.as_slice()),
};
}
tcx.supertraits.borrow_mut().insert(local_def(id),
Rc::new(ty_trait_refs));
bounds
}
}
@ -919,7 +830,8 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
return tpt;
}
ast::ItemFn(decl, fn_style, abi, ref generics, _) => {
let ty_generics = ty_generics_for_fn_or_method(ccx, generics, 0);
let ty_generics = ty_generics_for_fn_or_method(ccx, generics,
ty::Generics::empty());
let tofd = astconv::ty_of_bare_fn(ccx,
it.id,
fn_style,
@ -957,7 +869,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
ast::ItemEnum(_, ref generics) => {
// Create a new generic polytype.
let ty_generics = ty_generics_for_type(ccx, generics);
let substs = mk_item_substs(ccx, &ty_generics, None);
let substs = mk_item_substs(ccx, &ty_generics);
let t = ty::mk_enum(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty {
generics: ty_generics,
@ -972,7 +884,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
}
ast::ItemStruct(_, ref generics) => {
let ty_generics = ty_generics_for_type(ccx, generics);
let substs = mk_item_substs(ccx, &ty_generics, None);
let substs = mk_item_substs(ccx, &ty_generics);
let t = ty::mk_struct(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty {
generics: ty_generics,
@ -1001,10 +913,7 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
}
ast::ForeignItemStatic(t, _) => {
ty::ty_param_bounds_and_ty {
generics: ty::Generics {
type_param_defs: Rc::new(Vec::new()),
region_param_defs: Rc::new(Vec::new()),
},
generics: ty::Generics::empty(),
ty: ast_ty_to_ty(ccx, &ExplicitRscope, &*t)
}
}
@ -1013,34 +922,96 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
fn ty_generics_for_type(ccx: &CrateCtxt,
generics: &ast::Generics)
-> ty::Generics {
ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
-> ty::Generics
{
ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
&generics.ty_params, ty::Generics::empty())
}
fn ty_generics_for_trait(ccx: &CrateCtxt,
trait_id: ast::NodeId,
substs: &subst::Substs,
generics: &ast::Generics)
-> ty::Generics
{
let mut generics = ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
&generics.ty_params, ty::Generics::empty());
// Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter.
let param_id = trait_id;
let self_trait_ref =
Rc::new(ty::TraitRef { def_id: local_def(trait_id),
substs: (*substs).clone() });
let def = ty::TypeParameterDef {
space: subst::SelfSpace,
index: 0,
ident: special_idents::type_self,
def_id: local_def(param_id),
bounds: Rc::new(ty::ParamBounds {
builtin_bounds: ty::empty_builtin_bounds(),
trait_bounds: vec!(self_trait_ref),
}),
default: None
};
ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
generics.types.push(subst::SelfSpace, def);
generics
}
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
generics: &ast::Generics,
base_index: uint)
-> ty::Generics {
base_generics: ty::Generics)
-> ty::Generics
{
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
ty_generics(ccx, subst::FnSpace, &early_lifetimes,
&generics.ty_params, base_generics)
}
fn ty_generics(ccx: &CrateCtxt,
space: subst::ParamSpace,
lifetimes: &Vec<ast::Lifetime>,
ty_params: &OwnedSlice<ast::TyParam>,
base_index: uint) -> ty::Generics {
return ty::Generics {
region_param_defs: Rc::new(lifetimes.iter().map(|l| {
types: &OwnedSlice<ast::TyParam>,
base_generics: ty::Generics)
-> ty::Generics
{
let mut result = base_generics;
for (i, l) in lifetimes.iter().enumerate() {
result.regions.push(space,
ty::RegionParameterDef { name: l.name,
def_id: local_def(l.id) }
}).collect()),
type_param_defs: Rc::new(ty_params.iter().enumerate().map(|(offset, param)| {
let existing_def_opt = {
let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
ty_param_defs.find(&param.id).map(|def| def.clone())
};
existing_def_opt.unwrap_or_else(|| {
let param_ty = ty::param_ty {idx: base_index + offset,
space: space,
index: i,
def_id: local_def(l.id) });
}
for (i, param) in types.iter().enumerate() {
let def = get_or_create_type_parameter_def(ccx, space, param, i);
debug!("def for param: {}", def.repr(ccx.tcx));
result.types.push(space, def);
}
return result;
fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
space: subst::ParamSpace,
param: &ast::TyParam,
index: uint)
-> ty::TypeParameterDef
{
match ccx.tcx.ty_param_defs.borrow().find(&param.id) {
Some(d) => { return (*d).clone(); }
None => { }
}
let param_ty = ty::ParamTy {space: space,
idx: index,
def_id: local_def(param.id)};
let bounds = Rc::new(compute_bounds(ccx,
param_ty,
@ -1055,7 +1026,8 @@ fn ty_generics(ccx: &CrateCtxt,
ty::walk_ty(ty, |t| {
match ty::get(t).sty {
ty::ty_param(p) => if p.idx > cur_idx {
ccx.tcx.sess.span_err(path.span,
ccx.tcx.sess.span_err(
path.span,
"type parameters with a default cannot use \
forward declared identifiers")
},
@ -1067,21 +1039,22 @@ fn ty_generics(ccx: &CrateCtxt,
});
let def = ty::TypeParameterDef {
space: space,
index: index,
ident: param.ident,
def_id: local_def(param.id),
bounds: bounds,
default: default
};
debug!("def for param: {}", def.repr(ccx.tcx));
ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
def
})
}).collect()),
};
}
fn compute_bounds(
ccx: &CrateCtxt,
param_ty: ty::param_ty,
param_ty: ty::ParamTy,
ast_bounds: &OwnedSlice<ast::TyParamBound>,
sized: ast::Sized,
ident: ast::Ident,
@ -1101,7 +1074,8 @@ fn ty_generics(ccx: &CrateCtxt,
for ast_bound in ast_bounds.iter() {
match *ast_bound {
TraitTyParamBound(ref b) => {
let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
let ty = ty::mk_param(ccx.tcx, param_ty.space,
param_ty.idx, param_ty.def_id);
let trait_ref = instantiate_trait_ref(ccx, b, ty);
if !ty::try_add_builtin_trait(
ccx.tcx, trait_ref.def_id,
@ -1117,15 +1091,15 @@ fn ty_generics(ccx: &CrateCtxt,
UnboxedFnTyParamBound(ref unboxed_function) => {
let rscope = ExplicitRscope;
let mut trait_ref =
astconv::trait_ref_for_unboxed_function(
ccx,
&rscope,
unboxed_function);
let self_ty = ty::mk_param(ccx.tcx,
param_ty.space,
param_ty.idx,
param_ty.def_id);
trait_ref.substs.self_ty = Some(self_ty);
let trait_ref =
astconv::trait_ref_for_unboxed_function(ccx,
&rscope,
unboxed_function,
Some(self_ty));
param_bounds.trait_bounds.push(Rc::new(trait_ref));
}
@ -1196,7 +1170,8 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
}
let ty_generics_for_fn_or_method =
ty_generics_for_fn_or_method(ccx, ast_generics, 0);
ty_generics_for_fn_or_method(ccx, ast_generics,
ty::Generics::empty());
let rb = BindingRscope::new(def_id.node);
let input_tys = decl.inputs
.iter()
@ -1225,19 +1200,17 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
}
pub fn mk_item_substs(ccx: &CrateCtxt,
ty_generics: &ty::Generics,
self_ty: Option<ty::t>)
ty_generics: &ty::Generics)
-> subst::Substs
{
let params: Vec<ty::t> =
ty_generics.type_param_defs().iter().enumerate().map(
|(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
let types =
ty_generics.types.map(
|def| ty::mk_param_from_def(ccx.tcx, def));
let regions: Vec<ty::Region> =
ty_generics.region_param_defs().iter().enumerate().map(
|(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.name)).collect();
let regions =
ty_generics.regions.map(
|def| ty::ReEarlyBound(def.def_id.node, def.space,
def.index, def.name));
subst::Substs {regions: subst::NonerasedRegions(regions),
self_ty: self_ty,
tps: params}
subst::Substs::new(types, regions)
}

View file

@ -53,7 +53,7 @@ use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
use middle::ty::{IntType, UintType};
use middle::ty::{BuiltinBounds};
use middle::ty;
use middle::typeck::infer::{then, ToUres};
use middle::typeck::infer::{ToUres};
use middle::typeck::infer::glb::Glb;
use middle::typeck::infer::lub::Lub;
use middle::typeck::infer::sub::Sub;
@ -84,80 +84,94 @@ pub trait Combine {
fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t>;
fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t>;
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<Vec<ty::t> > {
fn tps(&self,
space: subst::ParamSpace,
as_: &[ty::t],
bs: &[ty::t])
-> cres<Vec<ty::t>>
{
// FIXME(#5781) -- In general, we treat variance a bit wrong
// here. For historical reasons, we treat Self as
// contravariant and other tps as invariant. Both are wrong:
// Self may or may not be contravariant, and other tps do not
// need to be invariant.
// Note: type parameters are always treated as *invariant*
// (otherwise the type system would be unsound). In the
// future we could allow type parameters to declare a
// variance.
if as_.len() == bs.len() {
result::fold_(as_.iter().zip(bs.iter())
.map(|(a, b)| eq_tys(self, *a, *b)))
.then(|| Ok(Vec::from_slice(as_)))
} else {
Err(ty::terr_ty_param_size(expected_found(self,
if as_.len() != bs.len() {
return Err(ty::terr_ty_param_size(expected_found(self,
as_.len(),
bs.len())))
}
bs.len())));
}
fn self_tys(&self, a: Option<ty::t>, b: Option<ty::t>)
-> cres<Option<ty::t>> {
match space {
subst::SelfSpace => {
result::fold(as_
.iter()
.zip(bs.iter())
.map(|(a, b)| self.contratys(*a, *b)),
Vec::new(),
|mut v, a| { v.push(a); v })
}
match (a, b) {
(None, None) => {
Ok(None)
}
(Some(a), Some(b)) => {
// FIXME(#5781) this should be eq_tys
// eq_tys(self, a, b).then(|| Ok(Some(a)) )
self.contratys(a, b).and_then(|t| Ok(Some(t)))
}
(None, Some(_)) |
(Some(_), None) => {
// I think it should never happen that we unify two
// substs and one of them has a self_ty and one
// doesn't...? I could be wrong about this.
self.infcx().tcx.sess.bug("substitution a had a self_ty \
and substitution b didn't, or \
vice versa");
subst::TypeSpace | subst::FnSpace => {
try!(result::fold_(as_
.iter()
.zip(bs.iter())
.map(|(a, b)| eq_tys(self, *a, *b))));
Ok(Vec::from_slice(as_))
}
}
}
fn substs(&self,
item_def_id: ast::DefId,
as_: &subst::Substs,
bs: &subst::Substs)
a_subst: &subst::Substs,
b_subst: &subst::Substs)
-> cres<subst::Substs>
{
fn relate_region_params<C:Combine>(this: &C,
item_def_id: ast::DefId,
a: &subst::RegionSubsts,
b: &subst::RegionSubsts)
-> cres<subst::RegionSubsts> {
let tcx = this.infcx().tcx;
match (a, b) {
(&subst::ErasedRegions, _) | (_, &subst::ErasedRegions) => {
Ok(subst::ErasedRegions)
let variances = ty::item_variances(self.infcx().tcx, item_def_id);
let mut substs = subst::Substs::empty();
for &space in subst::ParamSpace::all().iter() {
let a_tps = a_subst.types.get_vec(space);
let b_tps = b_subst.types.get_vec(space);
let tps = if_ok!(self.tps(space,
a_tps.as_slice(),
b_tps.as_slice()));
let a_regions = a_subst.regions().get_vec(space);
let b_regions = b_subst.regions().get_vec(space);
let r_variances = variances.regions.get_vec(space);
let regions = if_ok!(relate_region_params(self,
item_def_id,
r_variances,
a_regions,
b_regions));
*substs.types.get_mut_vec(space) = tps;
*substs.mut_regions().get_mut_vec(space) = regions;
}
(&subst::NonerasedRegions(ref a_rs),
&subst::NonerasedRegions(ref b_rs)) => {
let variances = ty::item_variances(tcx, item_def_id);
let region_params = &variances.region_params;
let num_region_params = region_params.len();
return Ok(substs);
fn relate_region_params<C:Combine>(this: &C,
item_def_id: ast::DefId,
variances: &Vec<ty::Variance>,
a_rs: &Vec<ty::Region>,
b_rs: &Vec<ty::Region>)
-> cres<Vec<ty::Region>>
{
let tcx = this.infcx().tcx;
let num_region_params = variances.len();
debug!("relate_region_params(\
item_def_id={}, \
a_rs={}, \
b_rs={},
region_params={})",
variances={})",
item_def_id.repr(tcx),
a_rs.repr(tcx),
b_rs.repr(tcx),
region_params.repr(tcx));
variances.repr(tcx));
assert_eq!(num_region_params, a_rs.len());
assert_eq!(num_region_params, b_rs.len());
@ -165,7 +179,7 @@ pub trait Combine {
for i in range(0, num_region_params) {
let a_r = *a_rs.get(i);
let b_r = *b_rs.get(i);
let variance = *region_params.get(i);
let variance = *variances.get(i);
let r = match variance {
ty::Invariant => {
eq_regions(this, a_r, b_r)
@ -177,21 +191,9 @@ pub trait Combine {
};
rs.push(if_ok!(r));
}
Ok(subst::NonerasedRegions(rs))
Ok(rs)
}
}
}
let tps = if_ok!(self.tps(as_.tps.as_slice(), bs.tps.as_slice()));
let self_ty = if_ok!(self.self_tys(as_.self_ty, bs.self_ty));
let regions = if_ok!(relate_region_params(self,
item_def_id,
&as_.regions,
&bs.regions));
Ok(subst::Substs { regions: regions,
self_ty: self_ty,
tps: tps.clone() })
}
fn bare_fn_tys(&self, a: &ty::BareFnTy,
b: &ty::BareFnTy) -> cres<ty::BareFnTy> {

View file

@ -61,6 +61,7 @@ time of error detection.
use std::collections::HashSet;
use middle::def;
use middle::subst;
use middle::ty;
use middle::ty::{Region, ReFree};
use middle::typeck::infer;
@ -1055,9 +1056,10 @@ impl<'a> Rebuilder<'a> {
ty: _
} = ty::lookup_item_type(self.tcx, did);
let expected = generics.region_param_defs().len();
let lifetimes = &path.segments.last()
.unwrap().lifetimes;
let expected =
generics.regions.len(subst::TypeSpace);
let lifetimes =
&path.segments.last().unwrap().lifetimes;
let mut insert = Vec::new();
if lifetimes.len() == 0 {
let anon = self.cur_anon.get();

View file

@ -21,7 +21,8 @@ pub use middle::typeck::infer::resolve::{resolve_ivar, resolve_all};
pub use middle::typeck::infer::resolve::{resolve_nested_tvar};
pub use middle::typeck::infer::resolve::{resolve_rvar};
use std::collections::HashMap;
use middle::subst;
use middle::subst::Substs;
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid};
use middle::ty;
use middle::ty_fold;
@ -37,6 +38,7 @@ use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::unify::{ValsAndBindings, Root};
use middle::typeck::infer::error_reporting::ErrorReporting;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
@ -588,6 +590,7 @@ impl<'a> InferCtxt<'a> {
let vals = &mut ty_var_bindings.vals;
vals.insert(id, Root(Bounds { lb: None, ub: None }, 0u));
}
debug!("created type variable {}", TyVid(id));
return TyVid(id);
}
@ -623,13 +626,35 @@ impl<'a> InferCtxt<'a> {
pub fn region_vars_for_defs(&self,
span: Span,
defs: &[ty::RegionParameterDef])
defs: &Vec<ty::RegionParameterDef>)
-> Vec<ty::Region> {
defs.iter()
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
.collect()
}
pub fn fresh_substs_for_type(&self,
span: Span,
generics: &ty::Generics)
-> subst::Substs
{
/*!
* Given a set of generics defined on a type or impl, returns
* a substitution mapping each type/region parameter to a
* fresh inference variable.
*/
assert!(generics.types.len(subst::SelfSpace) == 0);
assert!(generics.types.len(subst::FnSpace) == 0);
assert!(generics.regions.len(subst::SelfSpace) == 0);
assert!(generics.regions.len(subst::FnSpace) == 0);
let type_parameter_count = generics.types.len(subst::TypeSpace);
let region_param_defs = generics.regions.get_vec(subst::TypeSpace);
let regions = self.region_vars_for_defs(span, region_param_defs);
let type_parameters = self.next_ty_vars(type_parameter_count);
subst::Substs::new_type(type_parameters, regions)
}
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
self.region_vars.new_bound(binder_id)
}

View file

@ -66,6 +66,7 @@ use driver::config;
use middle::def;
use middle::resolve;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty;
use util::common::time;
use util::ppaux::Repr;
@ -73,7 +74,6 @@ use util::ppaux;
use util::nodemap::{DefIdMap, FnvHashMap};
use std::cell::RefCell;
use std::rc::Rc;
use syntax::codemap::Span;
use syntax::print::pprust::*;
use syntax::{ast, ast_map, abi};
@ -87,9 +87,9 @@ pub mod coherence;
pub mod variance;
#[deriving(Clone, Encodable, Decodable, PartialEq, PartialOrd)]
pub enum param_index {
param_numbered(uint),
param_self
pub struct param_index {
pub space: subst::ParamSpace,
pub index: uint
}
#[deriving(Clone, Encodable, Decodable)]
@ -176,8 +176,9 @@ impl MethodCall {
pub type MethodMap = RefCell<FnvHashMap<MethodCall, MethodCallee>>;
pub type vtable_param_res = Vec<vtable_origin>;
// Resolutions for bounds of all parameters, left to right, for a given path.
pub type vtable_res = Vec<vtable_param_res>;
pub type vtable_res = VecPerParamSpace<vtable_param_res>;
#[deriving(Clone)]
pub enum vtable_origin {
@ -197,6 +198,14 @@ pub enum vtable_origin {
and the second is the bound number (identifying baz)
*/
vtable_param(param_index, uint),
/*
Asked to determine the vtable for ty_err. This is the value used
for the vtables of `Self` in a virtual call like `foo.bar()`
where `foo` is of object type. The same value is also used when
type errors occur.
*/
vtable_error,
}
impl Repr for vtable_origin {
@ -213,6 +222,10 @@ impl Repr for vtable_origin {
vtable_param(x, y) => {
format!("vtable_param({:?}, {:?})", x, y)
}
vtable_error => {
format!("vtable_error")
}
}
}
}
@ -220,33 +233,7 @@ impl Repr for vtable_origin {
pub type vtable_map = RefCell<FnvHashMap<MethodCall, vtable_res>>;
// Information about the vtable resolutions for a trait impl.
// Mostly the information is important for implementing default
// methods.
#[deriving(Clone)]
pub struct impl_res {
// resolutions for any bounded params on the trait definition
pub trait_vtables: vtable_res,
// resolutions for the trait /itself/ (and for supertraits)
pub self_vtables: vtable_param_res
}
impl Repr for impl_res {
#[cfg(stage0)]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("impl_res \\{trait_vtables={}, self_vtables={}\\}",
self.trait_vtables.repr(tcx),
self.self_vtables.repr(tcx))
}
#[cfg(not(stage0))]
fn repr(&self, tcx: &ty::ctxt) -> String {
format!("impl_res {{trait_vtables={}, self_vtables={}}}",
self.trait_vtables.repr(tcx),
self.self_vtables.repr(tcx))
}
}
pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;
pub type impl_vtable_map = RefCell<DefIdMap<vtable_res>>;
pub struct CrateCtxt<'a> {
// A mapping from method call sites to traits that have that method.
@ -268,8 +255,7 @@ pub fn write_substs_to_tcx(tcx: &ty::ctxt,
node_id,
item_substs.repr(tcx));
assert!(item_substs.substs.tps.iter().
all(|t| !ty::type_needs_infer(*t)));
assert!(item_substs.substs.types.all(|t| !ty::type_needs_infer(*t)));
tcx.item_substs.borrow_mut().insert(node_id, item_substs);
}
@ -290,8 +276,8 @@ pub fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
ty::ty_param_bounds_and_ty {
generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
region_param_defs: Rc::new(Vec::new())},
generics: ty::Generics {types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty()},
ty: t
}
}

View file

@ -195,14 +195,15 @@ represents the "variance transform" as defined in the paper:
use std::collections::HashMap;
use arena;
use arena::Arena;
use rl = middle::resolve_lifetime;
use middle::subst;
use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
use middle::ty;
use std::fmt;
use std::rc::Rc;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
use syntax::owned_slice::OwnedSlice;
use syntax::visit;
use syntax::visit::Visitor;
use util::ppaux::Repr;
@ -266,11 +267,17 @@ struct TermsContext<'a> {
inferred_infos: Vec<InferredInfo<'a>> ,
}
enum ParamKind { TypeParam, RegionParam, SelfParam }
#[deriving(Show)]
enum ParamKind {
TypeParam,
RegionParam
}
struct InferredInfo<'a> {
item_id: ast::NodeId,
kind: ParamKind,
space: ParamSpace,
index: uint,
param_id: ast::NodeId,
term: VarianceTermPtr<'a>,
}
@ -288,9 +295,8 @@ fn determine_parameters_to_be_inferred<'a>(tcx: &'a ty::ctxt,
// cache and share the variance struct used for items with
// no type/region parameters
empty_variances: Rc::new(ty::ItemVariances {
self_param: None,
type_params: OwnedSlice::empty(),
region_params: OwnedSlice::empty()
types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty()
})
};
@ -303,12 +309,15 @@ impl<'a> TermsContext<'a> {
fn add_inferred(&mut self,
item_id: ast::NodeId,
kind: ParamKind,
space: ParamSpace,
index: uint,
param_id: ast::NodeId) {
let inf_index = InferredIndex(self.inferred_infos.len());
let term = self.arena.alloc(|| InferredTerm(inf_index));
self.inferred_infos.push(InferredInfo { item_id: item_id,
kind: kind,
space: space,
index: index,
param_id: param_id,
term: term });
let newly_added = self.inferred_map.insert(param_id, inf_index);
@ -338,7 +347,7 @@ impl<'a> Visitor<()> for TermsContext<'a> {
// item are assigned continuous indices.
match item.node {
ast::ItemTrait(..) => {
self.add_inferred(item.id, SelfParam, 0, item.id);
self.add_inferred(item.id, TypeParam, SelfSpace, 0, item.id);
}
_ => { }
}
@ -348,10 +357,10 @@ impl<'a> Visitor<()> for TermsContext<'a> {
ast::ItemStruct(_, ref generics) |
ast::ItemTrait(ref generics, _, _, _) => {
for (i, p) in generics.lifetimes.iter().enumerate() {
self.add_inferred(item.id, RegionParam, i, p.id);
self.add_inferred(item.id, RegionParam, TypeSpace, i, p.id);
}
for (i, p) in generics.ty_params.iter().enumerate() {
self.add_inferred(item.id, TypeParam, i, p.id);
self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);
}
// If this item has no type or lifetime parameters,
@ -399,9 +408,9 @@ struct ConstraintContext<'a> {
// are indexed by the `ParamKind` (type, lifetime, self). Note
// that there are no marker types for self, so the entries for
// self are always None.
invariant_lang_items: [Option<ast::DefId>, ..3],
covariant_lang_items: [Option<ast::DefId>, ..3],
contravariant_lang_items: [Option<ast::DefId>, ..3],
invariant_lang_items: [Option<ast::DefId>, ..2],
covariant_lang_items: [Option<ast::DefId>, ..2],
contravariant_lang_items: [Option<ast::DefId>, ..2],
// These are pointers to common `ConstantTerm` instances
covariant: VarianceTermPtr<'a>,
@ -422,9 +431,9 @@ struct Constraint<'a> {
fn add_constraints_from_crate<'a>(terms_cx: TermsContext<'a>,
krate: &ast::Crate)
-> ConstraintContext<'a> {
let mut invariant_lang_items = [None, ..3];
let mut covariant_lang_items = [None, ..3];
let mut contravariant_lang_items = [None, ..3];
let mut invariant_lang_items = [None, ..2];
let mut covariant_lang_items = [None, ..2];
let mut contravariant_lang_items = [None, ..2];
covariant_lang_items[TypeParam as uint] =
terms_cx.tcx.lang_items.covariant_type();
@ -547,7 +556,7 @@ impl<'a> ConstraintContext<'a> {
let tcx = self.terms_cx.tcx;
assert!(is_lifetime(&tcx.map, param_id));
match tcx.named_region_map.find(&param_id) {
Some(&ast::DefEarlyBoundRegion(_, lifetime_decl_id))
Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
=> lifetime_decl_id,
Some(_) => fail!("should not encounter non early-bound cases"),
@ -611,6 +620,7 @@ impl<'a> ConstraintContext<'a> {
param_def_id: ast::DefId,
item_def_id: ast::DefId,
kind: ParamKind,
space: ParamSpace,
index: uint)
-> VarianceTermPtr<'a> {
/*!
@ -637,9 +647,8 @@ impl<'a> ConstraintContext<'a> {
// variance already inferred, just look it up.
let variances = ty::item_variances(self.tcx(), item_def_id);
let variance = match kind {
SelfParam => variances.self_param.unwrap(),
TypeParam => *variances.type_params.get(index),
RegionParam => *variances.region_params.get(index),
TypeParam => *variances.types.get(space, index),
RegionParam => *variances.regions.get(space, index),
};
self.constant_term(variance)
}
@ -736,17 +745,50 @@ impl<'a> ConstraintContext<'a> {
ty::ty_enum(def_id, ref substs) |
ty::ty_struct(def_id, ref substs) => {
let item_type = ty::lookup_item_type(self.tcx(), def_id);
self.add_constraints_from_substs(def_id, &item_type.generics,
substs, variance);
let generics = &item_type.generics;
// All type parameters on enums and structs should be
// in the TypeSpace.
assert!(generics.types.get_vec(subst::SelfSpace).is_empty());
assert!(generics.types.get_vec(subst::FnSpace).is_empty());
assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
self.add_constraints_from_substs(
def_id,
generics.types.get_vec(subst::TypeSpace),
generics.regions.get_vec(subst::TypeSpace),
substs,
variance);
}
ty::ty_trait(box ty::TyTrait { def_id, ref substs, .. }) => {
let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
self.add_constraints_from_substs(def_id, &trait_def.generics,
substs, variance);
let generics = &trait_def.generics;
// Traits DO have a Self type parameter, but it is
// erased from object types.
assert!(!generics.types.get_vec(subst::SelfSpace).is_empty() &&
substs.types.get_vec(subst::SelfSpace).is_empty());
// Traits never declare region parameters in the self
// space.
assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
// Traits never declare type/region parameters in the
// fn space.
assert!(generics.types.get_vec(subst::FnSpace).is_empty());
assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
self.add_constraints_from_substs(
def_id,
generics.types.get_vec(subst::TypeSpace),
generics.regions.get_vec(subst::TypeSpace),
substs,
variance);
}
ty::ty_param(ty::param_ty { def_id: ref def_id, .. }) => {
ty::ty_param(ty::ParamTy { def_id: ref def_id, .. }) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
match self.terms_cx.inferred_map.find(&def_id.node) {
Some(&index) => {
@ -760,12 +802,6 @@ impl<'a> ConstraintContext<'a> {
}
}
ty::ty_self(ref def_id) => {
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
let index = self.inferred_index(def_id.node);
self.add_constraint(index, variance);
}
ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) |
ty::ty_closure(box ty::ClosureTy {
ref sig,
@ -796,28 +832,28 @@ impl<'a> ConstraintContext<'a> {
/// object, etc) appearing in a context with ambient variance `variance`
fn add_constraints_from_substs(&mut self,
def_id: ast::DefId,
generics: &ty::Generics,
type_param_defs: &Vec<ty::TypeParameterDef>,
region_param_defs: &Vec<ty::RegionParameterDef>,
substs: &subst::Substs,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?})", def_id);
for (i, p) in generics.type_param_defs().iter().enumerate() {
for p in type_param_defs.iter() {
let variance_decl =
self.declared_variance(p.def_id, def_id, TypeParam, i);
self.declared_variance(p.def_id, def_id, TypeParam,
p.space, p.index);
let variance_i = self.xform(variance, variance_decl);
self.add_constraints_from_ty(*substs.tps.get(i), variance_i);
let substs_ty = *substs.types.get(p.space, p.index);
self.add_constraints_from_ty(substs_ty, variance_i);
}
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref rps) => {
for (i, p) in generics.region_param_defs().iter().enumerate() {
for p in region_param_defs.iter() {
let variance_decl =
self.declared_variance(p.def_id, def_id, RegionParam, i);
self.declared_variance(p.def_id, def_id,
RegionParam, p.space, p.index);
let variance_i = self.xform(variance, variance_decl);
self.add_constraints_from_region(*rps.get(i), variance_i);
}
}
let substs_r = *substs.regions().get(p.space, p.index);
self.add_constraints_from_region(substs_r, variance_i);
}
}
@ -839,7 +875,7 @@ impl<'a> ConstraintContext<'a> {
region: ty::Region,
variance: VarianceTermPtr<'a>) {
match region {
ty::ReEarlyBound(param_id, _, _) => {
ty::ReEarlyBound(param_id, _, _, _) => {
if self.is_to_be_inferred(param_id) {
let index = self.inferred_index(param_id);
self.add_constraint(index, variance);
@ -931,7 +967,7 @@ impl<'a> SolveContext<'a> {
let new_value = glb(variance, old_value);
if old_value != new_value {
debug!("Updating inferred {} (node {}) \
from {:?} to {:?} due to {}",
from {} to {} due to {}",
inferred,
self.terms_cx
.inferred_infos
@ -965,32 +1001,29 @@ impl<'a> SolveContext<'a> {
let num_inferred = self.terms_cx.num_inferred();
while index < num_inferred {
let item_id = inferred_infos.get(index).item_id;
let mut self_param = None;
let mut type_params = vec!();
let mut region_params = vec!();
let mut types = VecPerParamSpace::empty();
let mut regions = VecPerParamSpace::empty();
while index < num_inferred &&
inferred_infos.get(index).item_id == item_id {
let info = inferred_infos.get(index);
let variance = *solutions.get(index);
debug!("Index {} Info {} / {} / {} Variance {}",
index, info.index, info.kind, info.space, variance);
match info.kind {
SelfParam => {
assert!(self_param.is_none());
self_param = Some(*solutions.get(index));
}
TypeParam => {
type_params.push(*solutions.get(index));
types.push(info.space, variance);
}
RegionParam => {
region_params.push(*solutions.get(index));
regions.push(info.space, variance);
}
}
index += 1;
}
let item_variances = ty::ItemVariances {
self_param: self_param,
type_params: OwnedSlice::from_vec(type_params),
region_params: OwnedSlice::from_vec(region_params)
types: types,
regions: regions
};
debug!("item_id={} item_variances={}",
item_id,

View file

@ -9,17 +9,18 @@
// except according to those terms.
use middle::def;
use middle::subst;
use middle::subst::Subst;
use middle::subst::{VecPerParamSpace,Subst};
use middle::ty::{ReSkolemized, ReVar};
use middle::ty::{BoundRegion, BrAnon, BrNamed};
use middle::ty::{BrFresh, ctxt};
use middle::ty::{mt, t, param_ty};
use middle::ty::{mt, t, ParamTy};
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
ReEmpty};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_self, ty_tup};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
use middle::ty;
use middle::typeck;
@ -188,7 +189,7 @@ pub fn region_to_str(cx: &ctxt, prefix: &str, space: bool, region: Region) -> St
// `explain_region()` or `note_and_explain_region()`.
match region {
ty::ReScope(_) => prefix.to_string(),
ty::ReEarlyBound(_, _, name) => {
ty::ReEarlyBound(_, _, _, name) => {
token::get_name(name).get().to_string()
}
ty::ReLateBound(_, br) => bound_region_to_str(cx, prefix, space, br),
@ -375,7 +376,7 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String {
}
ty_infer(infer_ty) => infer_ty.to_str(),
ty_err => "[type error]".to_string(),
ty_param(param_ty {idx: id, def_id: did}) => {
ty_param(ParamTy {idx: id, def_id: did, ..}) => {
let ident = match cx.ty_param_defs.borrow().find(&did.node) {
Some(def) => token::get_ident(def.ident).get().to_string(),
// This can only happen when a type mismatch error happens and
@ -391,22 +392,18 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String {
format!("{}:{:?}", ident, did)
}
}
ty_self(..) => "Self".to_string(),
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
let base = ty::item_path_str(cx, did);
parameterized(cx,
base.as_slice(),
&substs.regions,
substs.tps.as_slice(),
did,
false)
let generics = ty::lookup_item_type(cx, did).generics;
parameterized(cx, base.as_slice(), substs, &generics)
}
ty_trait(box ty::TyTrait {
def_id: did, ref substs, store, ref bounds
}) => {
let base = ty::item_path_str(cx, did);
let ty = parameterized(cx, base.as_slice(), &substs.regions,
substs.tps.as_slice(), did, true);
let trait_def = ty::lookup_trait_def(cx, did);
let ty = parameterized(cx, base.as_slice(),
substs, &trait_def.generics);
let bound_sep = if bounds.is_empty() { "" } else { ":" };
let bound_str = bounds.repr(cx);
format!("{}{}{}{}",
@ -429,39 +426,38 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String {
pub fn parameterized(cx: &ctxt,
base: &str,
regions: &subst::RegionSubsts,
tps: &[ty::t],
did: ast::DefId,
is_trait: bool)
-> String {
substs: &subst::Substs,
generics: &ty::Generics)
-> String
{
let mut strs = Vec::new();
match *regions {
match substs.regions {
subst::ErasedRegions => { }
subst::NonerasedRegions(ref regions) => {
for &r in regions.iter() {
strs.push(region_to_str(cx, "", false, r))
let s = region_to_str(cx, "", false, r);
if !s.is_empty() {
strs.push(s)
} else {
// This happens when the value of the region
// parameter is not easily serialized. This may be
// because the user omitted it in the first place,
// or because it refers to some block in the code,
// etc. I'm not sure how best to serialize this.
strs.push(format!("'_"));
}
}
}
}
let generics = if is_trait {
ty::lookup_trait_def(cx, did).generics.clone()
} else {
ty::lookup_item_type(cx, did).generics
};
let ty_params = generics.type_param_defs();
let tps = substs.types.get_vec(subst::TypeSpace);
let ty_params = generics.types.get_vec(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults {
// We should have a borrowed version of substs instead of cloning.
let mut substs = subst::Substs {
tps: Vec::from_slice(tps),
regions: regions.clone(),
self_ty: None
};
let num_defaults = if has_defaults && !cx.sess.verbose() {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
substs.tps.pop();
match def.default {
Some(default) => default.subst(cx, &substs) == actual,
Some(default) => default.subst(cx, substs) == actual,
None => false
}
}).count()
@ -473,6 +469,12 @@ pub fn parameterized(cx: &ctxt,
strs.push(ty_to_str(cx, *t))
}
if cx.sess.verbose() {
for t in substs.types.get_vec(subst::SelfSpace).iter() {
strs.push(format!("for {}", t.repr(cx)));
}
}
if strs.len() > 0u {
format!("{}<{}>", base, strs.connect(","))
} else {
@ -554,6 +556,12 @@ impl<T:Repr> Repr for Vec<T> {
}
}
impl Repr for def::Def {
fn repr(&self, _tcx: &ctxt) -> String {
format!("{:?}", *self)
}
}
impl Repr for ty::TypeParameterDef {
fn repr(&self, tcx: &ctxt) -> String {
format!("TypeParameterDef({:?}, {})", self.def_id,
@ -577,10 +585,18 @@ impl Repr for ty::t {
impl Repr for subst::Substs {
fn repr(&self, tcx: &ctxt) -> String {
format!("substs(regions={}, self_ty={}, tps={})",
self.regions.repr(tcx),
self.self_ty.repr(tcx),
self.tps.repr(tcx))
format!("Substs[types={}, regions={}]",
self.types.repr(tcx),
self.regions.repr(tcx))
}
}
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
fn repr(&self, tcx: &ctxt) -> String {
format!("[{};{};{}]",
self.get_vec(subst::TypeSpace).repr(tcx),
self.get_vec(subst::SelfSpace).repr(tcx),
self.get_vec(subst::FnSpace).repr(tcx))
}
}
@ -630,6 +646,12 @@ impl Repr for ast::Expr {
}
}
impl Repr for ast::Path {
fn repr(&self, _tcx: &ctxt) -> String {
format!("path({})", pprust::path_to_str(self))
}
}
impl Repr for ast::Item {
fn repr(&self, tcx: &ctxt) -> String {
format!("item({})", tcx.map.node_to_str(self.id))
@ -665,9 +687,10 @@ impl Repr for ty::BoundRegion {
impl Repr for ty::Region {
fn repr(&self, tcx: &ctxt) -> String {
match *self {
ty::ReEarlyBound(id, index, name) => {
format!("ReEarlyBound({}, {}, {})",
ty::ReEarlyBound(id, space, index, name) => {
format!("ReEarlyBound({}, {}, {}, {})",
id,
space,
index,
token::get_name(name))
}
@ -697,9 +720,7 @@ impl Repr for ty::Region {
}
ty::ReInfer(ReSkolemized(id, ref bound_region)) => {
format!("re_skolemized({}, {})",
id,
bound_region.repr(tcx))
format!("re_skolemized({}, {})", id, bound_region.repr(tcx))
}
ty::ReEmpty => {
@ -753,18 +774,18 @@ impl Repr for ty::ty_param_bounds_and_ty {
impl Repr for ty::Generics {
fn repr(&self, tcx: &ctxt) -> String {
format!("Generics(type_param_defs: {}, region_param_defs: {})",
self.type_param_defs().repr(tcx),
self.region_param_defs().repr(tcx))
format!("Generics(types: {}, regions: {})",
self.types.repr(tcx),
self.regions.repr(tcx))
}
}
impl Repr for ty::ItemVariances {
fn repr(&self, tcx: &ctxt) -> String {
format!("IterVariances(self_param={}, type_params={}, region_params={})",
self.self_param.repr(tcx),
self.type_params.repr(tcx),
self.region_params.repr(tcx))
format!("ItemVariances(types={}, \
regions={})",
self.types.repr(tcx),
self.regions.repr(tcx))
}
}
@ -952,23 +973,8 @@ impl UserString for ty::BuiltinBounds {
impl UserString for ty::TraitRef {
fn user_string(&self, tcx: &ctxt) -> String {
let base = ty::item_path_str(tcx, self.def_id);
if tcx.sess.verbose() && self.substs.self_ty.is_some() {
let mut all_tps = self.substs.tps.clone();
for &t in self.substs.self_ty.iter() { all_tps.push(t); }
parameterized(tcx,
base.as_slice(),
&self.substs.regions,
all_tps.as_slice(),
self.def_id,
true)
} else {
parameterized(tcx,
base.as_slice(),
&self.substs.regions,
self.substs.tps.as_slice(),
self.def_id,
true)
}
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics)
}
}

View file

@ -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),
_ => {}
};

View file

@ -208,14 +208,6 @@ impl Generics {
}
}
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
pub enum DefRegion {
DefStaticRegion,
DefEarlyBoundRegion(/* index */ uint, /* lifetime decl */ NodeId),
DefLateBoundRegion(/* binder_id */ NodeId, /* depth */ uint, /* lifetime decl */ NodeId),
DefFreeRegion(/* block scope */ NodeId, /* lifetime decl */ NodeId),
}
// The set of MetaItems that define the compilation environment of the crate,
// used to drive conditional compilation
pub type CrateConfig = Vec<Gc<MetaItem>>;

View file

@ -45,11 +45,16 @@ impl Trait<int> for S2 {
fn foo<'a>() {
let _ = S::new::<int,f64>(1, 1.0);
//~^ ERROR the impl referenced by this path needs 1 type parameter, but 0 type parameters were supplied
let _ = S::<'a,int>::new::<f64>(1, 1.0); //~ ERROR expected 0 lifetime parameters
//~^ ERROR too many type parameters provided
let _ = S::<'a,int>::new::<f64>(1, 1.0);
//~^ ERROR too many lifetime parameters provided
let _: S2 = Trait::new::<int,f64>(1, 1.0);
//~^ ERROR the trait referenced by this path needs 1 type parameter, but 0 type parameters were supplied
let _: S2 = Trait::<'a,int>::new::<f64>(1, 1.0); //~ ERROR expected 0 lifetime parameters
//~^ ERROR too many type parameters provided
let _: S2 = Trait::<'a,int>::new::<f64>(1, 1.0);
//~^ ERROR too many lifetime parameters provided
}
fn main() {}

View file

@ -18,7 +18,5 @@ impl<A, B, C = (A, B)> Foo<A, B, C> {
fn main() {
Foo::<int>::new();
//~^ ERROR the impl referenced by this path needs at least 2 type parameters,
// but 1 was supplied
//~^^^ ERROR not enough type parameters provided: expected at least 2, found 1
//~^ ERROR too few type parameters provided
}

View file

@ -20,7 +20,5 @@ impl<T, A = Heap> Vec<T, A> {
fn main() {
Vec::<int, Heap, bool>::new();
//~^ ERROR the impl referenced by this path needs at most 2 type parameters,
// but 3 were supplied
//~^^^ ERROR too many type parameters provided: expected at most 2, found 3
//~^ ERROR too many type parameters provided
}

View file

@ -12,7 +12,7 @@ fn main() {
let a = Some(box 1);
match a {
Ok(a) => //~ ERROR: mismatched types
println!("{}",a), //~ ERROR: failed to find an implementation of trait
println!("{}",a),
None => fail!()
}
}

View file

@ -15,7 +15,6 @@ pub fn main() {
// the actual arm `Result<T, E>` has two. typeck should not be
// tricked into looking up a non-existing second type parameter.
let _x: uint = match Some(1u) {
//~^ ERROR mismatched types: expected `uint` but found `<generic #0>`
Ok(u) => u, //~ ERROR mismatched types: expected `core::option::Option<uint>`
Err(e) => fail!(e) //~ ERROR mismatched types: expected `core::option::Option<uint>`
};

View file

@ -15,7 +15,6 @@ fn foo(x: Whatever) {
match x {
Some(field) => field.access(),
//~^ ERROR: mismatched types: expected `Whatever` but found
//~^^ ERROR: does not implement any method in scope named `access`
}
}

View file

@ -14,7 +14,7 @@
// Regions that just appear in normal spots are contravariant:
#[rustc_variance]
struct Test2<'a, 'b, 'c> { //~ ERROR region_params=[-, -, -]
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
x: &'a int,
y: &'b [int],
c: &'c str
@ -23,7 +23,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR region_params=[-, -, -]
// Those same annotations in function arguments become covariant:
#[rustc_variance]
struct Test3<'a, 'b, 'c> { //~ ERROR region_params=[+, +, +]
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
x: extern "Rust" fn(&'a int),
y: extern "Rust" fn(&'b [int]),
c: extern "Rust" fn(&'c str),
@ -32,7 +32,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR region_params=[+, +, +]
// Mutability induces invariance:
#[rustc_variance]
struct Test4<'a, 'b> { //~ ERROR region_params=[-, o]
struct Test4<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
x: &'a mut &'b int,
}
@ -40,7 +40,7 @@ struct Test4<'a, 'b> { //~ ERROR region_params=[-, o]
// contravariant context:
#[rustc_variance]
struct Test5<'a, 'b> { //~ ERROR region_params=[+, o]
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
x: extern "Rust" fn(&'a mut &'b int),
}
@ -50,21 +50,21 @@ struct Test5<'a, 'b> { //~ ERROR region_params=[+, o]
// argument list occurs in an invariant context.
#[rustc_variance]
struct Test6<'a, 'b> { //~ ERROR region_params=[-, o]
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
x: &'a mut extern "Rust" fn(&'b int),
}
// No uses at all is bivariant:
#[rustc_variance]
struct Test7<'a> { //~ ERROR region_params=[*]
struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
x: int
}
// Try enums too.
#[rustc_variance]
enum Test8<'a, 'b, 'c> { //~ ERROR region_params=[+, -, o]
enum Test8<'a, 'b, 'c> { //~ ERROR regions=[[+, -, o];[];[]]
Test8A(extern "Rust" fn(&'a int)),
Test8B(&'b [int]),
Test8C(&'b mut &'c str),

View file

@ -13,29 +13,29 @@
// Try enums too.
#[rustc_variance]
enum Base<'a, 'b, 'c, 'd> { //~ ERROR region_params=[+, -, o, *]
enum Base<'a, 'b, 'c, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
Test8A(extern "Rust" fn(&'a int)),
Test8B(&'b [int]),
Test8C(&'b mut &'c str),
}
#[rustc_variance]
struct Derived1<'w, 'x, 'y, 'z> { //~ ERROR region_params=[*, o, -, +]
struct Derived1<'w, 'x, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
f: Base<'z, 'y, 'x, 'w>
}
#[rustc_variance] // Combine - and + to yield o
struct Derived2<'a, 'b, 'c> { //~ ERROR region_params=[o, o, *]
struct Derived2<'a, 'b, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
f: Base<'a, 'a, 'b, 'c>
}
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
struct Derived3<'a, 'b, 'c> { //~ ERROR region_params=[o, -, *]
struct Derived3<'a, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
f: Base<'a, 'b, 'a, 'c>
}
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
struct Derived4<'a, 'b, 'c> { //~ ERROR region_params=[+, -, o]
struct Derived4<'a, 'b, 'c> { //~ ERROR regions=[[+, -, o];[];[]]
f: Base<'a, 'b, 'c, 'a>
}