collect.rs 53.2 KB
Newer Older
V
Virgile Andreani 已提交
1
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*

# Collect phase

The collect phase of type check has the job of visiting all items,
determining their type, and writing that type into the `tcx.tcache`
table.  Despite its name, this table does not really operate as a
*cache*, at least not for the types of items defined within the
current crate: we assume that after the collect phase, the types of
all local items will be present in the table.

Unlike most of the types that are present in Rust, the types computed
for each item are in fact polytypes.  In "layman's terms", this means
that they are generic types that may have type parameters (more
mathematically phrased, they are universally quantified over a set of
type parameters).  Polytypes are represented by an instance of
27 28 29
`ty::Polytype`.  This combines the core type along with a list of the
bounds for each parameter.  Type parameters themselves are represented
as `ty_param()` instances.
30 31 32

*/

33

34
use metadata::csearch;
35
use middle::def;
36
use middle::lang_items::SizedTraitLangItem;
37
use middle::resolve_lifetime;
38
use middle::subst;
39
use middle::subst::{Substs};
40
use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
41
use middle::ty::{Polytype};
42
use middle::ty;
43
use middle::ty_fold::TypeFolder;
44
use middle::typeck::astconv::{AstConv, ty_of_arg};
45
use middle::typeck::astconv::{ast_ty_to_ty};
46
use middle::typeck::astconv;
47
use middle::typeck::infer;
48
use middle::typeck::rscope::*;
N
Niko Matsakis 已提交
49
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
50
use middle::typeck;
51
use util::ppaux;
52
use util::ppaux::Repr;
53

54
use std::collections::{HashMap, HashSet};
55
use std::rc::Rc;
56 57
use std::gc::Gc;

58
use syntax::abi;
59 60
use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound};
use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
61 62
use syntax::ast;
use syntax::ast_map;
63
use syntax::ast_util::{local_def, split_trait_methods, PostExpansionMethod};
64
use syntax::codemap::Span;
65
use syntax::codemap;
66
use syntax::owned_slice::OwnedSlice;
67 68
use syntax::parse::token::special_idents;
use syntax::parse::token;
69
use syntax::print::pprust::{path_to_string};
70
use syntax::visit;
71

E
Eduard Burtescu 已提交
72
struct CollectItemTypesVisitor<'a> {
E
Eduard Burtescu 已提交
73
    ccx: &'a CrateCtxt<'a>
74 75
}

E
Eduard Burtescu 已提交
76
impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
77
    fn visit_item(&mut self, i: &ast::Item, _: ()) {
78 79 80
        convert(self.ccx, i);
        visit::walk_item(self, i, ());
    }
81
    fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
82 83 84 85 86
        convert_foreign(self.ccx, i);
        visit::walk_foreign_item(self, i, ());
    }
}

E
Eduard Burtescu 已提交
87
pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
88
    fn collect_intrinsic_type(ccx: &CrateCtxt,
89
                              lang_item: ast::DefId) {
90
        let ty::Polytype { ty: ty, .. } =
P
Philipp Brüschweiler 已提交
91
            ccx.get_item_ty(lang_item);
92
        ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
93 94
    }

A
Alex Crichton 已提交
95 96 97 98 99 100
    match ccx.tcx.lang_items.ty_desc() {
        Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
    }
    match ccx.tcx.lang_items.opaque() {
        Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
    }
P
Philipp Brüschweiler 已提交
101

102
    let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
103
    visit::walk_crate(&mut visitor, krate, ());
104 105
}

106
pub trait ToTy {
107
    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
108 109
}

E
Eduard Burtescu 已提交
110
impl<'a> ToTy for CrateCtxt<'a> {
111
    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
112 113 114 115
        ast_ty_to_ty(self, rs, ast_ty)
    }
}

E
Eduard Burtescu 已提交
116 117
impl<'a> AstConv for CrateCtxt<'a> {
    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
118

119
    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
120
        if id.krate != ast::LOCAL_CRATE {
P
Patrick Walton 已提交
121 122 123
            return csearch::get_type(self.tcx, id)
        }

124
        match self.tcx.map.find(id.node) {
125
            Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
126
            Some(ast_map::NodeForeignItem(foreign_item)) => {
127
                let abi = self.tcx.map.get_foreign_abi(id.node);
128
                ty_of_foreign_item(self, &*foreign_item, abi)
P
Patrick Walton 已提交
129
            }
130 131
            x => {
                self.tcx.sess.bug(format!("unexpected sort of node \
132 133
                                           in get_item_ty(): {:?}",
                                          x).as_slice());
134 135 136 137
            }
        }
    }

E
Eduard Burtescu 已提交
138
    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
139 140 141
        get_trait_def(self, id)
    }

142
    fn ty_infer(&self, span: Span) -> ty::t {
J
Jakub Wieczorek 已提交
143 144
        span_err!(self.tcx.sess, span, E0121,
                  "the type placeholder `_` is not allowed within types on item signatures.");
145
        ty::mk_err()
146 147 148
    }
}

