astconv.rs 66.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.

S
Steve Klabnik 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
//! Conversion from AST representation of types to the ty.rs
//! representation.  The main routine here is `ast_ty_to_ty()`: each use
//! is parameterized by an instance of `AstConv` and a `RegionScope`.
//!
//! The parameterization of `ast_ty_to_ty()` is because it behaves
//! somewhat differently during the collect and check phases,
//! particularly with respect to looking up the types of top-level
//! items.  In the collect phase, the crate context is used as the
//! `AstConv` instance; in this phase, the `get_item_ty()` function
//! triggers a recursive call to `ty_of_item()`  (note that
//! `ast_ty_to_ty()` will detect recursive types and report an error).
//! In the check phase, when the FnCtxt is used as the `AstConv`,
//! `get_item_ty()` just looks up the item type in `tcx.tcache`.
//!
//! The `RegionScope` trait controls what happens when the user does
//! not specify a region in some location where a region is required
//! (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
//! See the `rscope` module for more details.
//!
//! Unlike the `AstConv` trait, the region scope can change as we descend
//! the type.  This is to accommodate the fact that (a) fn types are binding
//! scopes and (b) the default region may change.  To understand case (a),
//! consider something like:
//!
//!   type foo = { x: &a.int, y: |&a.int| }
//!
//! The type of `x` is an error because there is no region `a` in scope.
//! In the type of `y`, however, region `a` is considered a bound region
//! as it does not already appear in scope.
//!
//! Case (b) says that if you have a type:
//!   type foo<'a> = ...;
//!   type bar = fn(&foo, &a.foo)
//! The fully expanded version of type bar is:
//!   type bar = fn(&'foo &, &a.foo<'a>)
//! Note that the self region for the `foo` defaulted to `&` in the first
//! case but `&a` in the second.  Basically, defaults that appear inside
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
49 50

use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
51
use middle::const_eval;
52
use middle::def;
53
use middle::resolve_lifetime as rl;
54
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
55
use middle::subst::{VecPerParamSpace};
56
use middle::ty::{mod, Ty};
N
Niko Matsakis 已提交
57 58 59
use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
             ShiftedRscope, BindingRscope};
use TypeAndSubsts;
60
use util::common::ErrorReported;
61
use util::nodemap::DefIdMap;
62
use util::ppaux::{mod, Repr, UserString};
63

E
Eduard Burtescu 已提交
64
use std::rc::Rc;
65 66
use std::iter::AdditiveIterator;
use syntax::{abi, ast, ast_util};
67
use syntax::codemap::Span;
68
use syntax::parse::token;
69
use syntax::print::pprust;
70

71 72
pub trait AstConv<'tcx> {
    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
73 74
    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx>;
    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
75

76
    /// What type should we use when a type is omitted?
77
    fn ty_infer(&self, span: Span) -> Ty<'tcx>;
78 79 80 81

    /// Returns true if associated types from the given trait and type are
    /// allowed to be used here and false otherwise.
    fn associated_types_of_trait_are_valid(&self,
82
                                           ty: Ty<'tcx>,
83 84 85
                                           trait_id: ast::DefId)
                                           -> bool;

86 87 88 89
    /// Returns the concrete type bound to the given associated type (indicated
    /// by associated_type_id) in the current context. For example,
    /// in `trait Foo { type A; }` looking up `A` will give a type variable;
    /// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`.
90 91
    fn associated_type_binding(&self,
                               span: Span,
92 93 94
                               self_ty: Option<Ty<'tcx>>,
                               // DefId for the declaration of the trait
                               // in which the associated type is declared.
95 96
                               trait_id: ast::DefId,
                               associated_type_id: ast::DefId)
97
                               -> Option<Ty<'tcx>>;
98 99
}

E
Eduard Burtescu 已提交
100
pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
101
                            -> ty::Region {
102
    let r = match tcx.named_region_map.get(&lifetime.id) {
103 104 105
        None => {
            // should have been recorded by the `resolve_lifetime` pass
            tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
106
        }
107

108
        Some(&rl::DefStaticRegion) => {
109
            ty::ReStatic
110 111
        }

112 113
        Some(&rl::DefLateBoundRegion(debruijn, id)) => {
            ty::ReLateBound(debruijn, ty::BrNamed(ast_util::local_def(id), lifetime.name))
114 115
        }

116 117
        Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
            ty::ReEarlyBound(id, space, index, lifetime.name)
118 119
        }

120
        Some(&rl::DefFreeRegion(scope, id)) => {
121
            ty::ReFree(ty::FreeRegion {
122
                    scope: scope,
123
                    bound_region: ty::BrNamed(ast_util::local_def(id),
124
                                              lifetime.name)
125 126 127 128 129
                })
        }
    };

    debug!("ast_region_to_region(lifetime={} id={}) yields {}",
130 131 132
           lifetime.repr(tcx),
           lifetime.id,
           r.repr(tcx));
133 134

    r
135 136
}

137
pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
138
    this: &AC,
139
    rscope: &RS,
140
    default_span: Span,
J
James Miller 已提交
141
    opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
142
{
143 144 145
    let r = match *opt_lifetime {
        Some(ref lifetime) => {
            ast_region_to_region(this.tcx(), lifetime)
146
        }
147 148 149

        None => {
            match rscope.anon_regions(default_span, 1) {
150
                Err(v) => {
151
                    debug!("optional region in illegal location");
J
Jakub Wieczorek 已提交
152 153
                    span_err!(this.tcx().sess, default_span, E0106,
                        "missing lifetime specifier");
154 155 156 157
                    match v {
                        Some(v) => {
                            let mut m = String::new();
                            let len = v.len();
158
                            for (i, (name, n)) in v.into_iter().enumerate() {
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
                                m.push_str(if n == 1 {
                                    format!("`{}`", name)
                                } else {
                                    format!("one of `{}`'s {} elided lifetimes", name, n)
                                }.as_slice());

                                if len == 2 && i == 0 {
                                    m.push_str(" or ");
                                } else if i == len - 2 {
                                    m.push_str(", or ");
                                } else if i != len - 1 {
                                    m.push_str(", ");
                                }
                            }
                            if len == 1 {
P
P1start 已提交
174
                                span_help!(this.tcx().sess, default_span,
175 176 177 178
                                    "this function's return type contains a borrowed value, but \
                                     the signature does not say which {} it is borrowed from",
                                    m);
                            } else if len == 0 {
P
P1start 已提交
179
                                span_help!(this.tcx().sess, default_span,
180 181
                                    "this function's return type contains a borrowed value, but \
                                     there is no value for it to be borrowed from");
P
P1start 已提交
182
                                span_help!(this.tcx().sess, default_span,
183 184
                                    "consider giving it a 'static lifetime");
                            } else {
P
P1start 已提交
185
                                span_help!(this.tcx().sess, default_span,
186 187 188 189 190 191 192
                                    "this function's return type contains a borrowed value, but \
                                     the signature does not say whether it is borrowed from {}",
                                    m);
                            }
                        }
                        None => {},
                    }
193
                    ty::ReStatic
194 195
                }

196
                Ok(rs) => rs[0],
197
            }
198
        }
199 200
    };

B
Ben Gamari 已提交
201
    debug!("opt_ast_region_to_region(opt_lifetime={}) yields {}",
202
            opt_lifetime.repr(this.tcx()),
203 204 205
            r.repr(this.tcx()));

    r
206 207
}