149
pub fn get_enum_variant_types(ccx: &CrateCtxt,
150
                              enum_ty: ty::t,
151
                              variants: &[ast::P<ast::Variant>],
152
                              generics: &ast::Generics) {
153 154 155
    let tcx = ccx.tcx;

    // Create a set of parameter types shared among all the variants.
D
Daniel Micay 已提交
156
    for variant in variants.iter() {
157 158
        // Nullary enum constructors get turned into constants; n-ary enum
        // constructors get turned into functions.
159 160
        let scope = variant.node.id;
        let result_ty = match variant.node.kind {
161
            ast::TupleVariantKind(ref args) if args.len() > 0 => {
162
                let rs = ExplicitRscope;
163
                let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
164
                ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
165
            }
166

167
            ast::TupleVariantKind(_) => {
168
                enum_ty
169
            }
170

171
            ast::StructVariantKind(struct_def) => {
172
                let pty = Polytype {
173
                    generics: ty_generics_for_type(ccx, generics),
174 175
                    ty: enum_ty
                };
176

177
                convert_struct(ccx, &*struct_def, pty, variant.node.id);
178

179 180
                let input_tys: Vec<_> = struct_def.fields.iter().map(
                    |f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
181
                ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
182
            }
183
        };
184

185
        let pty = Polytype {
186
            generics: ty_generics_for_type(ccx, generics),
187 188
            ty: result_ty
        };
189

190
        tcx.tcache.borrow_mut().insert(local_def(variant.node.id), pty);
191

192
        write_ty_to_tcx(tcx, variant.node.id, result_ty);
193 194 195
    }
}

196 197 198
pub fn ensure_trait_methods(ccx: &CrateCtxt,
                            trait_id: ast::NodeId,
                            trait_def: &ty::TraitDef) {
199
    let tcx = ccx.tcx;
200 201
    match tcx.map.get(trait_id) {
        ast_map::NodeItem(item) => {
202
            match item.node {
203
                ast::ItemTrait(_, _, _, ref trait_items) => {
204
                    // For each method, construct a suitable ty::Method and
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
                    // store it into the `tcx.impl_or_trait_items` table:
                    for trait_item in trait_items.iter() {
                        match *trait_item {
                            ast::RequiredMethod(_) |
                            ast::ProvidedMethod(_) => {
                                let ty_method = Rc::new(match *trait_item {
                                    ast::RequiredMethod(ref m) => {
                                        ty_method_of_trait_method(
                                            ccx,
                                            trait_id,
                                            &trait_def.generics,
                                            &m.id,
                                            &m.ident,
                                            &m.explicit_self,
                                            m.abi,
                                            &m.generics,
                                            &m.fn_style,
                                            &*m.decl)
                                    }
                                    ast::ProvidedMethod(ref m) => {
                                        ty_method_of_trait_method(
                                            ccx,
                                            trait_id,
                                            &trait_def.generics,
                                            &m.id,
                                            &m.pe_ident(),
                                            m.pe_explicit_self(),
                                            m.pe_abi(),
                                            m.pe_generics(),
                                            &m.pe_fn_style(),
                                            &*m.pe_fn_decl())
                                    }
                                });

                                if ty_method.explicit_self ==
                                        ty::StaticExplicitSelfCategory {
                                    make_static_method_ty(ccx, &*ty_method);
                                }

                                tcx.impl_or_trait_items
                                   .borrow_mut()
                                   .insert(ty_method.def_id,
                                           ty::MethodTraitItem(ty_method));
248 249
                            }
                        }
250 251
                    }

252
                    // Add an entry mapping
253 254 255 256 257 258 259 260 261 262 263 264
                    let trait_item_def_ids =
                        Rc::new(trait_items.iter()
                                           .map(|ti| {
                            match *ti {
                                ast::RequiredMethod(ref ty_method) => {
                                    ty::MethodTraitItemId(local_def(
                                            ty_method.id))
                                }
                                ast::ProvidedMethod(ref method) => {
                                    ty::MethodTraitItemId(local_def(
                                            method.id))
                                }
265
                            }
266
                        }).collect());
267 268

                    let trait_def_id = local_def(trait_id);
269 270
                    tcx.trait_item_def_ids.borrow_mut()
                        .insert(trait_def_id, trait_item_def_ids);
271
                }
272
                _ => {} // Ignore things that aren't traits.
273 274 275
            }
        }
        _ => { /* Ignore things that aren't traits */ }
276 277
    }

278 279 280
    fn make_static_method_ty(ccx: &CrateCtxt, m: &ty::Method) {
        ccx.tcx.tcache.borrow_mut().insert(
            m.def_id,
281
            Polytype {
282 283
                generics: m.generics.clone(),
                ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
284 285
    }

286
    fn ty_method_of_trait_method(this: &CrateCtxt,
287
                                 trait_id: ast::NodeId,
288
                                 trait_generics: &ty::Generics,
289
                                 m_id: &ast::NodeId,
290
                                 m_ident: &ast::Ident,
291
                                 m_explicit_self: &ast::ExplicitSelf,
292
                                 m_abi: abi::Abi,
293
                                 m_generics: &ast::Generics,
294
                                 m_fn_style: &ast::FnStyle,
295 296 297 298
                                 m_decl: &ast::FnDecl)
                                 -> ty::Method {
        let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));

299 300 301 302 303 304
        let (fty, explicit_self_category) =
            astconv::ty_of_method(this,
                                  *m_id,
                                  *m_fn_style,
                                  trait_self_ty,
                                  *m_explicit_self,
305 306 307 308 309 310
                                  m_decl,
                                  m_abi);
        let ty_generics =
            ty_generics_for_fn_or_method(this,
                                         m_generics,
                                         (*trait_generics).clone());
311 312
        ty::Method::new(
            *m_ident,
313
            ty_generics,
314
            fty,
315
            explicit_self_category,
316
            // assume public, because this is only invoked on trait methods
317
            ast::Public,
318
            local_def(*m_id),
319
            TraitContainer(local_def(trait_id)),
320
            None
321
        )
322 323 324
    }
}

325
pub fn convert_field(ccx: &CrateCtxt,
326
                     struct_generics: &ty::Generics,
327 328
                     v: &ast::StructField,
                     origin: ast::DefId) -> ty::field_ty {
329
    let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
330
    write_ty_to_tcx(ccx.tcx, v.node.id, tt);
331
    /* add the field to the tcache */
332
    ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
333
                                       ty::Polytype {
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
                                           generics: struct_generics.clone(),
                                           ty: tt
                                       });

    match v.node.kind {
        ast::NamedField(ident, visibility) => {
            ty::field_ty {
                name: ident.name,
                id: local_def(v.node.id),
                vis: visibility,
                origin: origin,
            }
        }
        ast::UnnamedField(visibility) => {
            ty::field_ty {
                name: special_idents::unnamed_field.name,
                id: local_def(v.node.id),
                vis: visibility,
                origin: origin,
            }
        }
    }
356 357
}

358
fn convert_methods(ccx: &CrateCtxt,
359
                   container: ImplOrTraitItemContainer,
360
                   ms: &[Gc<ast::Method>],
361 362
                   untransformed_rcvr_ty: ty::t,
                   rcvr_ty_generics: &ty::Generics,
363
                   rcvr_visibility: ast::Visibility) {
364
    let tcx = ccx.tcx;
365
    let mut seen_methods = HashSet::new();
366
    for m in ms.iter() {
367
        if !seen_methods.insert(m.pe_ident().repr(ccx.tcx)) {
368 369 370
            tcx.sess.span_err(m.span, "duplicate method in trait impl");
        }

E
Eduard Burtescu 已提交
371 372
        let mty = Rc::new(ty_of_method(ccx,
                                       container,
373
                                       &**m,
E
Eduard Burtescu 已提交
374
                                       untransformed_rcvr_ty,
375
                                       rcvr_ty_generics,
E
Eduard Burtescu 已提交
376
                                       rcvr_visibility));
377
        let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
378
        debug!("method {} (id {}) has type {}",
379
                m.pe_ident().repr(ccx.tcx),
380
                m.id,
381
                fty.repr(ccx.tcx));
382 383
        tcx.tcache.borrow_mut().insert(
            local_def(m.id),
384
            Polytype {
385
                generics: mty.generics.clone(),
386 387
                ty: fty
            });
388

389
        write_ty_to_tcx(tcx, m.id, fty);
390

391 392 393
        tcx.impl_or_trait_items
           .borrow_mut()
           .insert(mty.def_id, ty::MethodTraitItem(mty));
394
    }
395 396

    fn ty_of_method(ccx: &CrateCtxt,
397
                    container: ImplOrTraitItemContainer,
398
                    m: &ast::Method,
399
                    untransformed_rcvr_ty: ty::t,
400 401
                    rcvr_ty_generics: &ty::Generics,
                    rcvr_visibility: ast::Visibility)
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
                    -> ty::Method {
        // FIXME(pcwalton): Hack until we have syntax in stage0 for snapshots.
        let real_abi = match container {
            ty::TraitContainer(trait_id) => {
                if ccx.tcx.lang_items.fn_trait() == Some(trait_id) ||
                        ccx.tcx.lang_items.fn_mut_trait() == Some(trait_id) ||
                        ccx.tcx.lang_items.fn_once_trait() == Some(trait_id) {
                    abi::RustCall
                } else {
                    m.pe_abi()
                }
            }
            _ => m.pe_abi(),
        };

417 418 419 420 421 422
        let (fty, explicit_self_category) =
            astconv::ty_of_method(ccx,
                                  m.id,
                                  m.pe_fn_style(),
                                  untransformed_rcvr_ty,
                                  *m.pe_explicit_self(),
423 424
                                  &*m.pe_fn_decl(),
                                  real_abi);
425 426 427 428 429

        // if the method specifies a visibility, use that, otherwise
        // inherit the visibility from the impl (so `foo` in `pub impl
        // { fn foo(); }` is public, but private in `priv impl { fn
        // foo(); }`).
430
        let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
431

432
        let m_ty_generics =
433
            ty_generics_for_fn_or_method(ccx, m.pe_generics(),
434
                                         (*rcvr_ty_generics).clone());
435
        ty::Method::new(m.pe_ident(),
436 437
                        m_ty_generics,
                        fty,
438
                        explicit_self_category,
439 440 441 442
                        method_vis,
                        local_def(m.id),
                        container,
                        None)
443 444 445
    }
}

446
pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
447
                                 span: Span,
448
                                 generics: &ast::Generics,
449
                                 thing: &'static str) {
D
Daniel Micay 已提交
450
    for ty_param in generics.ty_params.iter() {
451
        if ty_param.bounds.len() > 0 {
J
Jakub Wieczorek 已提交
452 453
            span_err!(ccx.tcx.sess, span, E0122,
                      "trait bounds are not allowed in {} definitions", thing);
454 455 456 457
        }
    }
}

458
pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
459
    let tcx = ccx.tcx;
460
    debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