S
Steve Klabnik 已提交
208 209
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
/// returns an appropriate set of substitutions for this particular reference to `I`.
210
fn ast_path_substs_for_ty<'tcx,AC,RS>(
211 212 213
    this: &AC,
    rscope: &RS,
    decl_def_id: ast::DefId,
214
    decl_generics: &ty::Generics<'tcx>,
215
    path: &ast::Path)
216
    -> Substs<'tcx>
217
    where AC: AstConv<'tcx>, RS: RegionScope
218
{
219
    let tcx = this.tcx();
220

221 222 223 224 225 226 227 228
    // 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.
229 230
    assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
    assert!(decl_generics.types.all(|d| d.space != FnSpace));
231

232
    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
233 234 235 236 237 238
        ast::AngleBracketedParameters(ref data) => {
            convert_angle_bracketed_parameters(this, rscope, data)
        }
        ast::ParenthesizedParameters(ref data) => {
            span_err!(tcx.sess, path.span, E0169,
                      "parenthesized parameters may only be used with a trait");
239
            (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
240
        }
241 242
    };

243 244 245 246 247 248 249 250 251
    create_substs_for_ast_path(this,
                               rscope,
                               path.span,
                               decl_def_id,
                               decl_generics,
                               None,
                               types,
                               regions,
                               assoc_bindings)
252 253 254 255 256 257 258
}

fn create_substs_for_ast_path<'tcx,AC,RS>(
    this: &AC,
    rscope: &RS,
    span: Span,
    decl_def_id: ast::DefId,
259 260 261
    decl_generics: &ty::Generics<'tcx>,
    self_ty: Option<Ty<'tcx>>,
    types: Vec<Ty<'tcx>>,
262 263
    regions: Vec<ty::Region>,
    assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>)
264
    -> Substs<'tcx>
265 266 267 268
    where AC: AstConv<'tcx>, RS: RegionScope
{
    let tcx = this.tcx();

269
    // If the type is parameterized by the this region, then replace this
270 271
    // region with the current anon region binding (in other words,
    // whatever & would get replaced with).
272
    let expected_num_region_params = decl_generics.regions.len(TypeSpace);
273
    let supplied_num_region_params = regions.len();
274
    let regions = if expected_num_region_params == supplied_num_region_params {
275
        regions
276 277
    } else {
        let anon_regions =
278
            rscope.anon_regions(span, expected_num_region_params);
279

280
        if supplied_num_region_params != 0 || anon_regions.is_err() {
281
            span_err!(tcx.sess, span, E0107,
282 283
                      "wrong number of lifetime parameters: expected {}, found {}",
                      expected_num_region_params, supplied_num_region_params);
284
        }
285 286

        match anon_regions {
A
Aaron Turon 已提交
287
            Ok(v) => v.into_iter().collect(),
288
            Err(_) => Vec::from_fn(expected_num_region_params,
289
                                   |_| ty::ReStatic) // hokey
290
        }
291 292 293
    };

    // Convert the type parameters supplied by the user.
294
    let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
295
    let supplied_ty_param_count = types.len();
296 297
    let formal_ty_param_count =
        ty_param_defs.iter()
298 299
        .take_while(|x| !ty::is_associated_type(tcx, x.def_id))
        .count();
300 301
    let required_ty_param_count =
        ty_param_defs.iter()
302 303 304 305 306
        .take_while(|x| {
            x.default.is_none() &&
                !ty::is_associated_type(tcx, x.def_id)
        })
        .count();
307 308 309 310 311 312
    if supplied_ty_param_count < required_ty_param_count {
        let expected = if required_ty_param_count < formal_ty_param_count {
            "expected at least"
        } else {
            "expected"
        };
313
        this.tcx().sess.span_fatal(span,
314 315 316 317
                                   format!("wrong number of type arguments: {} {}, found {}",
                                           expected,
                                           required_ty_param_count,
                                           supplied_ty_param_count).as_slice());
318 319 320 321 322 323
    } else if supplied_ty_param_count > formal_ty_param_count {
        let expected = if required_ty_param_count < formal_ty_param_count {
            "expected at most"
        } else {
            "expected"
        };
324
        this.tcx().sess.span_fatal(span,
325 326 327 328
                                   format!("wrong number of type arguments: {} {}, found {}",
                                           expected,
                                           formal_ty_param_count,
                                           supplied_ty_param_count).as_slice());
329 330
    }

331
    if supplied_ty_param_count > required_ty_param_count
N
Nick Cameron 已提交
332
        && !this.tcx().sess.features.borrow().default_type_params {
333
        span_err!(this.tcx().sess, span, E0108,
J
Jakub Wieczorek 已提交
334
            "default type parameters are experimental and possibly buggy");
335
        span_help!(this.tcx().sess, span,
J
Jakub Wieczorek 已提交
336
            "add #![feature(default_type_params)] to the crate attributes to enable");
337 338
    }

339
    let mut substs = Substs::new_type(types, regions);
340

341 342 343 344 345 346 347 348 349 350
    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());
351
            substs.types.push(SelfSpace, ty);
352
        }
353
    }
354

355
    for param in ty_param_defs[supplied_ty_param_count..].iter() {
356 357 358 359 360
        match param.default {
            Some(default) => {
                // This is a default type parameter.
                let default = default.subst_spanned(tcx,
                                                    &substs,
361
                                                    Some(span));
362 363 364
                substs.types.push(TypeSpace, default);
            }
            None => {
365
                tcx.sess.span_bug(span, "extra parameter without default");
366 367
            }
        }
368
    }
369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
    let mut matched_assoc = 0u;
    for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() {
        let mut found = false;
        for &(ident, ty) in assoc_bindings.iter() {
            if formal_assoc.name.ident() == ident {
                substs.types.push(AssocSpace, ty);
                matched_assoc += 1;
                found = true;
                break;
            }
        }
        if !found {
            match this.associated_type_binding(span,
                                               self_ty,
                                               decl_def_id,
                                               formal_assoc.def_id) {
                Some(ty) => {
                    substs.types.push(AssocSpace, ty);
                    matched_assoc += 1;
                }
                None => {
                    span_err!(this.tcx().sess, span, E0179,
                              "missing type for associated type `{}`",
                              token::get_ident(formal_assoc.name.ident()));
                }
            }
        }
    }

    if decl_generics.types.get_slice(AssocSpace).len() != matched_assoc {
        span_err!(tcx.sess, span, E0171,
                  "wrong number of associated type parameters: expected {}, found {}",
                  decl_generics.types.get_slice(AssocSpace).len(), matched_assoc);
    }

    for &(ident, _) in assoc_bindings.iter() {
        let mut formal_idents = decl_generics.types.get_slice(AssocSpace)
                                .iter().map(|t| t.name.ident());
        if !formal_idents.any(|i| i == ident) {
            span_err!(this.tcx().sess, span, E0177,
                      "associated type `{}` does not exist",
                      token::get_ident(ident));
        }
413 414
    }

415
    return substs;
416
}
417

418 419 420
fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
                                                    rscope: &RS,
                                                    data: &ast::AngleBracketedParameterData)
421 422 423
                                                    -> (Vec<ty::Region>,
                                                        Vec<Ty<'tcx>>,
                                                        Vec<(ast::Ident, Ty<'tcx>)>)
424 425 426 427 428 429
    where AC: AstConv<'tcx>, RS: RegionScope
{
    let regions: Vec<_> =
        data.lifetimes.iter()
        .map(|l| ast_region_to_region(this.tcx(), l))
        .collect();
430

431 432 433 434 435
    let types: Vec<_> =
        data.types.iter()
        .map(|t| ast_ty_to_ty(this, rscope, &**t))
        .collect();

436 437 438 439 440 441
    let assoc_bindings: Vec<_> =
        data.bindings.iter()
        .map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty)))
        .collect();

    (regions, types, assoc_bindings)