461
    match it.node {
462 463 464 465
        // These don't define types.
        ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
        ast::ItemEnum(ref enum_definition, ref generics) => {
            ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
466 467
            let pty = ty_of_item(ccx, it);
            write_ty_to_tcx(tcx, it.id, pty.ty);
468
            get_enum_variant_types(ccx,
469
                                   pty.ty,
470
                                   enum_definition.variants.as_slice(),
471 472
                                   generics);
        },
473 474 475 476
        ast::ItemImpl(ref generics,
                      ref opt_trait_ref,
                      selfty,
                      ref impl_items) => {
477
            let ty_generics = ty_generics_for_type(ccx, generics);
478
            let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
479 480
            write_ty_to_tcx(tcx, it.id, selfty);

481
            tcx.tcache.borrow_mut().insert(local_def(it.id),
482
                                Polytype {
483 484
                                    generics: ty_generics.clone(),
                                    ty: selfty});
485

486 487 488 489 490 491 492 493 494 495 496
            // If there is a trait reference, treat the methods as always public.
            // This is to work around some incorrect behavior in privacy checking:
            // when the method belongs to a trait, it should acquire the privacy
            // from the trait, not the impl. Forcing the visibility to be public
            // makes things sorta work.
            let parent_visibility = if opt_trait_ref.is_some() {
                ast::Public
            } else {
                it.vis
            };

497 498 499 500 501 502 503 504 505 506 507
            let mut methods = Vec::new();
            for impl_item in impl_items.iter() {
                match *impl_item {
                    ast::MethodImplItem(ref method) => {
                        check_method_self_type(ccx,
                                               &BindingRscope::new(method.id),
                                               selfty,
                                               method.pe_explicit_self());
                        methods.push(*method);
                    }
                }
508 509
            }

510 511
            convert_methods(ccx,
                            ImplContainer(local_def(it.id)),
512
                            methods.as_slice(),
513
                            selfty,
514
                            &ty_generics,
515 516 517
                            parent_visibility);

            for trait_ref in opt_trait_ref.iter() {
518
                instantiate_trait_ref(ccx, trait_ref, selfty);
519 520
            }
        },
521
        ast::ItemTrait(_, _, _, ref trait_methods) => {
522 523
            let trait_def = trait_def_of_item(ccx, it);

524 525 526 527 528 529
            for trait_method in trait_methods.iter() {
                let self_type = ty::mk_param(ccx.tcx,
                                             subst::SelfSpace,
                                             0,
                                             local_def(it.id));
                match *trait_method {
530
                    ast::RequiredMethod(ref type_method) => {
531 532 533 534 535 536
                        let rscope = BindingRscope::new(type_method.id);
                        check_method_self_type(ccx,
                                               &rscope,
                                               self_type,
                                               &type_method.explicit_self)
                    }
537
                    ast::ProvidedMethod(ref method) => {
538 539 540 541 542 543 544 545
                        check_method_self_type(ccx,
                                               &BindingRscope::new(method.id),
                                               self_type,
                                               method.pe_explicit_self())
                    }
                }
            }

546 547
            // Run convert_methods on the provided methods.
            let (_, provided_methods) =
548
                split_trait_methods(trait_methods.as_slice());
549
            let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id));
550 551
            convert_methods(ccx,
                            TraitContainer(local_def(it.id)),
552
                            provided_methods.as_slice(),
553 554 555 556 557 558 559
                            untransformed_rcvr_ty,
                            &trait_def.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.
560
            ensure_trait_methods(ccx, it.id, &*trait_def);
561 562 563 564
        },
        ast::ItemStruct(struct_def, ref generics) => {
            ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");

565
            // Write the class type.
566 567
            let pty = ty_of_item(ccx, it);
            write_ty_to_tcx(tcx, it.id, pty.ty);
568

569
            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
570

571 572 573
            // Write the super-struct type, if it exists.
            match struct_def.super_struct {
                Some(ty) => {
574
                    let supserty = ccx.to_ty(&ExplicitRscope, &*ty);
575 576 577 578 579
                    write_ty_to_tcx(tcx, it.id, supserty);
                },
                _ => {},
            }

580
            convert_struct(ccx, &*struct_def, pty, it.id);
581 582 583
        },
        ast::ItemTy(_, ref generics) => {
            ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
R
Russell 已提交
584 585
            let tpt = ty_of_item(ccx, it);
            write_ty_to_tcx(tcx, it.id, tpt.ty);
586 587 588 589 590
        },
        _ => {
            // This call populates the type cache with the converted type
            // of the item in passing. All we have to do here is to write
            // it into the node type table.
591 592
            let pty = ty_of_item(ccx, it);
            write_ty_to_tcx(tcx, it.id, pty.ty);
593
        },
594 595
    }
}
596

597
pub fn convert_struct(ccx: &CrateCtxt,
598
                      struct_def: &ast::StructDef,
599
                      pty: ty::Polytype,
600
                      id: ast::NodeId) {
601 602
    let tcx = ccx.tcx;

603 604 605
    // Write the type of each of the members and check for duplicate fields.
    let mut seen_fields: HashMap<ast::Name, Span> = HashMap::new();
    let field_tys = struct_def.fields.iter().map(|f| {
606
        let result = convert_field(ccx, &pty.generics, f, local_def(id));
607 608 609 610

        if result.name != special_idents::unnamed_field.name {
            let dup = match seen_fields.find(&result.name) {
                Some(prev_span) => {
J
Jakub Wieczorek 已提交
611 612 613 614
                    span_err!(tcx.sess, f.span, E0124,
                              "field `{}` is already declared",
                              token::get_name(result.name));
                    span_note!(tcx.sess, *prev_span, "previously declared here");
615 616 617 618 619 620 621 622 623 624 625 626 627 628
                    true
                },
                None => false,
            };
            // FIXME(#6393) this whole dup thing is just to satisfy
            // the borrow checker :-(
            if !dup {
                seen_fields.insert(result.name, f.span);
            }
        }

        result
    }).collect();

E
Eduard Burtescu 已提交
629
    tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
630 631 632 633 634 635

    let super_struct = match struct_def.super_struct {
        Some(t) => match t.node {
            ast::TyPath(_, _, path_id) => {
                let def_map = tcx.def_map.borrow();
                match def_map.find(&path_id) {
636
                    Some(&def::DefStruct(def_id)) => {
637 638 639 640 641 642
                        // FIXME(#12511) Check for cycles in the inheritance hierarchy.
                        // Check super-struct is virtual.
                        match tcx.map.find(def_id.node) {
                            Some(ast_map::NodeItem(i)) => match i.node {
                                ast::ItemStruct(struct_def, _) => {
                                    if !struct_def.is_virtual {
J
Jakub Wieczorek 已提交
643 644 645
                                        span_err!(tcx.sess, t.span, E0126,
                                                  "struct inheritance is only \
                                                   allowed from virtual structs");
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
                                    }
                                },
                                _ => {},
                            },
                            _ => {},
                        }

                        Some(def_id)
                    },
                    _ => None,
                }
            }
            _ => None,
        },
        None => None,
    };
    tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);

664
    let substs = mk_item_substs(ccx, &pty.generics);
665
    let selfty = ty::mk_struct(tcx, local_def(id), substs);
666 667 668

    // If this struct is enum-like or tuple-like, create the type of its
    // constructor.
669 670 671 672 673 674
    match struct_def.ctor_id {
        None => {}
        Some(ctor_id) => {
            if struct_def.fields.len() == 0 {
                // Enum-like.
                write_ty_to_tcx(tcx, ctor_id, selfty);
675

676
                tcx.tcache.borrow_mut().insert(local_def(ctor_id), pty);
677
            } else if struct_def.fields.get(0).node.kind.is_unnamed() {
678
                // Tuple-like.
679
                let inputs: Vec<_> = struct_def.fields.iter().map(
680
                        |field| tcx.tcache.borrow().get(
681
                            &local_def(field.node.id)).ty).collect();
682 683 684 685
                let ctor_fn_ty = ty::mk_ctor_fn(tcx,
                                                ctor_id,
                                                inputs.as_slice(),
                                                selfty);
686
                write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
687
                tcx.tcache.borrow_mut().insert(local_def(ctor_id),
688 689
                                  Polytype {
                    generics: pty.generics,
690 691
                    ty: ctor_fn_ty
                });
692
            }
693
        }
694
    }
695 696
}

697
pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
698
    // As above, this call populates the type table with the converted
699
    // type of the foreign item. We simply write it into the node type
700
    // table.
701 702 703 704 705

    // For reasons I cannot fully articulate, I do so hate the AST
    // map, and I regard each time that I use it as a personal and
    // moral failing, but at the moment it seems like the only
    // convenient way to extract the ABI. - ndm
706
    let abi = ccx.tcx.map.get_foreign_abi(i.id);
707

708 709
    let pty = ty_of_foreign_item(ccx, i, abi);
    write_ty_to_tcx(ccx.tcx, i.id, pty.ty);
710

711
    ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
712 713
}

714
pub fn instantiate_trait_ref(ccx: &CrateCtxt,
715
                             ast_trait_ref: &ast::TraitRef,
E
Eduard Burtescu 已提交
716
                             self_ty: ty::t) -> Rc<ty::TraitRef> {
717 718 719
    /*!
     * Instantiates the path for the given trait reference, assuming that
     * it's bound to a valid trait type. Returns the def_id for the defining
V
Virgile Andreani 已提交
720
     * trait. Fails if the type is a type other than a trait type.
721
     */
722

N
Niko Matsakis 已提交
723 724
    // FIXME(#5121) -- distinguish early vs late lifetime params
    let rscope = ExplicitRscope;
725

726
    match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
727
        def::DefTrait(trait_did) => {
728 729
            let trait_ref =
                astconv::ast_path_to_trait_ref(
J
James Miller 已提交
730
                    ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
P
Patrick Walton 已提交
731

732
            ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
E
Eduard Burtescu 已提交
733 734
                                                   trait_ref.clone());
            trait_ref
735 736 737 738
        }
        _ => {
            ccx.tcx.sess.span_fatal(
                ast_trait_ref.path.span,
K
kud1ing 已提交
739
                format!("`{}` is not a trait",
740
                        path_to_string(&ast_trait_ref.path)).as_slice());
741 742 743
        }
    }
}
744

E
Eduard Burtescu 已提交
745
fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
746
    if trait_id.krate != ast::LOCAL_CRATE {
P
Patrick Walton 已提交
747 748 749
        return ty::lookup_trait_def(ccx.tcx, trait_id)
    }

750
    match ccx.tcx.map.get(trait_id.node) {
751
        ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
752 753 754 755
        _ => {
            ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
                                     trait_id.node).as_slice())
        }
756 757
    }
}
758

E
Eduard Burtescu 已提交
759
pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
760 761
    let def_id = local_def(it.id);
    let tcx = ccx.tcx;
762
    match tcx.trait_defs.borrow().find(&def_id) {
E
Eduard Burtescu 已提交
763
        Some(def) => return def.clone(),
764
        _ => {}
765
    }
P
Patrick Walton 已提交
766

N
Nick Cameron 已提交
767 768 769
    let (generics, unbound, supertraits) = match it.node {
        ast::ItemTrait(ref generics, ref unbound, ref supertraits, _) => {
            (generics, unbound, supertraits)
770 771 772 773
        }
        ref s => {
            tcx.sess.span_bug(
                it.span,
774
                format!("trait_def_of_item invoked on {:?}", s).as_slice());
775
        }
776 777 778 779 780 781 782 783 784 785
    };

    let substs = mk_trait_substs(ccx, it.id, generics);

    let ty_generics = ty_generics_for_trait(ccx,
                                            it.id,
                                            &substs,
                                            generics);

    let builtin_bounds =
N
Nick Cameron 已提交
786
        ensure_supertraits(ccx, it.id, it.span, supertraits, unbound);
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810

    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()
811
                    .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
812
                                                     subst::TypeSpace,
813 814
                                                     i,
                                                     def.lifetime.name))
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
                    .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>,
N
Nick Cameron 已提交
835
                          unbound: &Option<ast::TyParamBound>)
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
                          -> 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.