442 443
}

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
/// Returns the appropriate lifetime to use for any output lifetimes
/// (if one exists) and a vector of the (pattern, number of lifetimes)
/// corresponding to each input type/pattern.
fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
                              -> (Option<ty::Region>, Vec<(String, uint)>)
{
    let mut lifetimes_for_params: Vec<(String, uint)> = Vec::new();
    let mut possible_implied_output_region = None;

    for (input_type, input_pat) in input_tys.iter().zip(input_pats.into_iter()) {
        let mut accumulator = Vec::new();
        ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type);

        if accumulator.len() == 1 {
            // there's a chance that the unique lifetime of this
            // iteration will be the appropriate lifetime for output
            // parameters, so lets store it.
            possible_implied_output_region = Some(accumulator[0])
        }

        lifetimes_for_params.push((input_pat, accumulator.len()));
    }

    let implied_output_region = if lifetimes_for_params.iter().map(|&(_, n)| n).sum() == 1 {
        assert!(possible_implied_output_region.is_some());
        possible_implied_output_region
    } else {
        None
    };
    (implied_output_region, lifetimes_for_params)
}

fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
                                             implied_output_region: Option<ty::Region>,
                                             param_lifetimes: Vec<(String, uint)>,
                                             ty: &ast::Ty)
                                             -> Ty<'tcx>
    where AC: AstConv<'tcx>
{
    match implied_output_region {
        Some(implied_output_region) => {
            let rb = SpecificRscope::new(implied_output_region);
            ast_ty_to_ty(this, &rb, ty)
        }
        None => {
            // All regions must be explicitly specified in the output
            // if the lifetime elision rules do not apply. This saves
            // the user from potentially-confusing errors.
            let rb = UnelidableRscope::new(param_lifetimes);
            ast_ty_to_ty(this, &rb, ty)
        }
    }
}

498 499
fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
                                             data: &ast::ParenthesizedParameterData)
500
                                             -> Vec<Ty<'tcx>>
501 502 503 504 505
    where AC: AstConv<'tcx>
{
    let binding_rscope = BindingRscope::new();
    let inputs = data.inputs.iter()
                            .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
506 507 508 509 510 511
                            .collect::<Vec<Ty<'tcx>>>();

    let input_params = Vec::from_elem(inputs.len(), String::new());
    let (implied_output_region,
         params_lifetimes) = find_implied_output_region(&*inputs, input_params);

512 513 514
    let input_ty = ty::mk_tup(this.tcx(), inputs);

    let output = match data.output {
515 516 517 518
        Some(ref output_ty) => convert_ty_with_lifetime_elision(this,
                                                                implied_output_region,
                                                                params_lifetimes,
                                                                &**output_ty),
519 520 521 522 523
        None => ty::mk_nil(this.tcx()),
    };

    vec![input_ty, output]
}
524

525 526 527 528
pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
    this: &AC,
    rscope: &RS,
    ast_trait_ref: &ast::PolyTraitRef,
529
    self_ty: Option<Ty<'tcx>>)
530
    -> Rc<ty::TraitRef<'tcx>>
531 532
    where AC: AstConv<'tcx>, RS: RegionScope
{
533
    instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty)
534 535
}

S
Steve Klabnik 已提交
536 537 538
/// 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 trait. Fails if the type is a type other than a trait
/// type.
N
Niko Matsakis 已提交
539 540 541
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
                                         rscope: &RS,
                                         ast_trait_ref: &ast::TraitRef,
542 543
                                         self_ty: Option<Ty<'tcx>>,
                                         allow_eq: AllowEqConstraints)
544
                                         -> Rc<ty::TraitRef<'tcx>>
N
Niko Matsakis 已提交
545 546 547
                                         where AC: AstConv<'tcx>,
                                               RS: RegionScope
{
N
Niko Matsakis 已提交
548 549 550
    match ::lookup_def_tcx(this.tcx(),
                           ast_trait_ref.path.span,
                           ast_trait_ref.ref_id) {
551
        def::DefTrait(trait_def_id) => {
552 553 554 555 556 557
            let trait_ref = Rc::new(ast_path_to_trait_ref(this,
                                                          rscope,
                                                          trait_def_id,
                                                          self_ty,
                                                          &ast_trait_ref.path,
                                                          allow_eq));
N
Niko Matsakis 已提交
558 559 560 561 562 563 564 565 566 567 568 569
            this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
                                                      trait_ref.clone());
            trait_ref
        }
        _ => {
            this.tcx().sess.span_fatal(
                ast_trait_ref.path.span,
                format!("`{}` is not a trait", ast_trait_ref.path.user_string(this.tcx()))[]);
        }
    }
}

570 571 572 573 574 575
#[deriving(PartialEq,Show)]
pub enum AllowEqConstraints {
    Allow,
    DontAllow
}

576 577 578 579
fn ast_path_to_trait_ref<'tcx,AC,RS>(
    this: &AC,
    rscope: &RS,
    trait_def_id: ast::DefId,
580
    self_ty: Option<Ty<'tcx>>,
581 582
    path: &ast::Path,
    allow_eq: AllowEqConstraints)
583
    -> ty::TraitRef<'tcx>
584 585
    where AC: AstConv<'tcx>, RS: RegionScope
{
586
    debug!("ast_path_to_trait_ref {}", path);
E
Eduard Burtescu 已提交
587
    let trait_def = this.get_trait_def(trait_def_id);
588 589 590 591 592 593 594 595

    // the trait reference introduces a binding level here, so
    // we need to shift the `rscope`. It'd be nice if we could
    // do away with this rscope stuff and work this knowledge
    // into resolve_lifetimes, as we do with non-omitted
    // lifetimes. Oh well, not there yet.
    let shifted_rscope = ShiftedRscope::new(rscope);

596
    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
597 598 599 600
        ast::AngleBracketedParameters(ref data) => {
            convert_angle_bracketed_parameters(this, &shifted_rscope, data)
        }
        ast::ParenthesizedParameters(ref data) => {
601
            (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
602 603 604
        }
    };

605 606 607 608 609
    if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 {
        span_err!(this.tcx().sess, path.span, E0173,
                  "equality constraints are not allowed in this position");
    }

610 611 612 613 614 615 616
    let substs = create_substs_for_ast_path(this,
                                            &shifted_rscope,
                                            path.span,
                                            trait_def_id,
                                            &trait_def.generics,
                                            self_ty,
                                            types,
617 618
                                            regions,
                                            assoc_bindings);
619 620

    ty::TraitRef::new(trait_def_id, substs)
621 622
}

623
pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
624 625 626
    this: &AC,
    rscope: &RS,
    did: ast::DefId,
627
    path: &ast::Path)
628
    -> TypeAndSubsts<'tcx>
629
{
630
    let tcx = this.tcx();
631
    let ty::Polytype {
632
        generics,
633 634 635
        ty: decl_ty
    } = this.get_item_ty(did);

636 637 638 639 640 641
    let substs = ast_path_substs_for_ty(this,
                                        rscope,
                                        did,
                                        &generics,
                                        None,
                                        path);
642
    let ty = decl_ty.subst(tcx, &substs);
643
    TypeAndSubsts { substs: substs, ty: ty }
644 645
}