J
Jakub Wieczorek 已提交
865 866
                    span_err!(tcx.sess, sp, E0127,
                              "duplicate supertrait in trait declaration");
867 868 869 870 871 872 873
                    break;
                } else {
                    ty_trait_refs.push(trait_ref);
                }
            }
        }

N
Nick Cameron 已提交
874
        add_unsized_bound(ccx, unbound, &mut bounds, "trait", sp);
875 876 877
        tcx.supertraits.borrow_mut().insert(local_def(id),
                                            Rc::new(ty_trait_refs));
        bounds
878 879 880
    }
}

881
pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
882
                  -> ty::Polytype {
883 884
    let def_id = local_def(it.id);
    let tcx = ccx.tcx;
885
    match tcx.tcache.borrow().find(&def_id) {
886
        Some(pty) => return pty.clone(),
887
        _ => {}
888
    }
889
    match it.node {
890
        ast::ItemStatic(t, _, _) => {
891
            let typ = ccx.to_ty(&ExplicitRscope, &*t);
892
            let pty = no_params(typ);
893

894 895
            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
            return pty;
896
        }
897
        ast::ItemFn(decl, fn_style, abi, ref generics, _) => {
898 899
            let ty_generics = ty_generics_for_fn_or_method(ccx, generics,
                                                           ty::Generics::empty());
900 901
            let tofd = astconv::ty_of_bare_fn(ccx,
                                              it.id,
902
                                              fn_style,
903
                                              abi,
904
                                              &*decl);
905
            let pty = Polytype {
906
                generics: ty_generics,
907 908 909
                ty: ty::mk_bare_fn(ccx.tcx, tofd)
            };
            debug!("type of {} (id {}) is {}",
910
                    token::get_ident(it.ident),
911
                    it.id,
912
                    ppaux::ty_to_string(tcx, pty.ty));
913

914 915
            ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
            return pty;
916
        }
917
        ast::ItemTy(t, ref generics) => {
918
            match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
919
                Some(pty) => return pty.clone(),
920
                None => { }
921
            }
922

923
            let pty = {
924
                let ty = ccx.to_ty(&ExplicitRscope, &*t);
925
                Polytype {
926
                    generics: ty_generics_for_type(ccx, generics),
927 928 929 930
                    ty: ty
                }
            };

931 932
            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
            return pty;
933
        }
934
        ast::ItemEnum(_, ref generics) => {
935
            // Create a new generic polytype.
936
            let ty_generics = ty_generics_for_type(ccx, generics);
937
            let substs = mk_item_substs(ccx, &ty_generics);
938
            let t = ty::mk_enum(tcx, local_def(it.id), substs);
939
            let pty = Polytype {
940 941 942
                generics: ty_generics,
                ty: t
            };
943

944 945
            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
            return pty;
946
        }
947
        ast::ItemTrait(..) => {
948
            tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
949
        }
950
        ast::ItemStruct(_, ref generics) => {
951
            let ty_generics = ty_generics_for_type(ccx, generics);
952
            let substs = mk_item_substs(ccx, &ty_generics);
953
            let t = ty::mk_struct(tcx, local_def(it.id), substs);
954
            let pty = Polytype {
955 956 957
                generics: ty_generics,
                ty: t
            };
958

959 960
            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
            return pty;
961
        }
962
        ast::ItemImpl(..) | ast::ItemMod(_) |
963
        ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
964 965 966
    }
}

967
pub fn ty_of_foreign_item(ccx: &CrateCtxt,
968
                          it: &ast::ForeignItem,
969
                          abi: abi::Abi) -> ty::Polytype
970
{
971
    match it.node {
972
        ast::ForeignItemFn(fn_decl, ref generics) => {
973
            ty_of_foreign_fn_decl(ccx,
974
                                  &*fn_decl,
975
                                  local_def(it.id),
976
                                  generics,
977
                                  abi)
978
        }
979
        ast::ForeignItemStatic(t, _) => {
980
            ty::Polytype {
981
                generics: ty::Generics::empty(),
982
                ty: ast_ty_to_ty(ccx, &ExplicitRscope, &*t)
983 984
            }
        }
985 986 987
    }
}

E
Eduard Burtescu 已提交
988 989
fn ty_generics_for_type(ccx: &CrateCtxt,
                        generics: &ast::Generics)
990 991 992 993 994 995 996
                        -> ty::Generics {
    ty_generics(ccx,
                subst::TypeSpace,
                &generics.lifetimes,
                &generics.ty_params,
                ty::Generics::empty(),
                &generics.where_clause)
997 998 999 1000 1001 1002
}

fn ty_generics_for_trait(ccx: &CrateCtxt,
                         trait_id: ast::NodeId,
                         substs: &subst::Substs,
                         generics: &ast::Generics)
1003 1004 1005 1006 1007 1008 1009
                         -> ty::Generics {
    let mut generics = ty_generics(ccx,
                                   subst::TypeSpace,
                                   &generics.lifetimes,
                                   &generics.ty_params,
                                   ty::Generics::empty(),
                                   &generics.where_clause);
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035

    // 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
1036 1037
}

E
Eduard Burtescu 已提交
1038 1039
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
                                generics: &ast::Generics,
1040
                                base_generics: ty::Generics)
1041
                                -> ty::Generics {
1042
    let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1043 1044 1045 1046 1047 1048
    ty_generics(ccx,
                subst::FnSpace,
                &early_lifetimes,
                &generics.ty_params,
                base_generics,
                &generics.where_clause)
1049 1050
}

N
Nick Cameron 已提交
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
fn add_unsized_bound(ccx: &CrateCtxt,
                     unbound: &Option<ast::TyParamBound>,
                     bounds: &mut ty::BuiltinBounds,
                     desc: &str,
                     span: Span) {
    let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
    match unbound {
        &Some(TraitTyParamBound(ref tpb)) => {
            // #FIXME(8559) currently requires the unbound to be built-in.
            let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
            match kind_id {
                Ok(kind_id) if trait_def_id != kind_id => {
                    ccx.tcx.sess.span_warn(span,
                                           format!("default bound relaxed \
                                                    for a {}, but this does \
                                                    nothing because the given \
                                                    bound is not a default. \
                                                    Only `Sized?` is supported.",
                                                   desc).as_slice());
                    ty::try_add_builtin_trait(ccx.tcx,
                                              kind_id,
                                              bounds);
                }
                _ => {}
            }
        }
        _ if kind_id.is_ok() => {
            ty::try_add_builtin_trait(ccx.tcx,
                                      kind_id.unwrap(),
                                      bounds);
        }
        // No lang item for Sized, so we can't add it as a bound.
        _ => {}
    }
}

E
Eduard Burtescu 已提交
1088
fn ty_generics(ccx: &CrateCtxt,
1089
               space: subst::ParamSpace,
1090
               lifetimes: &Vec<ast::LifetimeDef>,
1091
               types: &OwnedSlice<ast::TyParam>,
1092 1093 1094
               base_generics: ty::Generics,
               where_clause: &ast::WhereClause)
               -> ty::Generics {
1095 1096 1097
    let mut result = base_generics;

    for (i, l) in lifetimes.iter().enumerate() {
1098
        let def = ty::RegionParameterDef { name: l.lifetime.name,
1099 1100
                                           space: space,
                                           index: i,
1101
                                           def_id: local_def(l.lifetime.id) };
1102 1103
        debug!("ty_generics: def for region param: {}", def);
        result.regions.push(space, def);
1104
    }
1105

1106
    for (i, param) in types.iter().enumerate() {
1107 1108 1109 1110 1111
        let def = get_or_create_type_parameter_def(ccx,
                                                   space,
                                                   param,
                                                   i,
                                                   where_clause);
1112
        debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
1113 1114
        result.types.push(space, def);
    }
1115

1116 1117 1118 1119 1120
    return result;

    fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
                                        space: subst::ParamSpace,
                                        param: &ast::TyParam,
1121 1122 1123
                                        index: uint,
                                        where_clause: &ast::WhereClause)
                                        -> ty::TypeParameterDef {
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
        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,
                                            &param.bounds,
N
Nick Cameron 已提交
1135
                                            &param.unbound,
1136
                                            param.ident,
1137 1138
                                            param.span,
                                            where_clause));
1139 1140 1141 1142 1143 1144 1145
        let default = param.default.map(|path| {
            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
            let cur_idx = param_ty.idx;

            ty::walk_ty(ty, |t| {
                match ty::get(t).sty {
                    ty::ty_param(p) => if p.idx > cur_idx {
J
Jakub Wieczorek 已提交
1146 1147 1148
                    span_err!(ccx.tcx.sess, path.span, E0128,
                              "type parameters with a default cannot use \
                               forward declared identifiers");
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
                    },
                    _ => {}
                }
            });

            ty
        });

        let def = ty::TypeParameterDef {
            space: space,
            index: index,
            ident: param.ident,
            def_id: local_def(param.id),
            bounds: bounds,
            default: default
        };

        ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());

        def
    }
1170

1171 1172 1173 1174 1175 1176 1177 1178
    fn compute_bounds(ccx: &CrateCtxt,
                      param_ty: ty::ParamTy,
                      ast_bounds: &OwnedSlice<ast::TyParamBound>,
                      unbound: &Option<ast::TyParamBound>,
                      ident: ast::Ident,
                      span: Span,
                      where_clause: &ast::WhereClause)
                      -> ty::ParamBounds {
1179 1180 1181 1182
        /*!
         * Translate the AST's notion of ty param bounds (which are an
         * enum consisting of a newtyped Ty or a region) to ty's
         * notion of ty param bounds, which can either be user-defined
1183
         * traits, or the built-in trait (formerly known as kind): Send.
1184 1185
         */

1186
        let mut param_bounds = ty::ParamBounds {
K
Kevin Butler 已提交
1187
            builtin_bounds: ty::empty_builtin_bounds(),
1188
            trait_bounds: Vec::new()
1189
        };
D
Daniel Micay 已提交
1190
        for ast_bound in ast_bounds.iter() {
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
            compute_bound(ccx, &mut param_bounds, param_ty, ast_bound);
        }
        for predicate in where_clause.predicates.iter() {
            let predicate_param_id = ccx.tcx
                                        .def_map
                                        .borrow()
                                        .find(&predicate.id)
                                        .expect("compute_bounds(): resolve \
                                                 didn't resolve the type \
                                                 parameter identifier in a \
                                                 `where` clause")
                                        .def_id();
            if param_ty.def_id != predicate_param_id {
                continue
            }
            for bound in predicate.bounds.iter() {
                compute_bound(ccx, &mut param_bounds, param_ty, bound);
1208
            }
1209 1210
        }

N
Nick Cameron 已提交
1211 1212 1213 1214 1215
        add_unsized_bound(ccx,
                          unbound,
                          &mut param_bounds.builtin_bounds,
                          "type parameter",
                          span);
1216 1217 1218

        check_bounds_compatible(ccx.tcx, &param_bounds, ident, span);

J
Jason Fager 已提交
1219 1220
        param_bounds.trait_bounds.sort_by(|a,b| a.def_id.cmp(&b.def_id));

1221
        param_bounds
1222
    }
1223