646 647 648 649 650
/// Returns the type that this AST path refers to. If the path has no type
/// parameters and the corresponding type has type parameters, fresh type
/// and/or region variables are substituted.
///
/// This is used when checking the constructor in struct literals.
651 652 653 654
pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
    this: &AC,
    rscope: &RS,
    did: ast::DefId,
655
    path: &ast::Path)
656
    -> TypeAndSubsts<'tcx>
657 658
    where AC : AstConv<'tcx>, RS : RegionScope
{
659 660
    let tcx = this.tcx();
    let ty::Polytype {
661
        generics,
662 663 664
        ty: decl_ty
    } = this.get_item_ty(did);

665 666 667 668 669 670 671 672
    let wants_params =
        generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);

    let needs_defaults =
        wants_params &&
        path.segments.iter().all(|s| s.parameters.is_empty());

    let substs = if needs_defaults {
673 674 675 676 677 678 679 680
        let type_params = Vec::from_fn(generics.types.len(TypeSpace),
                                       |_| this.ty_infer(path.span));
        let region_params =
            rscope.anon_regions(path.span, generics.regions.len(TypeSpace))
                  .unwrap();
        Substs::new(VecPerParamSpace::params_from_type(type_params),
                    VecPerParamSpace::params_from_type(region_params))
    } else {
681
        ast_path_substs_for_ty(this, rscope, did, &generics, None, path)
682 683 684 685 686 687 688 689 690
    };

    let ty = decl_ty.subst(tcx, &substs);
    TypeAndSubsts {
        substs: substs,
        ty: ty,
    }
}

691 692
/// Converts the given AST type to a built-in type. A "built-in type" is, at
/// present, either a core numeric type, a string, or `Box`.
693 694 695 696
pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
        this: &AC,
        rscope: &RS,
        ast_ty: &ast::Ty)
697
        -> Option<Ty<'tcx>> {
698 699 700
    match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
        Some(typ) => return Some(typ),
        None => {}
701 702
    }

703
    match ast_ty.node {
704
        ast::TyPath(ref path, id) => {
705
            let a_def = match this.tcx().def_map.borrow().get(&id) {
706 707 708 709 710
                None => {
                    this.tcx()
                        .sess
                        .span_bug(ast_ty.span,
                                  format!("unbound path {}",
711
                                          path.repr(this.tcx())).as_slice())
712
                }
713 714
                Some(&d) => d
            };
715

716 717 718
            // FIXME(#12938): This is a hack until we have full support for
            // DST.
            match a_def {
719 720
                def::DefTy(did, _) |
                def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
721
                    let ty = ast_path_to_ty(this, rscope, did, path).ty;
722
                    match ty.sty {
723 724 725 726 727 728 729 730 731 732 733 734
                        ty::ty_struct(struct_def_id, ref substs) => {
                            assert_eq!(struct_def_id, did);
                            assert_eq!(substs.types.len(TypeSpace), 1);
                            let referent_ty = *substs.types.get(TypeSpace, 0);
                            Some(ty::mk_uniq(this.tcx(), referent_ty))
                        }
                        _ => {
                            this.tcx().sess.span_bug(
                                path.span,
                                format!("converting `Box` to `{}`",
                                        ty.repr(this.tcx()))[]);
                        }
735 736
                    }
                }
737
                _ => None
738
            }
739
        }
740 741 742 743
        _ => None
    }
}

744 745 746 747 748 749
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
                                   rscope: &RS,
                                   ty: &ast::Ty,
                                   bounds: &[ast::TyParamBound])
                                   -> Result<ty::TraitRef<'tcx>, ErrorReported>
    where AC : AstConv<'tcx>, RS : RegionScope
750
{
751 752 753 754 755 756 757 758 759 760
    /*!
     * In a type like `Foo + Send`, we want to wait to collect the
     * full set of bounds before we make the object type, because we
     * need them to infer a region bound.  (For example, if we tried
     * made a type from just `Foo`, then it wouldn't be enough to
     * infer a 'static bound, and hence the user would get an error.)
     * So this function is used when we're dealing with a sum type to
     * convert the LHS. It only accepts a type that refers to a trait
     * name, and reports an error otherwise.
     */
761

762 763 764 765 766 767 768 769
    match ty.node {
        ast::TyPath(ref path, id) => {
            match this.tcx().def_map.borrow().get(&id) {
                Some(&def::DefTrait(trait_def_id)) => {
                    return Ok(ast_path_to_trait_ref(this,
                                                    rscope,
                                                    trait_def_id,
                                                    None,
770 771
                                                    path,
                                                    AllowEqConstraints::Allow));
772 773
                }
                _ => {
774
                    span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
775 776 777
                    Err(ErrorReported)
                }
            }
778
        }
779 780 781 782 783 784 785 786 787 788 789
        _ => {
            span_err!(this.tcx().sess, ty.span, E0171,
                      "expected a path on the left-hand side of `+`, not `{}`",
                      pprust::ty_to_string(ty));
            match ty.node {
                ast::TyRptr(None, ref mut_ty) => {
                    span_note!(this.tcx().sess, ty.span,
                               "perhaps you meant `&{}({} +{})`? (per RFC 248)",
                               ppaux::mutability_to_string(mut_ty.mutbl),
                               pprust::ty_to_string(&*mut_ty.ty),
                               pprust::bounds_to_string(bounds));
790
                }
791 792 793 794 795 796 797 798 799 800 801 802

                ast::TyRptr(Some(ref lt), ref mut_ty) => {
                    span_note!(this.tcx().sess, ty.span,
                               "perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
                               pprust::lifetime_to_string(lt),
                               ppaux::mutability_to_string(mut_ty.mutbl),
                               pprust::ty_to_string(&*mut_ty.ty),
                               pprust::bounds_to_string(bounds));
                }

                _ => {
                    span_note!(this.tcx().sess, ty.span,
A
Alex Crichton 已提交
803
                               "perhaps you forgot parentheses? (per RFC 248)");
804 805
                }
            }
806
            Err(ErrorReported)
807
        }
808 809
    }

810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
}

fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
                                        rscope: &RS,
                                        span: Span,
                                        trait_ref: ty::TraitRef<'tcx>,
                                        bounds: &[ast::TyParamBound])
                                        -> Ty<'tcx>
    where AC : AstConv<'tcx>, RS : RegionScope
{
    let existential_bounds = conv_existential_bounds(this,
                                                     rscope,
                                                     span,
                                                     &[Rc::new(trait_ref.clone())],
                                                     bounds);

    let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
    debug!("trait_ref_to_object_type: result={}",
           result.repr(this.tcx()));

    result
831 832
}

833 834 835 836 837 838
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
                           rscope: &RS,
                           ast_ty: &ast::Ty, // the TyQPath
                           qpath: &ast::QPath)
                           -> Ty<'tcx>
    where AC: AstConv<'tcx>, RS: RegionScope
839
{
840 841
    debug!("qpath_to_ty(ast_ty={})",
           ast_ty.repr(this.tcx()));
842

843 844 845
    let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);

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

847
    let trait_ref = instantiate_trait_ref(this,
848
                                          rscope,
849
                                          &*qpath.trait_ref,
850 851
                                          Some(self_type),
                                          AllowEqConstraints::DontAllow);
852 853 854 855 856 857 858 859 860

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

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

    for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
        if ty_param_def.name == qpath.item_name.name {
            debug!("qpath_to_ty: corresponding ty_param_def={}", ty_param_def);
            return trait_ref.substs.type_for_def(ty_param_def);
861 862
        }
    }
863 864

    this.tcx().sess.span_bug(ast_ty.span,
865 866 867 868
                             "this associated type didn't get added \
                              as a parameter for some reason")
}

869 870
// Parses the programmer's textual representation of a type into our
// internal notion of a type.
871
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
872
        this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>
873 874 875
{
    debug!("ast_ty_to_ty(ast_ty={})",
           ast_ty.repr(this.tcx()));
876

877
    let tcx = this.tcx();
878

879
    let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
880
    match ast_ty_to_ty_cache.get(&ast_ty.id) {
881 882 883 884 885 886
        Some(&ty::atttce_resolved(ty)) => return ty,
        Some(&ty::atttce_unresolved) => {
            tcx.sess.span_fatal(ast_ty.span,
                                "illegal recursive type; insert an enum \
                                 or struct in the cycle, if this is \
                                 desired");
887
        }
888
        None => { /* go on */ }
889
    }
890 891
    ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
    drop(ast_ty_to_ty_cache);
892

893 894
    let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
        match ast_ty.node {
895 896
            ast::TyVec(ref ty) => {
                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
897
            }
898 899 900 901 902 903 904 905 906 907 908
            ast::TyObjectSum(ref ty, ref bounds) => {
                match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
                    Ok(trait_ref) => {
                        trait_ref_to_object_type(this, rscope, ast_ty.span,
                                                 trait_ref, bounds.as_slice())
                    }
                    Err(ErrorReported) => {
                        ty::mk_err()
                    }
                }
            }
909
            ast::TyPtr(ref mt) => {
910
                ty::mk_ptr(tcx, ty::mt {
911
                    ty: ast_ty_to_ty(this, rscope, &*mt.ty),
912 913
                    mutbl: mt.mutbl
                })
914
            }
915 916 917
            ast::TyRptr(ref region, ref mt) => {
                let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
                debug!("ty_rptr r={}", r.repr(this.tcx()));
918 919
                let t = ast_ty_to_ty(this, rscope, &*mt.ty);
                ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
920 921
            }
            ast::TyTup(ref fields) => {
922
                let flds = fields.iter()
923
                                 .map(|t| ast_ty_to_ty(this, rscope, &**t))
924
                                 .collect();
925 926
                ty::mk_tup(tcx, flds)
            }
927
            ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
928
            ast::TyBareFn(ref bf) => {
929
                if bf.decl.variadic && bf.abi != abi::C {
930 931 932
                    tcx.sess.span_err(ast_ty.span,
                                      "variadic function must have C calling convention");
                }
933
                ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.fn_style, bf.abi, &*bf.decl))
934
            }
935
            ast::TyClosure(ref f) => {
936 937
                // Use corresponding trait store to figure out default bounds
                // if none were specified.
938 939 940 941 942
                let bounds = conv_existential_bounds(this,
                                                     rscope,
                                                     ast_ty.span,
                                                     [].as_slice(),
                                                     f.bounds.as_slice());
943
                let fn_decl = ty_of_closure(this,
944
                                            f.fn_style,
945 946
                                            f.onceness,
                                            bounds,
947 948 949
                                            ty::RegionTraitStore(
                                                bounds.region_bound,
                                                ast::MutMutable),
950
                                            &*f.decl,
951
                                            abi::Rust,
952 953 954 955 956 957
                                            None);
                ty::mk_closure(tcx, fn_decl)
            }
            ast::TyProc(ref f) => {
                // Use corresponding trait store to figure out default bounds
                // if none were specified.
958 959 960 961
                let bounds = conv_existential_bounds(this, rscope,
                                                     ast_ty.span,
                                                     [].as_slice(),
                                                     f.bounds.as_slice());
962 963 964 965 966 967

                let fn_decl = ty_of_closure(this,
                                            f.fn_style,
                                            f.onceness,
                                            bounds,
                                            ty::UniqTraitStore,
968
                                            &*f.decl,
969
                                            abi::Rust,
970
                                            None);
971

972 973
                ty::mk_closure(tcx, fn_decl)
            }
974 975
            ast::TyPolyTraitRef(ref bounds) => {
                conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
N
Niko Matsakis 已提交
976
            }
977
            ast::TyPath(ref path, id) => {
978
                let a_def = match tcx.def_map.borrow().get(&id) {
979 980 981 982
                    None => {
                        tcx.sess
                           .span_bug(ast_ty.span,
                                     format!("unbound path {}",
983
                                             path.repr(tcx)).as_slice())
984
                    }
985 986 987
                    Some(&d) => d
                };
                match a_def {
N
Nick Cameron 已提交
988
                    def::DefTrait(trait_def_id) => {
989 990
                        // N.B. this case overlaps somewhat with
                        // TyObjectSum, see that fn for details
991 992 993 994
                        let result = ast_path_to_trait_ref(this,
                                                           rscope,
                                                           trait_def_id,
                                                           None,
995 996
                                                           path,
                                                           AllowEqConstraints::Allow);
997
                        trait_ref_to_object_type(this, rscope, path.span, result, &[])
998
                    }
999
                    def::DefTy(did, _) | def::DefStruct(did) => {
1000
                        ast_path_to_ty(this, rscope, did, path).ty
1001
                    }
1002
                    def::DefTyParam(space, id, n) => {
1003
                        check_path_args(tcx, path, NO_TPS | NO_REGIONS);
1004
                        ty::mk_param(tcx, space, n, id)
1005
                    }
1006
                    def::DefSelfTy(id) => {
1007 1008 1009 1010 1011
                        // n.b.: resolve guarantees that the this type only appears in a
                        // trait, which we rely upon in various places when creating
                        // substs
                        check_path_args(tcx, path, NO_TPS | NO_REGIONS);
                        let did = ast_util::local_def(id);
1012
                        ty::mk_self_type(tcx, did)
1013
                    }
1014
                    def::DefMod(id) => {
1015 1016
                        tcx.sess.span_fatal(ast_ty.span,
                            format!("found module name used as a type: {}",
1017
                                    tcx.map.node_to_string(id.node)).as_slice());
1018
                    }
1019
                    def::DefPrimTy(_) => {
S
Steve Klabnik 已提交
1020
                        panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
1021
                    }
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
                    def::DefAssociatedTy(trait_type_id) => {
                        let path_str = tcx.map.path_to_string(
                            tcx.map.get_parent(trait_type_id.node));
                        tcx.sess.span_err(ast_ty.span,
                                          format!("ambiguous associated \
                                                   type; specify the type \
                                                   using the syntax `<Type \
                                                   as {}>::{}`",
                                                  path_str,
                                                  token::get_ident(
                                                      path.segments
                                                          .last()
                                                          .unwrap()
                                                          .identifier)
                                                  .get()).as_slice());
                        ty::mk_err()
                    }
1039 1040
                    _ => {
                        tcx.sess.span_fatal(ast_ty.span,
1041
                                            format!("found value name used \
L
Luqman Aden 已提交
1042
                                                     as a type: {}",
1043
                                                    a_def).as_slice());
1044 1045 1046
                    }
                }
            }
1047
            ast::TyQPath(ref qpath) => {
1048
                qpath_to_ty(this, rscope, ast_ty, &**qpath)
1049
            }