1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
    /// Translates the AST's notion of a type parameter bound to
    /// typechecking's notion of the same, and pushes the resulting bound onto
    /// the appropriate section of `param_bounds`.
    fn compute_bound(ccx: &CrateCtxt,
                     param_bounds: &mut ty::ParamBounds,
                     param_ty: ty::ParamTy,
                     ast_bound: &ast::TyParamBound) {
        match *ast_bound {
            TraitTyParamBound(ref b) => {
                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,
                        &mut param_bounds.builtin_bounds) {
                    // Must be a user-defined trait
                    param_bounds.trait_bounds.push(trait_ref);
                }
            }

            StaticRegionTyParamBound => {
                param_bounds.builtin_bounds.add(ty::BoundStatic);
            }

            UnboxedFnTyParamBound(ref unboxed_function) => {
                let rscope = ExplicitRscope;
                let self_ty = ty::mk_param(ccx.tcx,
                                           param_ty.space,
                                           param_ty.idx,
                                           param_ty.def_id);
                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));
            }

            OtherRegionTyParamBound(span) => {
                if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
                    ccx.tcx.sess.span_err(
                        span,
                        "only the 'static lifetime is accepted here.");
                }
            }
        }
    }

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
    fn check_bounds_compatible(tcx: &ty::ctxt,
                               param_bounds: &ty::ParamBounds,
                               ident: ast::Ident,
                               span: Span) {
        // Currently the only bound which is incompatible with other bounds is
        // Sized/Unsized.
        if !param_bounds.builtin_bounds.contains_elem(ty::BoundSized) {
            ty::each_bound_trait_and_supertraits(tcx,
                                                 param_bounds.trait_bounds.as_slice(),
                                                 |trait_ref| {
                let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
N
Nick Cameron 已提交
1283
                if trait_def.bounds.contains_elem(ty::BoundSized) {
J
Jakub Wieczorek 已提交
1284 1285 1286 1287 1288
                    span_err!(tcx.sess, span, E0129,
                              "incompatible bounds on type parameter {}, \
                               bound {} does not allow unsized type",
                              token::get_ident(ident),
                              ppaux::trait_ref_to_string(tcx, &*trait_ref));
1289 1290 1291 1292 1293
                }
                true
            });
        }
    }
1294 1295
}

1296
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1297
                             decl: &ast::FnDecl,
1298
                             def_id: ast::DefId,
1299
                             ast_generics: &ast::Generics,
1300
                             abi: abi::Abi)
1301
                          -> ty::Polytype {
1302 1303 1304 1305

    for i in decl.inputs.iter() {
        match (*i).pat.node {
            ast::PatIdent(_, _, _) => (),
1306
            ast::PatWild(ast::PatWildSingle) => (),
J
Jakub Wieczorek 已提交
1307 1308 1309 1310
            _ => {
                span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
                          "patterns aren't allowed in foreign function declarations");
            }
1311 1312 1313
        }
    }

1314
    let ty_generics_for_fn_or_method =
1315 1316
        ty_generics_for_fn_or_method(ccx, ast_generics,
                                     ty::Generics::empty());
1317
    let rb = BindingRscope::new(def_id.node);
1318 1319 1320 1321
    let input_tys = decl.inputs
                        .iter()
                        .map(|a| ty_of_arg(ccx, &rb, a, None))
                        .collect();
1322

1323
    let output_ty = ast_ty_to_ty(ccx, &rb, &*decl.output);
1324

1325 1326 1327
    let t_fn = ty::mk_bare_fn(
        ccx.tcx,
        ty::BareFnTy {
1328
            abi: abi,
1329
            fn_style: ast::UnsafeFn,
1330 1331 1332 1333
            sig: ty::FnSig {binder_id: def_id.node,
                            inputs: input_tys,
                            output: output_ty,
                            variadic: decl.variadic}
1334
        });
1335
    let pty = Polytype {
1336
        generics: ty_generics_for_fn_or_method,
1337 1338
        ty: t_fn
    };
1339

1340 1341
    ccx.tcx.tcache.borrow_mut().insert(def_id, pty.clone());
    return pty;
1342 1343
}

1344
pub fn mk_item_substs(ccx: &CrateCtxt,
1345
                      ty_generics: &ty::Generics)
1346
                      -> subst::Substs
1347
{
1348 1349 1350
    let types =
        ty_generics.types.map(
            |def| ty::mk_param_from_def(ccx.tcx, def));
1351

1352 1353 1354 1355
    let regions =
        ty_generics.regions.map(
            |def| ty::ReEarlyBound(def.def_id.node, def.space,
                                   def.index, def.name));
1356

1357
    subst::Substs::new(types, regions)
1358
}
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368

/// Verifies that the explicit self type of a method matches the impl or
/// trait.
fn check_method_self_type<RS:RegionScope>(
                          crate_context: &CrateCtxt,
                          rs: &RS,
                          required_type: ty::t,
                          explicit_self: &ast::ExplicitSelf) {
    match explicit_self.node {
        ast::SelfExplicit(ref ast_type, _) => {
1369
            let typ = crate_context.to_ty(rs, &**ast_type);
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
            let base_type = match ty::get(typ).sty {
                ty::ty_rptr(_, tm) => tm.ty,
                ty::ty_uniq(typ) => typ,
                _ => typ,
            };
            let infcx = infer::new_infer_ctxt(crate_context.tcx);
            drop(typeck::require_same_types(crate_context.tcx,
                                            Some(&infcx),
                                            false,
                                            explicit_self.span,
                                            base_type,
                                            required_type,
                                            || {
                format!("mismatched self type: expected `{}`",
                        ppaux::ty_to_string(crate_context.tcx, required_type))
            }));
            infcx.resolve_regions_and_report_errors();
        }
        _ => {}
    }
}