1050 1051
            ast::TyFixedLengthVec(ref ty, ref e) => {
                match const_eval::eval_const_expr_partial(tcx, &**e) {
1052 1053 1054
                    Ok(ref r) => {
                        match *r {
                            const_eval::const_int(i) =>
1055
                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
1056
                                           Some(i as uint)),
1057
                            const_eval::const_uint(i) =>
1058
                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
1059
                                           Some(i as uint)),
1060 1061
                            _ => {
                                tcx.sess.span_fatal(
1062
                                    ast_ty.span, "expected constant expr for array length");
1063 1064 1065 1066 1067 1068
                            }
                        }
                    }
                    Err(ref r) => {
                        tcx.sess.span_fatal(
                            ast_ty.span,
1069
                            format!("expected constant expr for array \
1070 1071
                                     length: {}",
                                    *r).as_slice());
1072 1073 1074
                    }
                }
            }
1075
            ast::TyTypeof(ref _e) => {
1076 1077 1078
                tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
            }
            ast::TyInfer => {
1079
                // TyInfer also appears as the type of arguments or return
1080
                // values in a ExprClosure or ExprProc, or as
1081 1082
                // the type of local variables. Both of these cases are
                // handled specially and will not descend into this routine.
1083
                this.ty_infer(ast_ty.span)
1084
            }
1085 1086
        }
    });
1087

1088
    tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
B
Brian Anderson 已提交
1089
    return typ;
1090 1091
}

1092 1093
pub fn ty_of_arg<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(this: &AC, rscope: &RS,
                                                           a: &ast::Arg,
1094 1095
                                                           expected_ty: Option<Ty<'tcx>>)
                                                           -> Ty<'tcx> {
E
Erick Tryzelaar 已提交
1096
    match a.ty.node {
1097 1098
        ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
        ast::TyInfer => this.ty_infer(a.ty.span),
1099
        _ => ast_ty_to_ty(this, rscope, &*a.ty),
1100
    }
1101 1102
}

1103 1104
struct SelfInfo<'a, 'tcx> {
    untransformed_self_ty: Ty<'tcx>,
1105
    explicit_self: &'a ast::ExplicitSelf,
1106 1107
}

1108
pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
1109 1110
                    this: &AC,
                    fn_style: ast::FnStyle,
1111
                    untransformed_self_ty: Ty<'tcx>,
1112
                    explicit_self: &ast::ExplicitSelf,
1113 1114
                    decl: &ast::FnDecl,
                    abi: abi::Abi)
1115
                    -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
1116
    let self_info = Some(SelfInfo {
1117
        untransformed_self_ty: untransformed_self_ty,
1118 1119 1120 1121 1122
        explicit_self: explicit_self,
    });
    let (bare_fn_ty, optional_explicit_self_category) =
        ty_of_method_or_bare_fn(this,
                                fn_style,
1123
                                abi,
1124 1125 1126
                                self_info,
                                decl);
    (bare_fn_ty, optional_explicit_self_category.unwrap())
1127 1128
}

1129
pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, fn_style: ast::FnStyle, abi: abi::Abi,
1130
                                              decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> {
1131
    let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, fn_style, abi, None, decl);
1132
    bare_fn_ty
1133 1134
}

1135
fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
1136 1137 1138
                           this: &AC,
                           fn_style: ast::FnStyle,
                           abi: abi::Abi,
1139
                           opt_self_info: Option<SelfInfo<'a, 'tcx>>,
1140
                           decl: &ast::FnDecl)
1141
                           -> (ty::BareFnTy<'tcx>,
1142
                               Option<ty::ExplicitSelfCategory>) {
1143
    debug!("ty_of_method_or_bare_fn");
1144

1145 1146
    // New region names that appear inside of the arguments of the function
    // declaration are bound to that function type.
1147
    let rb = rscope::BindingRscope::new();
1148

1149 1150 1151 1152 1153
    // `implied_output_region` is the region that will be assumed for any
    // region parameters in the return type. In accordance with the rules for
    // lifetime elision, we can determine it in two ways. First (determined
    // here), if self is by-reference, then the implied output region is the
    // region of the self parameter.
1154
    let mut explicit_self_category_result = None;
1155 1156 1157 1158 1159 1160 1161 1162
    let (self_ty, mut implied_output_region) = match opt_self_info {
        None => (None, None),
        Some(self_info) => {
            // Figure out and record the explicit self category.
            let explicit_self_category =
                determine_explicit_self_category(this, &rb, &self_info);
            explicit_self_category_result = Some(explicit_self_category);
            match explicit_self_category {
1163 1164 1165
                ty::StaticExplicitSelfCategory => {
                    (None, None)
                }
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
                ty::ByValueExplicitSelfCategory => {
                    (Some(self_info.untransformed_self_ty), None)
                }
                ty::ByReferenceExplicitSelfCategory(region, mutability) => {
                    (Some(ty::mk_rptr(this.tcx(),
                                      region,
                                      ty::mt {
                                        ty: self_info.untransformed_self_ty,
                                        mutbl: mutability
                                      })),
                     Some(region))
                }
                ty::ByBoxExplicitSelfCategory => {
                    (Some(ty::mk_uniq(this.tcx(),
                                      self_info.untransformed_self_ty)),
                     None)
                }
1183 1184
            }
        }
1185
    };
1186 1187

    // HACK(eddyb) replace the fake self type in the AST with the actual type.
1188
    let input_params = if self_ty.is_some() {
1189 1190 1191 1192
        decl.inputs.slice_from(1)
    } else {
        decl.inputs.as_slice()
    };
1193 1194 1195 1196
    let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None));
    let input_pats: Vec<String> = input_params.iter()
                                              .map(|a| pprust::pat_to_string(&*a.pat))
                                              .collect();
1197
    let self_and_input_tys: Vec<Ty> =
A
Aaron Turon 已提交
1198
        self_ty.into_iter().chain(input_tys).collect();
1199

1200

1201 1202 1203
    // Second, if there was exactly one lifetime (either a substitution or a
    // reference) in the arguments, then any anonymous regions in the output
    // have that lifetime.
1204 1205
    let lifetimes_for_params = if implied_output_region.is_none() {
        let input_tys = if self_ty.is_some() {
1206
            // Skip the first argument if `self` is present.
1207 1208 1209 1210
            self_and_input_tys.slice_from(1)
        } else {
            self_and_input_tys.slice_from(0)
        };
1211

1212 1213 1214 1215 1216 1217
        let (ior, lfp) = find_implied_output_region(input_tys, input_pats);
        implied_output_region = ior;
        lfp
    } else {
        vec![]
    };
1218

1219 1220 1221 1222
    let output_ty = match decl.output {
        ast::Return(ref output) if output.node == ast::TyInfer =>
            ty::FnConverging(this.ty_infer(output.span)),
        ast::Return(ref output) =>
1223 1224 1225 1226
            ty::FnConverging(convert_ty_with_lifetime_elision(this,
                                                              implied_output_region,
                                                              lifetimes_for_params,
                                                              &**output)),
1227
        ast::NoReturn(_) => ty::FnDiverging
1228 1229
    };

1230
    (ty::BareFnTy {
1231
        fn_style: fn_style,
1232
        abi: abi,
1233 1234 1235 1236 1237
        sig: ty::FnSig {
            inputs: self_and_input_tys,
            output: output_ty,
            variadic: decl.variadic
        }
1238 1239 1240
    }, explicit_self_category_result)
}

1241
fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>,
1242 1243 1244
                                    RS:RegionScope>(
                                    this: &AC,
                                    rscope: &RS,
1245
                                    self_info: &SelfInfo<'a, 'tcx>)
1246 1247 1248
                                    -> ty::ExplicitSelfCategory
{
    return match self_info.explicit_self.node {
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
        ast::SelfStatic => ty::StaticExplicitSelfCategory,
        ast::SelfValue(_) => ty::ByValueExplicitSelfCategory,
        ast::SelfRegion(ref lifetime, mutability, _) => {
            let region =
                opt_ast_region_to_region(this,
                                         rscope,
                                         self_info.explicit_self.span,
                                         lifetime);
            ty::ByReferenceExplicitSelfCategory(region, mutability)
        }
1259 1260
        ast::SelfExplicit(ref ast_type, _) => {
            let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
1261

1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
            // We wish to (for now) categorize an explicit self
            // declaration like `self: SomeType` into either `self`,
            // `&self`, `&mut self`, or `Box<self>`. We do this here
            // by some simple pattern matching. A more precise check
            // is done later in `check_method_self_type()`.
            //
            // Examples:
            //
            // ```
            // impl Foo for &T {
            //     // Legal declarations:
            //     fn method1(self: &&T); // ByReferenceExplicitSelfCategory
            //     fn method2(self: &T); // ByValueExplicitSelfCategory
            //     fn method3(self: Box<&T>); // ByBoxExplicitSelfCategory
            //
            //     // Invalid cases will be caught later by `check_method_self_type`:
            //     fn method_err1(self: &mut T); // ByReferenceExplicitSelfCategory
            // }
            // ```
            //
            // To do the check we just count the number of "modifiers"
            // on each type and compare them. If they are the same or
            // the impl has more, we call it "by value". Otherwise, we
            // look at the outermost modifier on the method decl and
            // call it by-ref, by-box as appropriate. For method1, for
            // example, the impl type has one modifier, but the method
            // type has two, so we end up with
            // ByReferenceExplicitSelfCategory.

            let impl_modifiers = count_modifiers(self_info.untransformed_self_ty);
            let method_modifiers = count_modifiers(explicit_type);

            debug!("determine_explicit_self_category(self_info.untransformed_self_ty={} \
                   explicit_type={} \
                   modifiers=({},{})",
                   self_info.untransformed_self_ty.repr(this.tcx()),
                   explicit_type.repr(this.tcx()),
                   impl_modifiers,
                   method_modifiers);

            if impl_modifiers >= method_modifiers {
                ty::ByValueExplicitSelfCategory
            } else {
1305
                match explicit_type.sty {
1306 1307 1308
                    ty::ty_rptr(r, mt) => ty::ByReferenceExplicitSelfCategory(r, mt.mutbl),
                    ty::ty_uniq(_) => ty::ByBoxExplicitSelfCategory,
                    _ => ty::ByValueExplicitSelfCategory,
1309 1310
                }
            }
1311 1312
        }
    };
1313

1314
    fn count_modifiers(ty: Ty) -> uint {
1315
        match ty.sty {
1316 1317 1318
            ty::ty_rptr(_, mt) => count_modifiers(mt.ty) + 1,
            ty::ty_uniq(t) => count_modifiers(t) + 1,
            _ => 0,
1319 1320
        }
    }
1321 1322
}

1323
pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
1324
    this: &AC,
1325
    fn_style: ast::FnStyle,
1326
    onceness: ast::Onceness,
1327
    bounds: ty::ExistentialBounds,
1328
    store: ty::TraitStore,
1329
    decl: &ast::FnDecl,
1330
    abi: abi::Abi,
1331 1332
    expected_sig: Option<ty::FnSig<'tcx>>)
    -> ty::ClosureTy<'tcx>
1333
{
1334 1335
    debug!("ty_of_closure(expected_sig={})",
           expected_sig.repr(this.tcx()));
1336 1337 1338

    // new region names that appear inside of the fn decl are bound to
    // that function type
1339
    let rb = rscope::BindingRscope::new();
1340

1341
    let input_tys: Vec<_> = decl.inputs.iter().enumerate().map(|(i, a)| {
1342
        let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
1343 1344
            // no guarantee that the correct number of expected args
            // were supplied
1345
            if i < e.inputs.len() {
1346
                Some(e.inputs[i])
1347 1348 1349
            } else {
                None
            }
1350
        });
J
James Miller 已提交
1351
        ty_of_arg(this, &rb, a, expected_arg_ty)
1352
    }).collect();
1353

1354
    let expected_ret_ty = expected_sig.map(|e| e.output);
J
Jakub Bukaj 已提交
1355

1356 1357 1358 1359 1360 1361 1362 1363
    let output_ty = match decl.output {
        ast::Return(ref output) if output.node == ast::TyInfer && expected_ret_ty.is_some() =>
            expected_ret_ty.unwrap(),
        ast::Return(ref output) if output.node == ast::TyInfer =>
            ty::FnConverging(this.ty_infer(output.span)),
        ast::Return(ref output) =>
            ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
        ast::NoReturn(_) => ty::FnDiverging
1364 1365
    };

1366 1367 1368
    debug!("ty_of_closure: input_tys={}", input_tys.repr(this.tcx()));
    debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx()));

1369
    ty::ClosureTy {
1370
        fn_style: fn_style,
1371
        onceness: onceness,
1372
        store: store,
1373
        bounds: bounds,
1374
        abi: abi,
1375
        sig: ty::FnSig {inputs: input_tys,
1376 1377
                        output: output_ty,
                        variadic: decl.variadic}
1378 1379
    }
}
1380

S
Steve Klabnik 已提交
1381 1382 1383 1384
/// Given an existential type like `Foo+'a+Bar`, this routine converts the `'a` and `Bar` intos an
/// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
/// for closures. Eventually this should all be normalized, I think, so that there is no "main
/// trait ref" and instead we just have a flat list of bounds as the existential type.
1385
pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
1386 1387 1388
    this: &AC,
    rscope: &RS,
    span: Span,
1389
    main_trait_refs: &[Rc<ty::TraitRef<'tcx>>],
1390 1391 1392 1393 1394 1395
    ast_bounds: &[ast::TyParamBound])
    -> ty::ExistentialBounds
{
    let ast_bound_refs: Vec<&ast::TyParamBound> =
        ast_bounds.iter().collect();

1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
    let partitioned_bounds =
        partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());

    conv_existential_bounds_from_partitioned_bounds(
        this, rscope, span, main_trait_refs, partitioned_bounds)
}

fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
    this: &AC,
    rscope: &RS,
    span: Span,
    ast_bounds: &[ast::TyParamBound])
1408
    -> Ty<'tcx>
1409 1410 1411 1412 1413 1414 1415
    where AC: AstConv<'tcx>, RS:RegionScope
{
    let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect();
    let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);

    let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
        Some(trait_bound) => {
1416 1417 1418 1419 1420
            Some(instantiate_trait_ref(this,
                                       rscope,
                                       &trait_bound.trait_ref,
                                       None,
                                       AllowEqConstraints::Allow))
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
        }
        None => {
            this.tcx().sess.span_err(
                span,
                "at least one non-builtin trait is required for an object type");
            None
        }
    };

    let bounds = conv_existential_bounds_from_partitioned_bounds(this,
                                                                 rscope,
                                                                 span,
                                                                 main_trait_bound.as_slice(),
                                                                 partitioned_bounds);

    match main_trait_bound {
        None => ty::mk_err(),
        Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
    }
}

pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
    this: &AC,
    rscope: &RS,
    span: Span,
1446
    main_trait_refs: &[Rc<ty::TraitRef<'tcx>>],
1447 1448 1449 1450
    partitioned_bounds: PartitionedBounds)
    -> ty::ExistentialBounds
    where AC: AstConv<'tcx>, RS:RegionScope
{
1451 1452
    let PartitionedBounds { builtin_bounds,
                            trait_bounds,
1453
                            region_bounds } =
1454
        partitioned_bounds;
1455 1456

    if !trait_bounds.is_empty() {
1457
        let b = &trait_bounds[0];
1458
        this.tcx().sess.span_err(
1459
            b.trait_ref.path.span,
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
            format!("only the builtin traits can be used \
                     as closure or object bounds").as_slice());
    }

    // The "main trait refs", rather annoyingly, have no type
    // specified for the `Self` parameter of the trait. The reason for
    // this is that they are, after all, *existential* types, and
    // hence that type is unknown. However, leaving this type missing
    // causes the substitution code to go all awry when walking the
    // bounds, so here we clone those trait refs and insert ty::err as
    // the self type. Perhaps we should do this more generally, it'd
    // be convenient (or perhaps something else, i.e., ty::erased).
    let main_trait_refs: Vec<Rc<ty::TraitRef>> =
        main_trait_refs.iter()
        .map(|t|
             Rc::new(ty::TraitRef {
                 def_id: t.def_id,
                 substs: t.substs.with_self_ty(ty::mk_err()) }))
        .collect();

    let region_bound = compute_region_bound(this,
                                            rscope,
                                            span,
                                            builtin_bounds,
                                            region_bounds.as_slice(),
                                            main_trait_refs.as_slice());

    ty::ExistentialBounds {
        region_bound: region_bound,
        builtin_bounds: builtin_bounds,
    }
}

S
Steve Klabnik 已提交
1493 1494 1495 1496
/// Given the bounds on a type parameter / existential type, determines what single region bound
/// (if any) we can use to summarize this type. The basic idea is that we will use the bound the
/// user provided, if they provided one, and otherwise search the supertypes of trait bounds for
/// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
1497 1498 1499 1500 1501 1502
pub fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      span: Span,
                                      builtin_bounds: ty::BuiltinBounds,
                                      region_bounds: &[&ast::Lifetime],
                                      trait_bounds: &[Rc<ty::TraitRef<'tcx>>])
                                      -> Option<ty::Region>
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
{
    if region_bounds.len() > 1 {
        tcx.sess.span_err(
            region_bounds[1].span,
            format!("only a single explicit lifetime bound is permitted").as_slice());
    }

    if region_bounds.len() != 0 {
        // Explicitly specified region bound. Use that.
        let r = region_bounds[0];
        return Some(ast_region_to_region(tcx, r));
    }

    // No explicit region bound specified. Therefore, examine trait
    // bounds and see if we can derive region bounds from those.
    let derived_region_bounds =
        ty::required_region_bounds(
            tcx,
N
Nick Cameron 已提交
1521
            &[],
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
            builtin_bounds,
            trait_bounds);

    // If there are no derived region bounds, then report back that we
    // can find no region bound.
    if derived_region_bounds.len() == 0 {
        return None;
    }

    // If any of the derived region bounds are 'static, that is always
    // the best choice.
    if derived_region_bounds.iter().any(|r| ty::ReStatic == *r) {
        return Some(ty::ReStatic);
    }

    // Determine whether there is exactly one unique region in the set
    // of derived region bounds. If so, use that. Otherwise, report an
    // error.
1540
    let r = derived_region_bounds[0];
1541 1542 1543 1544 1545 1546 1547 1548 1549
    if derived_region_bounds.slice_from(1).iter().any(|r1| r != *r1) {
        tcx.sess.span_err(
            span,
            format!("ambiguous lifetime bound, \
                     explicit lifetime bound required").as_slice());
    }
    return Some(r);
}

S
Steve Klabnik 已提交
1550 1551 1552
/// A version of `compute_opt_region_bound` for use where some region bound is required
/// (existential types, basically). Reports an error if no region bound can be derived and we are
/// in an `rscope` that does not provide a default.
1553
fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
1554 1555 1556 1557 1558
    this: &AC,
    rscope: &RS,
    span: Span,
    builtin_bounds: ty::BuiltinBounds,
    region_bounds: &[&ast::Lifetime],
1559
    trait_bounds: &[Rc<ty::TraitRef<'tcx>>])
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
    -> ty::Region
{
    match compute_opt_region_bound(this.tcx(), span, builtin_bounds,
                                   region_bounds, trait_bounds) {
        Some(r) => r,
        None => {
            match rscope.default_region_bound(span) {
                Some(r) => { r }
                None => {
                    this.tcx().sess.span_err(
                        span,
                        format!("explicit lifetime bound required").as_slice());
                    ty::ReStatic
                }
            }
        }
    }
}

pub struct PartitionedBounds<'a> {
    pub builtin_bounds: ty::BuiltinBounds,
1581
    pub trait_bounds: Vec<&'a ast::PolyTraitRef>,
1582 1583 1584
    pub region_bounds: Vec<&'a ast::Lifetime>,
}

S
Steve Klabnik 已提交
1585 1586
/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
/// general trait bounds, and region bounds.
1587 1588 1589 1590 1591 1592 1593 1594
pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                            _span: Span,
                            ast_bounds: &'a [&ast::TyParamBound])
                            -> PartitionedBounds<'a>
{
    let mut builtin_bounds = ty::empty_builtin_bounds();
    let mut region_bounds = Vec::new();
    let mut trait_bounds = Vec::new();
1595
    let mut trait_def_ids = DefIdMap::new();
1596 1597 1598
    for &ast_bound in ast_bounds.iter() {
        match *ast_bound {
            ast::TraitTyParamBound(ref b) => {
N
Niko Matsakis 已提交
1599
                match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
1600
                    def::DefTrait(trait_did) => {
1601
                        match trait_def_ids.get(&trait_did) {
1602 1603 1604 1605 1606
                            // Already seen this trait. We forbid
                            // duplicates in the list (for some
                            // reason).
                            Some(span) => {
                                span_err!(
1607
                                    tcx.sess, b.trait_ref.path.span, E0127,
1608 1609
                                    "trait `{}` already appears in the \
                                     list of bounds",
1610
                                    b.trait_ref.path.user_string(tcx));
1611 1612 1613 1614 1615
                                tcx.sess.span_note(
                                    *span,
                                    "previous appearance is here");

                                continue;
1616
                            }
1617 1618

                            None => { }
1619
                        }
1620

1621
                        trait_def_ids.insert(trait_did, b.trait_ref.path.span);
1622 1623 1624 1625 1626

                        if ty::try_add_builtin_trait(tcx,
                                                     trait_did,
                                                     &mut builtin_bounds) {
                            continue; // success
1627 1628
                        }
                    }
1629 1630 1631 1632
                    _ => {
                        // Not a trait? that's an error, but it'll get
                        // reported later.
                    }
1633
                }
1634 1635 1636 1637 1638
                trait_bounds.push(b);
            }
            ast::RegionTyParamBound(ref l) => {
                region_bounds.push(l);
            }
1639
        }
1640 1641 1642 1643 1644 1645
    }

    PartitionedBounds {
        builtin_bounds: builtin_bounds,
        trait_bounds: trait_bounds,
        region_bounds: region_bounds,
1646 1647
    }
}