mod.rs 194.5 KB
Newer Older
1
// Copyright 2012-2015 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.

B
Brian Anderson 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*

# check.rs

Within the check phase of type check, we check each item one at a time
(bodies of function expressions are checked as part of the containing
function).  Inference is used to supply types wherever they are
unknown.

By far the most complex case is checking the body of a function. This
can be broken down into several distinct phases:

- gather: creates type variables to represent the type of each local
  variable and pattern binding.

- main: the main pass does the lion's share of the work: it
  determines the types of all expressions, resolves
  methods, checks for most invalid conditions, and so forth.  In
  some cases, where a type is unknown, it may create a type or region
  variable and use that as the type of an expression.

  In the process of checking, various constraints will be placed on
  these type variables through the subtyping relationships requested
N
Niko Matsakis 已提交
34
  through the `demand` module.  The `infer` module is in charge
B
Brian Anderson 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
  of resolving those constraints.

- regionck: after main is complete, the regionck pass goes over all
  types looking for regions and making sure that they did not escape
  into places they are not in scope.  This may also influence the
  final assignments of the various region variables if there is some
  flexibility.

- vtable: find and records the impls to use for each trait bound that
  appears on a type parameter.

- writeback: writes the final types within a function body, replacing
  type variables with their final inferred types.  These final types
  are written into the `tcx.node_types` table, which should *never* contain
  any reference to a type variable.

## Intermediate types

While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
55
stored in `fcx.node_types` and `fcx.item_substs`.  These types
B
Brian Anderson 已提交
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
may contain unresolved type variables.  After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
permanent home in the type context `ccx.tcx`.

This means that during inferencing you should use `fcx.write_ty()`
and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
nodes within the function.

The types of top-level items, which never contain unbound type
variables, are stored directly into the `tcx` tables.

n.b.: A type variable is not the same thing as a type parameter.  A
type variable is rather an "instance" of a type parameter: that is,
given a generic function `fn foo<T>(t: T)`: while checking the
function `foo`, the type `ty_param(0)` refers to the type `T`, which
is treated in abstract.  When `foo()` is called, however, `T` will be
substituted for a fresh type variable `N`.  This variable will
eventually be resolved to some concrete type (which might itself be
type parameter).

*/

79
pub use self::Expectation::*;
80
pub use self::compare_method::{compare_impl_method, compare_const_impl};
S
Steven Fackler 已提交
81
use self::TupleArgumentsFlag::*;
82

83
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
N
Niko Matsakis 已提交
84
use check::_match::pat_ctxt;
M
Manish Goregaokar 已提交
85
use fmt_macros::{Parser, Piece, Position};
N
Niko Matsakis 已提交
86
use metadata::cstore::LOCAL_CRATE;
87
use middle::astconv_util::prohibit_type_params;
88
use middle::def;
N
Niko Matsakis 已提交
89
use middle::def_id::DefId;
90
use middle::infer;
91
use middle::infer::type_variable;
92
use middle::pat_util::{self, pat_id_map};
93
use middle::privacy::{AllPublic, LastMod};
94
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
N
Nick Cameron 已提交
95
use middle::traits::{self, report_fulfillment_errors};
96
use middle::ty::{FnSig, GenericPredicates, TypeScheme};
97
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
98
use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
99
use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
100
use middle::ty::{MethodCall, MethodCallee};
101
use middle::ty::adjustment;
102
use middle::ty::error::TypeError;
103
use middle::ty::fold::{TypeFolder, TypeFoldable};
104
use middle::ty::util::Representability;
105
use require_c_abi_if_variadic;
106
use rscope::{ElisionFailureInfo, RegionScope};
N
Niko Matsakis 已提交
107
use session::Session;
108
use {CrateCtxt, lookup_full_def};
N
Niko Matsakis 已提交
109
use TypeAndSubsts;
110
use lint;
111
use util::common::{block_query, ErrorReported, indenter, loop_query};
112
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
113
use util::lev_distance::lev_distance;
114

J
Jakub Bukaj 已提交
115
use std::cell::{Cell, Ref, RefCell};
116
use std::collections::{HashSet};
117
use std::mem::replace;
118 119
use syntax::abi;
use syntax::ast;
120 121
use syntax::attr;
use syntax::attr::AttrMetaMethods;
122
use syntax::codemap::{self, Span, Spanned};
123
use syntax::owned_slice::OwnedSlice;
124
use syntax::parse::token::{self, InternedString};
125
use syntax::ptr::P;
126 127 128 129 130 131

use rustc_front::visit::{self, Visitor};
use rustc_front::hir;
use rustc_front::hir::Visibility;
use rustc_front::hir::{Item, ItemImpl};
use rustc_front::print::pprust;
132
use rustc_back::slice;
B
Brian Anderson 已提交
133

134
mod assoc;
F
Felix S. Klock II 已提交
135
pub mod dropck;
136
pub mod _match;
137 138
pub mod writeback;
pub mod regionck;
139
pub mod coercion;
140
pub mod demand;
B
Brian Anderson 已提交
141
pub mod method;
142
mod upvar;
143 144
mod wf;
mod wfcheck;
145
mod cast;
146
mod closure;
147
mod callee;
148
mod compare_method;
149
mod intrinsic;
150
mod op;
B
Brian Anderson 已提交
151 152 153 154

/// closures defined within the function.  For example:
///
///     fn foo() {
155
///         bar(move|| { ... })
B
Brian Anderson 已提交
156 157 158
///     }
///
/// Here, the function `foo()` and the closure passed to
159
/// `bar()` will each have their own `FnCtxt`, but they will
B
Brian Anderson 已提交
160
/// share the inherited fields.
161 162
pub struct Inherited<'a, 'tcx: 'a> {
    infcx: infer::InferCtxt<'a, 'tcx>,
163
    locals: RefCell<NodeMap<Ty<'tcx>>>,
164

165
    tables: &'a RefCell<ty::Tables<'tcx>>,
166

167 168 169 170
    // When we process a call like `c()` where `c` is a closure type,
    // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
    // `FnOnce` closure. In that case, we defer full resolution of the
    // call until upvar inference can kick in and make the
171
    // decision. We keep these deferred resolutions grouped by the
172 173 174
    // def-id of the closure, so that once we decide, we can easily go
    // back and process them.
    deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
N
Nick Cameron 已提交
175

176
    deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
177 178
}

179 180
trait DeferredCallResolution<'tcx> {
    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
181 182
}

183
type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
184

185 186
/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
187
#[derive(Copy, Clone, Debug)]
188
pub enum Expectation<'tcx> {
189 190 191 192
    /// We know nothing about what type this expression should have.
    NoExpectation,

    /// This expression should have the type given (or some subtype)
193
    ExpectHasType(Ty<'tcx>),
194

195
    /// This expression will be cast to the `Ty`
196
    ExpectCastableToType(Ty<'tcx>),
197 198 199 200

    /// This rvalue expression will be wrapped in `&` or `Box` and coerced
    /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
    ExpectRvalueLikeUnsized(Ty<'tcx>),
201 202
}

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
impl<'tcx> Expectation<'tcx> {
    // Disregard "castable to" expectations because they
    // can lead us astray. Consider for example `if cond
    // {22} else {c} as u8` -- if we propagate the
    // "castable to u8" constraint to 22, it will pick the
    // type 22u8, which is overly constrained (c might not
    // be a u8). In effect, the problem is that the
    // "castable to" expectation is not the tightest thing
    // we can say, so we want to drop it in this case.
    // The tightest thing we can say is "must unify with
    // else branch". Note that in the case of a "has type"
    // constraint, this limitation does not hold.

    // If the expected type is just a type variable, then don't use
    // an expected type. Otherwise, we might write parts of the type
    // when checking the 'then' block which are incompatible with the
    // 'else' branch.
    fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
221
        match *self {
222 223
            ExpectHasType(ety) => {
                let ety = fcx.infcx().shallow_resolve(ety);
224
                if !ety.is_ty_var() {
225 226 227 228 229
                    ExpectHasType(ety)
                } else {
                    NoExpectation
                }
            }
230 231 232
            ExpectRvalueLikeUnsized(ety) => {
                ExpectRvalueLikeUnsized(ety)
            }
233 234 235 236 237
            _ => NoExpectation
        }
    }
}

238
#[derive(Copy, Clone)]
N
Niko Matsakis 已提交
239
pub struct UnsafetyState {
240
    pub def: ast::NodeId,
241
    pub unsafety: hir::Unsafety,
242
    pub unsafe_push_count: u32,
243
    from_fn: bool
244 245
}

N
Niko Matsakis 已提交
246
impl UnsafetyState {
247
    pub fn function(unsafety: hir::Unsafety, def: ast::NodeId) -> UnsafetyState {
248
        UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true }
249 250
    }

251
    pub fn recurse(&mut self, blk: &hir::Block) -> UnsafetyState {
N
Niko Matsakis 已提交
252
        match self.unsafety {
253 254 255 256
            // If this unsafe, then if the outer function was already marked as
            // unsafe we shouldn't attribute the unsafe'ness to the block. This
            // way the block can be warned about instead of ignoring this
            // extraneous block (functions are never warned about).
257
            hir::Unsafety::Unsafe if self.from_fn => *self,
258

N
Niko Matsakis 已提交
259
            unsafety => {
260
                let (unsafety, def, count) = match blk.rules {
261
                    hir::PushUnsafeBlock(..) =>
262
                        (unsafety, blk.id, self.unsafe_push_count.checked_add(1).unwrap()),
263
                    hir::PopUnsafeBlock(..) =>
264
                        (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
265 266
                    hir::UnsafeBlock(..) =>
                        (hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
N
Nick Cameron 已提交
267
                    hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock =>
268
                        (unsafety, self.def, self.unsafe_push_count),
269
                };
N
Niko Matsakis 已提交
270
                UnsafetyState{ def: def,
271 272 273
                               unsafety: unsafety,
                               unsafe_push_count: count,
                               from_fn: false }
274 275 276
            }
        }
    }
277 278
}

279
#[derive(Clone)]
280
pub struct FnCtxt<'a, 'tcx: 'a> {
281 282
    body_id: ast::NodeId,

283 284 285 286
    // This flag is set to true if, during the writeback phase, we encounter
    // a type error in this function.
    writeback_errors: Cell<bool>,

287 288 289 290
    // Number of errors that had been reported when we started
    // checking this function. On exit, if we find that *more* errors
    // have been reported, we will skip regionck and other work that
    // expects the types within the function to be consistent.
291
    err_count_on_creation: usize,
292

293
    ret_ty: ty::FnOutput<'tcx>,
B
Brian Anderson 已提交
294

N
Niko Matsakis 已提交
295
    ps: RefCell<UnsafetyState>,
B
Brian Anderson 已提交
296

297
    inh: &'a Inherited<'a, 'tcx>,
B
Brian Anderson 已提交
298

299
    ccx: &'a CrateCtxt<'a, 'tcx>,
B
Brian Anderson 已提交
300 301
}

302 303
impl<'a, 'tcx> Inherited<'a, 'tcx> {
    fn new(tcx: &'a ty::ctxt<'tcx>,
304
           tables: &'a RefCell<ty::Tables<'tcx>>,
305
           param_env: ty::ParameterEnvironment<'a, 'tcx>)
306
           -> Inherited<'a, 'tcx> {
307

308
        Inherited {
309
            infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
310
            locals: RefCell::new(NodeMap()),
311
            tables: tables,
312
            deferred_call_resolutions: RefCell::new(DefIdMap()),
N
Nick Cameron 已提交
313
            deferred_cast_checks: RefCell::new(Vec::new()),
314
        }
B
Brian Anderson 已提交
315
    }
316

317 318 319 320 321
    fn normalize_associated_types_in<T>(&self,
                                        span: Span,
                                        body_id: ast::NodeId,
                                        value: &T)
                                        -> T
322
        where T : TypeFoldable<'tcx> + HasTypeFlags
323
    {
324
        let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
325
        assoc::normalize_associated_types_in(&self.infcx,
326 327
                                             &mut fulfillment_cx,
                                             span,
328 329 330 331
                                             body_id,
                                             value)
    }

B
Brian Anderson 已提交
332 333 334
}

// Used by check_const and check_enum_variants
335 336
pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                               inh: &'a Inherited<'a, 'tcx>,
337
                               rty: ty::FnOutput<'tcx>,
338 339
                               body_id: ast::NodeId)
                               -> FnCtxt<'a, 'tcx> {
E
Eduard Burtescu 已提交
340
    FnCtxt {
341
        body_id: body_id,
342
        writeback_errors: Cell::new(false),
343
        err_count_on_creation: ccx.tcx.sess.err_count(),
B
Brian Anderson 已提交
344
        ret_ty: rty,
345
        ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, 0)),
E
Eduard Burtescu 已提交
346
        inh: inh,
B
Brian Anderson 已提交
347 348 349 350
        ccx: ccx
    }
}

J
Jared Roesch 已提交
351 352
fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                                     tables: &'a RefCell<ty::Tables<'tcx>>)
353
                                    -> Inherited<'a, 'tcx> {
E
Eduard Burtescu 已提交
354 355
    // It's kind of a kludge to manufacture a fake function context
    // and statement context, but we might as well do write the code only once
356
    let param_env = ccx.tcx.empty_parameter_environment();
357
    Inherited::new(ccx.tcx, &tables, param_env)
E
Eduard Burtescu 已提交
358 359
}

360
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
361
struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
362

363
impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
364
    fn visit_item(&mut self, i: &'tcx hir::Item) {
365
        check_item_type(self.ccx, i);
366
        visit::walk_item(self, i);
367
    }
368

369
    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
370
        match t.node {
371
            hir::TyFixedLengthVec(_, ref expr) => {
372
                check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
373
            }
374 375 376 377 378
            hir::TyBareFn(ref function_declaration) => {
                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
                return
            }
379 380 381 382 383
            _ => {}
        }

        visit::walk_ty(self, t);
    }
384 385
}

386
impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
387
    fn visit_item(&mut self, i: &'tcx hir::Item) {
388 389 390 391 392
        check_item_body(self.ccx, i);
        visit::walk_item(self, i);
    }
}

393 394 395 396 397 398
pub fn check_wf_old(ccx: &CrateCtxt) {
    // FIXME(#25759). The new code below is much more reliable but (for now)
    // only generates warnings. So as to ensure that we continue
    // getting errors where we used to get errors, we run the old wf
    // code first and abort if it encounters any errors. If no abort
    // comes, we run the new code and issue warnings.
399
    let krate = ccx.tcx.map.krate();
400
    let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
401
    visit::walk_crate(&mut visit, krate);
402 403 404 405

    // If types are not well-formed, it leads to all manner of errors
    // downstream, so stop reporting errors at this point.
    ccx.tcx.sess.abort_if_errors();
406
}
407

408 409 410
pub fn check_wf_new(ccx: &CrateCtxt) {
    let krate = ccx.tcx.map.krate();
    let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
411
    visit::walk_crate(&mut visit, krate);
N
Nick Cameron 已提交
412

413 414
    // If types are not well-formed, it leads to all manner of errors
    // downstream, so stop reporting errors at this point.
N
Nick Cameron 已提交
415
    ccx.tcx.sess.abort_if_errors();
416
}
417

418 419 420 421 422 423 424 425 426
pub fn check_item_types(ccx: &CrateCtxt) {
    let krate = ccx.tcx.map.krate();
    let mut visit = CheckItemTypesVisitor { ccx: ccx };
    visit::walk_crate(&mut visit, krate);
    ccx.tcx.sess.abort_if_errors();
}

pub fn check_item_bodies(ccx: &CrateCtxt) {
    let krate = ccx.tcx.map.krate();
427 428 429 430
    let mut visit = CheckItemBodiesVisitor { ccx: ccx };
    visit::walk_crate(&mut visit, krate);

    ccx.tcx.sess.abort_if_errors();
431
}
432

433
pub fn check_drop_impls(ccx: &CrateCtxt) {
A
Ariel Ben-Yehuda 已提交
434 435 436 437 438
    let drop_trait = match ccx.tcx.lang_items.drop_trait() {
        Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
    };
    drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
        if drop_impl_did.is_local() {
439 440 441 442 443 444 445
            match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
                Ok(()) => {}
                Err(()) => {
                    assert!(ccx.tcx.sess.has_errors());
                }
            }
        }
A
Ariel Ben-Yehuda 已提交
446
    });
447 448

    ccx.tcx.sess.abort_if_errors();
B
Brian Anderson 已提交
449 450
}

451
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
452 453
                           decl: &'tcx hir::FnDecl,
                           body: &'tcx hir::Block,
454 455
                           fn_id: ast::NodeId,
                           fn_span: Span,
456
                           raw_fty: Ty<'tcx>,
457 458
                           param_env: ty::ParameterEnvironment<'a, 'tcx>)
{
459
    match raw_fty.sty {
460
        ty::TyBareFn(_, ref fn_ty) => {
461 462
            let tables = RefCell::new(ty::Tables::empty());
            let inh = Inherited::new(ccx.tcx, &tables, param_env);
463

464
            // Compute the fty from point of view of inside fn.
465
            let fn_scope = ccx.tcx.region_maps.item_extent(body.id);
466
            let fn_sig =
467
                fn_ty.sig.subst(ccx.tcx, &inh.infcx.parameter_environment.free_substs);
468
            let fn_sig =
469
                ccx.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
470
            let fn_sig =
J
Jared Roesch 已提交
471
                inh.normalize_associated_types_in(body.span,
472 473
                                                  body.id,
                                                  &fn_sig);
474

475 476
            let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
                               decl, fn_id, body, &inh);
477

N
Nick Cameron 已提交
478
            fcx.select_all_obligations_and_apply_defaults();
479
            upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
480
            fcx.select_obligations_where_possible();
N
Nick Cameron 已提交
481
            fcx.check_casts();
A
Ariel Ben-Yehuda 已提交
482 483
            fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.

484
            regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
E
Eduard Burtescu 已提交
485
            writeback::resolve_type_vars_in_fn(&fcx, decl, body);
B
Brian Anderson 已提交
486 487 488 489 490 491
        }
        _ => ccx.tcx.sess.impossible_case(body.span,
                                 "check_bare_fn: function type expected")
    }
}

492 493
struct GatherLocalsVisitor<'a, 'tcx: 'a> {
    fcx: &'a FnCtxt<'a, 'tcx>
494 495
}

496
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
497
    fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
498 499 500
        match ty_opt {
            None => {
                // infer the variable's type
J
Jakub Bukaj 已提交
501
                let var_ty = self.fcx.infcx().next_ty_var();
502 503
                self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
                var_ty
504
            }
505 506 507 508 509 510
            Some(typ) => {
                // take type that the user specified
                self.fcx.inh.locals.borrow_mut().insert(nid, typ);
                typ
            }
        }
511 512 513
    }
}

514
impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
515
    // Add explicitly-declared locals.
516
    fn visit_local(&mut self, local: &'tcx hir::Local) {
S
Seo Sanghyeon 已提交
517 518 519
        let o_ty = match local.ty {
            Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
            None => None
520
        };
521
        self.assign(local.span, local.id, o_ty);
522 523
        debug!("Local variable {:?} is assigned type {}",
               local.pat,
524
               self.fcx.infcx().ty_to_string(
525
                   self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
526
        visit::walk_local(self, local);
527
    }
528 529

    // Add pattern bindings.
530 531
    fn visit_pat(&mut self, p: &'tcx hir::Pat) {
        if let hir::PatIdent(_, ref path1, _) = p.node {
532
            if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map.borrow(), p) {
533 534 535 536 537
                let var_ty = self.assign(p.span, p.id, None);

                self.fcx.require_type_is_sized(var_ty, p.span,
                                               traits::VariableType(p.id));

538
                debug!("Pattern binding {} is assigned to {} with type {:?}",
539
                       path1.node,
540
                       self.fcx.infcx().ty_to_string(
541
                           self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
542
                       var_ty);
543
            }
544 545
        }
        visit::walk_pat(self, p);
546 547
    }

548
    fn visit_block(&mut self, b: &'tcx hir::Block) {
549 550 551
        // non-obvious: the `blk` variable maps to region lb, so
        // we have to keep this up-to-date.  This
        // is... unfortunate.  It'd be nice to not need this.
552
        visit::walk_block(self, b);
553 554
    }

555 556
    // Since an expr occurs as part of the type fixed size arrays we
    // need to record the type for that node
557
    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
558
        match t.node {
559
            hir::TyFixedLengthVec(ref ty, ref count_expr) => {
560
                self.visit_ty(&**ty);
561
                check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
562
            }
563 564 565 566
            hir::TyBareFn(ref function_declaration) => {
                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
            }
567
            _ => visit::walk_ty(self, t)
568 569 570
        }
    }

E
Eduard Burtescu 已提交
571
    // Don't descend into fns and items
572 573 574
    fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx hir::FnDecl,
                _: &'tcx hir::Block, _: Span, _: ast::NodeId) { }
    fn visit_item(&mut self, _: &hir::Item) { }
575 576 577

}

S
Steve Klabnik 已提交
578 579 580 581 582 583
/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
/// body and returns the function context used for that purpose, since in the case of a fn item
/// there is still a bit more to do.
///
/// * ...
/// * inherited: other fields inherited from the enclosing fn (if any)
584
fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
585
                      unsafety: hir::Unsafety,
N
Niko Matsakis 已提交
586
                      unsafety_id: ast::NodeId,
587
                      fn_sig: &ty::FnSig<'tcx>,
588
                      decl: &'tcx hir::FnDecl,
589
                      fn_id: ast::NodeId,
590
                      body: &'tcx hir::Block,
591
                      inherited: &'a Inherited<'a, 'tcx>)
592 593
                      -> FnCtxt<'a, 'tcx>
{
B
Brian Anderson 已提交
594
    let tcx = ccx.tcx;
595
    let err_count_on_creation = tcx.sess.err_count();
B
Brian Anderson 已提交
596

597
    let arg_tys = &fn_sig.inputs;
598
    let ret_ty = fn_sig.output;
B
Brian Anderson 已提交
599

600 601 602
    debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
           arg_tys,
           ret_ty,
603
           fn_id);
B
Brian Anderson 已提交
604 605 606

    // Create the function context.  This is either derived from scratch or,
    // in the case of function expressions, based on the outer context.
E
Eduard Burtescu 已提交
607
    let fcx = FnCtxt {
608
        body_id: body.id,
609
        writeback_errors: Cell::new(false),
610 611
        err_count_on_creation: err_count_on_creation,
        ret_ty: ret_ty,
N
Niko Matsakis 已提交
612
        ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
613 614
        inh: inherited,
        ccx: ccx
B
Brian Anderson 已提交
615 616
    };

J
Jakub Bukaj 已提交
617
    if let ty::FnConverging(ret_ty) = ret_ty {
618
        fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
J
Jakub Bukaj 已提交
619 620
    }

621
    debug!("fn-sig-map: fn_id={} fn_sig={:?}", fn_id, fn_sig);
622

623
    inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig.clone());
B
Brian Anderson 已提交
624

625
    {
E
Eduard Burtescu 已提交
626
        let mut visit = GatherLocalsVisitor { fcx: &fcx, };
627

B
Brian Anderson 已提交
628
        // Add formal parameters.
629
        for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
630 631 632 633 634 635 636 637
            // The type of the argument must be well-formed.
            //
            // NB -- this is now checked in wfcheck, but that
            // currently only results in warnings, so we issue an
            // old-style WF obligation here so that we still get the
            // errors that we used to get.
            fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation);

B
Brian Anderson 已提交
638
            // Create type variables for each argument.
639 640 641 642 643 644 645 646
            pat_util::pat_bindings(
                &tcx.def_map,
                &*input.pat,
                |_bm, pat_id, sp, _path| {
                    let var_ty = visit.assign(sp, pat_id, None);
                    fcx.require_type_is_sized(var_ty, sp,
                                              traits::VariableType(pat_id));
                });
B
Brian Anderson 已提交
647 648

            // Check the pattern.
649
            let pcx = pat_ctxt {
E
Eduard Burtescu 已提交
650
                fcx: &fcx,
651
                map: pat_id_map(&tcx.def_map, &*input.pat),
B
Brian Anderson 已提交
652
            };
653
            _match::check_pat(&pcx, &*input.pat, *arg_ty);
B
Brian Anderson 已提交
654 655
        }

656
        visit.visit_block(body);
B
Brian Anderson 已提交
657
    }
658

J
Jakub Bukaj 已提交
659 660 661 662
    check_block_with_expected(&fcx, body, match ret_ty {
        ty::FnConverging(result_type) => ExpectHasType(result_type),
        ty::FnDiverging => NoExpectation
    });
663

664 665
    for (input, arg) in decl.inputs.iter().zip(arg_tys) {
        fcx.write_ty(input.id, arg);
666 667 668
    }

    fcx
B
Brian Anderson 已提交
669 670
}

E
Eduard Burtescu 已提交
671
pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
S
Seo Sanghyeon 已提交
672 673
    let tcx = ccx.tcx;

674
    check_representable(tcx, span, id, "struct");
S
Seo Sanghyeon 已提交
675

676
    if tcx.lookup_simd(ccx.tcx.map.local_def_id(id)) {
S
Seo Sanghyeon 已提交
677 678
        check_simd(tcx, span, id);
    }
B
Brian Anderson 已提交
679 680
}

681
pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
682
    debug!("check_item_type(it.id={}, it.name={})",
B
Brian Anderson 已提交
683
           it.id,
684
           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
B
Brian Anderson 已提交
685
    let _indenter = indenter();
686
    match it.node {
687
      // Consts can play a role in type-checking, so they are included here.
688 689 690
      hir::ItemStatic(_, _, ref e) |
      hir::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
      hir::ItemEnum(ref enum_definition, _) => {
691 692
        check_enum_variants(ccx,
                            it.span,
693
                            &enum_definition.variants,
694
                            it.id);
B
Brian Anderson 已提交
695
      }
696 697
      hir::ItemFn(..) => {} // entirely within check_item_body
      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
V
Vadim Petrochenkov 已提交
698
          debug!("ItemImpl {} with id {}", it.name, it.id);
699
          match ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(it.id)) {
700
              Some(impl_trait_ref) => {
701 702
                check_impl_items_against_trait(ccx,
                                               it.span,
703
                                               &impl_trait_ref,
704
                                               impl_items);
705 706 707
              }
              None => { }
          }
B
Brian Anderson 已提交
708
      }
709
      hir::ItemTrait(_, ref generics, _, _) => {
M
Manish Goregaokar 已提交
710
        check_trait_on_unimplemented(ccx, generics, it);
B
Brian Anderson 已提交
711
      }
712
      hir::ItemStruct(..) => {
E
Erick Tryzelaar 已提交
713
        check_struct(ccx, it.id, it.span);
B
Brian Anderson 已提交
714
      }
715
      hir::ItemTy(ref t, ref generics) => {
716
        let pty_ty = ccx.tcx.node_id_to_type(it.id);
717
        check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
B
Brian Anderson 已提交
718
      }
719
      hir::ItemForeignMod(ref m) => {
720
        if m.abi == abi::RustIntrinsic {
721
            for item in &m.items {
722
                intrinsic::check_intrinsic_type(ccx, &**item);
B
Brian Anderson 已提交
723
            }
724 725
        } else if m.abi == abi::PlatformIntrinsic {
            for item in &m.items {
726
                intrinsic::check_platform_intrinsic_type(ccx, &**item);
B
Brian Anderson 已提交
727 728
            }
        } else {
729
            for item in &m.items {
730
                let pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(item.id));
731
                if !pty.generics.types.is_empty() {
732 733
                    span_err!(ccx.tcx.sess, item.span, E0044,
                        "foreign items may not have type parameters");
G
Guillaume Gomez 已提交
734 735
                    span_help!(ccx.tcx.sess, item.span,
                        "consider using specialization instead of \
G
Guillaume Gomez 已提交
736
                        type parameters");
737 738
                }

739
                if let hir::ForeignItemFn(ref fn_decl, _) = item.node {
740
                    require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
B
Brian Anderson 已提交
741 742 743 744 745 746 747 748
                }
            }
        }
      }
      _ => {/* nothing to do */ }
    }
}

749
pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
750
    debug!("check_item_body(it.id={}, it.name={})",
751
           it.id,
752
           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
753 754
    let _indenter = indenter();
    match it.node {
755
      hir::ItemFn(ref decl, _, _, _, _, ref body) => {
756
        let fn_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
757 758 759
        let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
        check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
      }
760
      hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
V
Vadim Petrochenkov 已提交
761
        debug!("ItemImpl {} with id {}", it.name, it.id);
762

763
        let impl_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
764 765 766

        for impl_item in impl_items {
            match impl_item.node {
767
                hir::ImplItem_::Const(_, ref expr) => {
768 769
                    check_const(ccx, impl_item.span, &*expr, impl_item.id)
                }
770
                hir::ImplItem_::Method(ref sig, ref body) => {
771 772 773
                    check_method_body(ccx, &impl_pty.generics, sig, body,
                                      impl_item.id, impl_item.span);
                }
774
                hir::ImplItem_::Type(_) => {
775 776 777 778 779
                    // Nothing to do here.
                }
            }
        }
      }
780
      hir::ItemTrait(_, _, _, ref trait_items) => {
781
        let trait_def = ccx.tcx.lookup_trait_def(ccx.tcx.map.local_def_id(it.id));
782 783
        for trait_item in trait_items {
            match trait_item.node {
784
                hir::ConstTraitItem(_, Some(ref expr)) => {
785
                    check_const(ccx, trait_item.span, &*expr, trait_item.id)
786
                }
787
                hir::MethodTraitItem(ref sig, Some(ref body)) => {
N
Niko Matsakis 已提交
788 789
                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);

790 791 792
                    check_method_body(ccx, &trait_def.generics, sig, body,
                                      trait_item.id, trait_item.span);
                }
793
                hir::MethodTraitItem(ref sig, None) => {
N
Niko Matsakis 已提交
794 795
                    check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
                }
796 797
                hir::ConstTraitItem(_, None) |
                hir::TypeTraitItem(..) => {
798 799 800 801 802 803 804 805 806
                    // Nothing to do.
                }
            }
        }
      }
      _ => {/* nothing to do */ }
    }
}

N
Niko Matsakis 已提交
807 808
fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     span: Span,
809
                                     constness: hir::Constness)
N
Niko Matsakis 已提交
810 811
{
    match constness {
812
        hir::Constness::NotConst => {
N
Niko Matsakis 已提交
813 814
            // good
        }
815
        hir::Constness::Const => {
N
Niko Matsakis 已提交
816 817 818 819 820
            span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
        }
    }
}

M
Manish Goregaokar 已提交
821
fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
822 823
                               generics: &hir::Generics,
                               item: &hir::Item) {
824
    if let Some(ref attr) = item.attrs.iter().find(|a| {
825
        a.check_name("rustc_on_unimplemented")
M
Manish Goregaokar 已提交
826 827
    }) {
        if let Some(ref istring) = attr.value_str() {
828
            let parser = Parser::new(&istring);
829
            let types = &*generics.ty_params;
M
Manish Goregaokar 已提交
830 831 832 833 834 835 836 837
            for token in parser {
                match token {
                    Piece::String(_) => (), // Normal string, no need to check it
                    Piece::NextArgument(a) => match a.position {
                        // `{Self}` is allowed
                        Position::ArgumentNamed(s) if s == "Self" => (),
                        // So is `{A}` if A is a type parameter
                        Position::ArgumentNamed(s) => match types.iter().find(|t| {
838
                            t.name.as_str() == s
M
Manish Goregaokar 已提交
839 840 841
                        }) {
                            Some(_) => (),
                            None => {
B
Brian Anderson 已提交
842 843
                                span_err!(ccx.tcx.sess, attr.span, E0230,
                                                 "there is no type parameter \
M
Manish Goregaokar 已提交
844
                                                          {} on trait {}",
V
Vadim Petrochenkov 已提交
845
                                                           s, item.name);
M
Manish Goregaokar 已提交
846 847 848 849
                            }
                        },
                        // `{:1}` and `{}` are not to be used
                        Position::ArgumentIs(_) | Position::ArgumentNext => {
B
Brian Anderson 已提交
850
                            span_err!(ccx.tcx.sess, attr.span, E0231,
M
Manish Goregaokar 已提交
851 852 853 854 855 856 857
                                                  "only named substitution \
                                                   parameters are allowed");
                        }
                    }
                }
            }
        } else {
B
Brian Anderson 已提交
858
            span_err!(ccx.tcx.sess, attr.span, E0232,
M
Manish Goregaokar 已提交
859
                                  "this attribute must have a value, \
860
                                   eg `#[rustc_on_unimplemented = \"foo\"]`")
M
Manish Goregaokar 已提交
861 862 863 864
        }
    }
}

S
Steve Klabnik 已提交
865 866 867 868 869 870 871 872
/// Type checks a method body.
///
/// # Parameters
///
/// * `item_generics`: generics defined on the impl/trait that contains
///   the method
/// * `self_bound`: bound for the `Self` type parameter, if any
/// * `method`: the method definition
873 874
fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               item_generics: &ty::Generics<'tcx>,
875 876
                               sig: &'tcx hir::MethodSig,
                               body: &'tcx hir::Block,
877
                               id: ast::NodeId, span: Span) {
878 879
    debug!("check_method_body(item_generics={:?}, id={})",
            item_generics, id);
880
    let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
881

882
    let fty = ccx.tcx.node_id_to_type(id);
883
    debug!("check_method_body: fty={:?}", fty);
884

885
    check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
886 887
}

888 889
fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            impl_span: Span,
890
                                            impl_trait_ref: &ty::TraitRef<'tcx>,
891
                                            impl_items: &[P<hir::ImplItem>]) {
892 893
    // Locate trait methods
    let tcx = ccx.tcx;
894
    let trait_items = tcx.trait_items(impl_trait_ref.def_id);
895
    let mut overridden_associated_type = None;
896 897 898

    // Check existing impl methods to see if they are both present in trait
    // and compatible with trait signature
899
    for impl_item in impl_items {
900
        let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id));
901 902 903 904 905 906
        let ty_trait_item = trait_items.iter()
            .find(|ac| ac.name() == ty_impl_item.name())
            .unwrap_or_else(|| {
                // This is checked by resolve
                tcx.sess.span_bug(impl_item.span,
                                  &format!("impl-item `{}` is not a member of `{:?}`",
907
                                           ty_impl_item.name(),
908 909
                                           impl_trait_ref));
            });
910
        match impl_item.node {
911
            hir::ImplItem_::Const(..) => {
912 913 914 915
                let impl_const = match ty_impl_item {
                    ty::ConstTraitItem(ref cti) => cti,
                    _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
                };
916 917

                // Find associated const definition.
918 919 920 921 922 923 924 925 926 927
                if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
                    compare_const_impl(ccx.tcx,
                                       &impl_const,
                                       impl_item.span,
                                       trait_const,
                                       &*impl_trait_ref);
                } else {
                    span_err!(tcx.sess, impl_item.span, E0323,
                              "item `{}` is an associated const, \
                              which doesn't match its trait `{:?}`",
928
                              impl_const.name,
929
                              impl_trait_ref)
930 931
                }
            }
932
            hir::ImplItem_::Method(ref sig, ref body) => {
N
Niko Matsakis 已提交
933 934
                check_trait_fn_not_const(ccx, impl_item.span, sig.constness);

935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
                let impl_method = match ty_impl_item {
                    ty::MethodTraitItem(ref mti) => mti,
                    _ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
                };

                if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
                    compare_impl_method(ccx.tcx,
                                        &impl_method,
                                        impl_item.span,
                                        body.id,
                                        &trait_method,
                                        &impl_trait_ref);
                } else {
                    span_err!(tcx.sess, impl_item.span, E0324,
                              "item `{}` is an associated method, \
                              which doesn't match its trait `{:?}`",
951
                              impl_method.name,
952
                              impl_trait_ref)
953
                }
954
            }
955
            hir::ImplItem_::Type(_) => {
956 957 958 959 960
                let impl_type = match ty_impl_item {
                    ty::TypeTraitItem(ref tti) => tti,
                    _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
                };

961 962 963 964
                if let &ty::TypeTraitItem(ref at) = ty_trait_item {
                    if let Some(_) = at.ty {
                        overridden_associated_type = Some(impl_item);
                    }
965 966 967 968
                } else {
                    span_err!(tcx.sess, impl_item.span, E0325,
                              "item `{}` is an associated type, \
                              which doesn't match its trait `{:?}`",
969
                              impl_type.name,
970
                              impl_trait_ref)
971 972
                }
            }
973 974 975
        }
    }

976
    // Check for missing items from trait
977
    let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
978
    let mut missing_items = Vec::new();
979 980
    let mut invalidated_items = Vec::new();
    let associated_type_overridden = overridden_associated_type.is_some();
981
    for trait_item in trait_items.iter() {
982
        match *trait_item {
983 984 985
            ty::ConstTraitItem(ref associated_const) => {
                let is_implemented = impl_items.iter().any(|ii| {
                    match ii.node {
986
                        hir::ImplItem_::Const(..) => {
V
Vadim Petrochenkov 已提交
987
                            ii.name == associated_const.name
988 989 990 991
                        }
                        _ => false,
                    }
                });
992 993
                let is_provided = associated_const.has_value;

994 995 996 997 998 999
                if !is_implemented {
                    if !is_provided {
                        missing_items.push(associated_const.name);
                    } else if associated_type_overridden {
                        invalidated_items.push(associated_const.name);
                    }
1000 1001
                }
            }
1002 1003 1004
            ty::MethodTraitItem(ref trait_method) => {
                let is_implemented =
                    impl_items.iter().any(|ii| {
1005
                        match ii.node {
1006
                            hir::ImplItem_::Method(..) => {
V
Vadim Petrochenkov 已提交
1007
                                ii.name == trait_method.name
1008
                            }
1009
                            _ => false,
1010 1011 1012
                        }
                    });
                let is_provided =
1013
                    provided_methods.iter().any(|m| m.name == trait_method.name);
1014 1015 1016 1017 1018 1019
                if !is_implemented {
                    if !is_provided {
                        missing_items.push(trait_method.name);
                    } else if associated_type_overridden {
                        invalidated_items.push(trait_method.name);
                    }
1020 1021
                }
            }
1022 1023
            ty::TypeTraitItem(ref associated_type) => {
                let is_implemented = impl_items.iter().any(|ii| {
1024
                    match ii.node {
1025
                        hir::ImplItem_::Type(_) => {
V
Vadim Petrochenkov 已提交
1026
                            ii.name == associated_type.name
1027
                        }
1028
                        _ => false,
1029 1030
                    }
                });
1031
                let is_provided = associated_type.ty.is_some();
1032 1033 1034 1035 1036 1037
                if !is_implemented {
                    if !is_provided {
                        missing_items.push(associated_type.name);
                    } else if associated_type_overridden {
                        invalidated_items.push(associated_type.name);
                    }
1038 1039
                }
            }
1040 1041 1042
        }
    }

1043
    if !missing_items.is_empty() {
1044
        span_err!(tcx.sess, impl_span, E0046,
1045 1046
            "not all trait items implemented, missing: `{}`",
            missing_items.iter()
1047
                  .map(|name| name.to_string())
1048
                  .collect::<Vec<_>>().join("`, `"))
1049 1050 1051 1052 1053 1054 1055
    }

    if !invalidated_items.is_empty() {
        let invalidator = overridden_associated_type.unwrap();
        span_err!(tcx.sess, invalidator.span, E0399,
                  "the following trait items need to be reimplemented \
                   as `{}` was overridden: `{}`",
V
Vadim Petrochenkov 已提交
1056
                  invalidator.name,
1057
                  invalidated_items.iter()
1058
                                   .map(|name| name.to_string())
1059
                                   .collect::<Vec<_>>().join("`, `"))
1060 1061 1062
    }
}

1063 1064 1065 1066
fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                         span: Span,
                                         t_span: Span,
                                         e_span: Span,
A
Ariel Ben-Yehuda 已提交
1067 1068
                                         t_cast: Ty<'tcx>,
                                         t_expr: Ty<'tcx>,
1069
                                         id: ast::NodeId) {
A
Ariel Ben-Yehuda 已提交
1070
    let tstr = fcx.infcx().ty_to_string(t_cast);
1071 1072
    fcx.type_error_message(span, |actual| {
        format!("cast to unsized type: `{}` as `{}`", actual, tstr)
A
Ariel Ben-Yehuda 已提交
1073 1074
    }, t_expr, None);
    match t_expr.sty {
1075
        ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
1076
            let mtstr = match mt {
1077 1078
                hir::MutMutable => "mut ",
                hir::MutImmutable => ""
1079
            };
1080
            if t_cast.is_trait() {
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
                match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                    Ok(s) => {
                        fcx.tcx().sess.span_suggestion(t_span,
                                                       "try casting to a reference instead:",
                                                       format!("&{}{}", mtstr, s));
                    },
                    Err(_) =>
                        span_help!(fcx.tcx().sess, t_span,
                                   "did you mean `&{}{}`?", mtstr, tstr),
                }
1091 1092 1093 1094
            } else {
                span_help!(fcx.tcx().sess, span,
                           "consider using an implicit coercion to `&{}{}` instead",
                           mtstr, tstr);
1095 1096
            }
        }
1097
        ty::TyBox(..) => {
1098 1099 1100 1101 1102 1103 1104 1105 1106
            match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                Ok(s) => {
                    fcx.tcx().sess.span_suggestion(t_span,
                                                   "try casting to a `Box` instead:",
                                                   format!("Box<{}>", s));
                },
                Err(_) =>
                    span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
            }
1107 1108 1109 1110 1111
        }
        _ => {
            span_help!(fcx.tcx().sess, e_span,
                       "consider using a box or reference as appropriate");
        }
1112
    }
1113 1114
    fcx.write_error(id);
}
1115 1116


1117
impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
N
Niko Matsakis 已提交
1118
    fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
B
Brian Anderson 已提交
1119

N
Niko Matsakis 已提交
1120
    fn get_item_type_scheme(&self, _: Span, id: DefId)
1121 1122
                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
    {
1123
        Ok(self.tcx().lookup_item_type(id))
B
Brian Anderson 已提交
1124 1125
    }

N
Niko Matsakis 已提交
1126
    fn get_trait_def(&self, _: Span, id: DefId)
1127
                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
1128
    {
1129
        Ok(self.tcx().lookup_trait_def(id))
1130 1131
    }

N
Niko Matsakis 已提交
1132
    fn ensure_super_predicates(&self, _: Span, _: DefId) -> Result<(), ErrorReported> {
1133 1134 1135 1136
        // all super predicates are ensured during collect pass
        Ok(())
    }

1137
    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1138
        Some(&self.inh.infcx.parameter_environment.free_substs)
1139 1140
    }

1141
    fn get_type_parameter_bounds(&self,
1142 1143 1144
                                 _: Span,
                                 node_id: ast::NodeId)
                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1145
    {
1146
        let def = self.tcx().type_parameter_def(node_id);
1147 1148
        let r = self.inh.infcx.parameter_environment
                                  .caller_bounds
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
                                  .iter()
                                  .filter_map(|predicate| {
                                      match *predicate {
                                          ty::Predicate::Trait(ref data) => {
                                              if data.0.self_ty().is_param(def.space, def.index) {
                                                  Some(data.to_poly_trait_ref())
                                              } else {
                                                  None
                                              }
                                          }
                                          _ => {
                                              None
                                          }
1162
                                      }
1163 1164 1165
                                  })
                                  .collect();
        Ok(r)
1166 1167
    }

1168
    fn trait_defines_associated_type_named(&self,
N
Niko Matsakis 已提交
1169
                                           trait_def_id: DefId,
1170 1171 1172
                                           assoc_name: ast::Name)
                                           -> bool
    {
1173
        let trait_def = self.ccx.tcx.lookup_trait_def(trait_def_id);
1174 1175 1176
        trait_def.associated_type_names.contains(&assoc_name)
    }

J
Jared Roesch 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185
    fn ty_infer(&self,
                ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
                substs: Option<&mut subst::Substs<'tcx>>,
                space: Option<subst::ParamSpace>,
                span: Span) -> Ty<'tcx> {
        // Grab the default doing subsitution
        let default = ty_param_def.and_then(|def| {
            def.default.map(|ty| type_variable::Default {
                ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
J
Jared Roesch 已提交
1186
                origin_span: span,
J
Jared Roesch 已提交
1187
                def_id: def.default_def_id
J
Jared Roesch 已提交
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
            })
        });

        let ty_var = self.infcx().next_ty_var_with_default(default);

        // Finally we add the type variable to the substs
        match substs {
            None => ty_var,
            Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
        }
B
Brian Anderson 已提交
1198
    }
1199

1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
    fn projected_ty_from_poly_trait_ref(&self,
                                        span: Span,
                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
                                        item_name: ast::Name)
                                        -> Ty<'tcx>
    {
        let (trait_ref, _) =
            self.infcx().replace_late_bound_regions_with_fresh_var(
                span,
                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
                &poly_trait_ref);

        self.normalize_associated_type(span, trait_ref, item_name)
1213 1214
    }

1215 1216
    fn projected_ty(&self,
                    span: Span,
1217
                    trait_ref: ty::TraitRef<'tcx>,
1218 1219 1220 1221
                    item_name: ast::Name)
                    -> Ty<'tcx>
    {
        self.normalize_associated_type(span, trait_ref, item_name)
1222
    }
B
Brian Anderson 已提交
1223 1224
}

1225
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
N
Niko Matsakis 已提交
1226
    fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1227

1228
    pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
E
Eduard Burtescu 已提交
1229
        &self.inh.infcx
1230
    }
1231

1232
    pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1233
        &self.inh.infcx.parameter_environment
1234 1235
    }

1236 1237 1238 1239
    pub fn sess(&self) -> &Session {
        &self.tcx().sess
    }

1240
    pub fn err_count_since_creation(&self) -> usize {
1241 1242
        self.ccx.tcx.sess.err_count() - self.err_count_on_creation
    }
1243

1244 1245 1246 1247
    /// Resolves type variables in `ty` if possible. Unlike the infcx
    /// version, this version will also select obligations if it seems
    /// useful, in an effort to get more type information.
    fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1248
        debug!("resolve_type_vars_if_possible(ty={:?})", ty);
1249

1250 1251
        // No TyInfer()? Nothing needs doing.
        if !ty.has_infer_types() {
1252
            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1253 1254 1255 1256 1257
            return ty;
        }

        // If `ty` is a type variable, see whether we already know what it is.
        ty = self.infcx().resolve_type_vars_if_possible(&ty);
1258
        if !ty.has_infer_types() {
1259
            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1260 1261 1262 1263
            return ty;
        }

        // If not, try resolving any new fcx obligations that have cropped up.
N
Nick Cameron 已提交
1264
        self.select_new_obligations();
1265
        ty = self.infcx().resolve_type_vars_if_possible(&ty);
1266
        if !ty.has_infer_types() {
1267
            debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1268 1269 1270 1271 1272 1273 1274
            return ty;
        }

        // If not, try resolving *all* pending obligations as much as
        // possible. This can help substantially when there are
        // indirect dependencies that don't seem worth tracking
        // precisely.
N
Nick Cameron 已提交
1275
        self.select_obligations_where_possible();
1276 1277
        ty = self.infcx().resolve_type_vars_if_possible(&ty);

1278
        debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1279
        ty
1280 1281
    }

1282
    fn record_deferred_call_resolution(&self,
N
Niko Matsakis 已提交
1283
                                       closure_def_id: DefId,
1284 1285
                                       r: DeferredCallResolutionHandler<'tcx>) {
        let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1286
        deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1287 1288 1289
    }

    fn remove_deferred_call_resolutions(&self,
N
Niko Matsakis 已提交
1290
                                        closure_def_id: DefId)
1291 1292 1293 1294
                                        -> Vec<DeferredCallResolutionHandler<'tcx>>
    {
        let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
        deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1295 1296
    }

1297
    pub fn tag(&self) -> String {
N
Nick Cameron 已提交
1298 1299
        let self_ptr: *const FnCtxt = self;
        format!("{:?}", self_ptr)
1300
    }
B
Brian Anderson 已提交
1301

1302
    pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1303
        match self.inh.locals.borrow().get(&nid) {
1304
            Some(&t) => t,
1305
            None => {
1306 1307 1308
                span_err!(self.tcx().sess, span, E0513,
                          "no type for local variable {}",
                          nid);
1309
                self.tcx().types.err
1310 1311 1312 1313
            }
        }
    }

1314
    #[inline]
1315
    pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1316 1317
        debug!("write_ty({}, {:?}) in fcx {}",
               node_id, ty, self.tag());
1318
        self.inh.tables.borrow_mut().node_types.insert(node_id, ty);
B
Brian Anderson 已提交
1319 1320
    }

1321
    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1322
        if !substs.substs.is_noop() {
1323
            debug!("write_substs({}, {:?}) in fcx {}",
B
Brian Anderson 已提交
1324
                   node_id,
1325
                   substs,
B
Brian Anderson 已提交
1326
                   self.tag());
1327

1328
            self.inh.tables.borrow_mut().item_substs.insert(node_id, substs);
B
Brian Anderson 已提交
1329 1330 1331
        }
    }

1332
    pub fn write_autoderef_adjustment(&self,
1333
                                      node_id: ast::NodeId,
1334
                                      derefs: usize) {
1335 1336
        self.write_adjustment(
            node_id,
1337
            adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
1338
                autoderefs: derefs,
1339 1340 1341
                autoref: None,
                unsize: None
            })
1342
        );
B
Brian Anderson 已提交
1343 1344
    }

1345
    pub fn write_adjustment(&self,
1346
                            node_id: ast::NodeId,
1347
                            adj: adjustment::AutoAdjustment<'tcx>) {
1348
        debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
1349

1350 1351 1352 1353
        if adj.is_identity() {
            return;
        }

1354
        self.inh.tables.borrow_mut().adjustments.insert(node_id, adj);
B
Brian Anderson 已提交
1355 1356
    }

1357 1358 1359 1360 1361 1362 1363 1364
    /// Basically whenever we are converting from a type scheme into
    /// the fn body space, we always want to normalize associated
    /// types as well. This function combines the two.
    fn instantiate_type_scheme<T>(&self,
                                  span: Span,
                                  substs: &Substs<'tcx>,
                                  value: &T)
                                  -> T
1365
        where T : TypeFoldable<'tcx> + HasTypeFlags
1366 1367 1368
    {
        let value = value.subst(self.tcx(), substs);
        let result = self.normalize_associated_types_in(span, &value);
1369 1370 1371 1372
        debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
               value,
               substs,
               result);
1373 1374 1375
        result
    }

1376 1377 1378 1379 1380
    /// As `instantiate_type_scheme`, but for the bounds found in a
    /// generic type scheme.
    fn instantiate_bounds(&self,
                          span: Span,
                          substs: &Substs<'tcx>,
1381 1382
                          bounds: &ty::GenericPredicates<'tcx>)
                          -> ty::InstantiatedPredicates<'tcx>
1383
    {
1384 1385
        ty::InstantiatedPredicates {
            predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1386 1387 1388 1389
        }
    }


1390
    fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1391
        where T : TypeFoldable<'tcx> + HasTypeFlags
1392
    {
J
Jared Roesch 已提交
1393
        self.inh.normalize_associated_types_in(span, self.body_id, value)
1394 1395 1396 1397
    }

    fn normalize_associated_type(&self,
                                 span: Span,
1398
                                 trait_ref: ty::TraitRef<'tcx>,
1399 1400 1401 1402 1403 1404
                                 item_name: ast::Name)
                                 -> Ty<'tcx>
    {
        let cause = traits::ObligationCause::new(span,
                                                 self.body_id,
                                                 traits::ObligationCauseCode::MiscObligation);
1405 1406 1407
        self.inh
            .infcx
            .fulfillment_cx
1408
            .borrow_mut()
N
Niko Matsakis 已提交
1409 1410 1411 1412 1413
            .normalize_projection_type(self.infcx(),
                                       ty::ProjectionTy {
                                           trait_ref: trait_ref,
                                           item_name: item_name,
                                       },
1414 1415 1416
                                       cause)
    }

1417 1418
    /// Instantiates the type in `did` with the generics in `path` and returns
    /// it (registering the necessary trait obligations along the way).
S
Steve Klabnik 已提交
1419
    ///
1420 1421
    /// Note that this function is only intended to be used with type-paths,
    /// not with value-paths.
1422
    pub fn instantiate_type(&self,
N
Niko Matsakis 已提交
1423
                            did: DefId,
1424
                            path: &hir::Path)
1425
                            -> Ty<'tcx>
1426
    {
1427
        debug!("instantiate_type(did={:?}, path={:?})", did, path);
1428
        let type_scheme =
1429
            self.tcx().lookup_item_type(did);
1430
        let type_predicates =
1431 1432 1433 1434 1435 1436 1437
            self.tcx().lookup_predicates(did);
        let substs = astconv::ast_path_substs_for_ty(self, self,
                                                     path.span,
                                                     PathParamMode::Optional,
                                                     &type_scheme.generics,
                                                     path.segments.last().unwrap());
        debug!("instantiate_type: ty={:?} substs={:?}", &type_scheme.ty, &substs);
1438
        let bounds =
1439
            self.instantiate_bounds(path.span, &substs, &type_predicates);
1440 1441
        self.add_obligations_for_parameters(
            traits::ObligationCause::new(
1442
                path.span,
N
Niko Matsakis 已提交
1443
                self.body_id,
1444
                traits::ItemObligation(did)),
1445
            &bounds);
1446

1447
        self.instantiate_type_scheme(path.span, &substs, &type_scheme.ty)
1448 1449
    }

1450
    /// Return the dict-like variant corresponding to a given `Def`.
1451
    pub fn def_struct_variant(&self,
1452 1453
                              def: def::Def,
                              span: Span)
1454
                              -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
1455
    {
1456
        let (adt, variant) = match def {
1457 1458
            def::DefVariant(enum_id, variant_id, true) => {
                let adt = self.tcx().lookup_adt_def(enum_id);
1459
                (adt, adt.variant_with_id(variant_id))
1460 1461 1462 1463
            }
            def::DefTy(did, _) | def::DefStruct(did) => {
                let typ = self.tcx().lookup_item_type(did);
                if let ty::TyStruct(adt, _) = typ.ty.sty {
1464
                    (adt, adt.struct_variant())
1465
                } else {
1466
                    return None;
1467 1468
                }
            }
1469 1470
            _ => return None
        };
1471

1472
        let var_kind = variant.kind();
1473
        if var_kind == ty::VariantKind::Struct {
1474
            Some((adt, variant))
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
        } else if var_kind == ty::VariantKind::Unit {
            if !self.tcx().sess.features.borrow().braced_empty_structs {
                self.tcx().sess.span_err(span, "empty structs and enum variants \
                                                with braces are unstable");
                fileline_help!(self.tcx().sess, span, "add #![feature(braced_empty_structs)] to \
                                                       the crate features to enable");
            }

             Some((adt, variant))
         } else {
             None
         }
1487 1488
    }

1489
    pub fn write_nil(&self, node_id: ast::NodeId) {
1490
        self.write_ty(node_id, self.tcx().mk_nil());
B
Brian Anderson 已提交
1491
    }
P
Patrick Walton 已提交
1492
    pub fn write_error(&self, node_id: ast::NodeId) {
1493
        self.write_ty(node_id, self.tcx().types.err);
T
Tim Chevalier 已提交
1494
    }
B
Brian Anderson 已提交
1495

1496
    pub fn require_type_meets(&self,
1497
                              ty: Ty<'tcx>,
1498
                              span: Span,
1499
                              code: traits::ObligationCauseCode<'tcx>,
1500 1501
                              bound: ty::BuiltinBound)
    {
1502
        self.register_builtin_bound(
1503
            ty,
1504 1505
            bound,
            traits::ObligationCause::new(span, self.body_id, code));
1506 1507 1508
    }

    pub fn require_type_is_sized(&self,
1509
                                 ty: Ty<'tcx>,
1510
                                 span: Span,
1511
                                 code: traits::ObligationCauseCode<'tcx>)
1512 1513 1514 1515 1516
    {
        self.require_type_meets(ty, span, code, ty::BoundSized);
    }

    pub fn require_expr_have_sized_type(&self,
1517
                                        expr: &hir::Expr,
1518
                                        code: traits::ObligationCauseCode<'tcx>)
1519 1520 1521 1522
    {
        self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
    }

1523
    pub fn type_is_known_to_be_sized(&self,
1524 1525
                                     ty: Ty<'tcx>,
                                     span: Span)
1526 1527 1528 1529
                                     -> bool
    {
        traits::type_known_to_meet_builtin_bound(self.infcx(),
                                                 ty,
1530 1531
                                                 ty::BoundSized,
                                                 span)
1532 1533
    }

1534 1535 1536 1537 1538
    pub fn register_builtin_bound(&self,
                                  ty: Ty<'tcx>,
                                  builtin_bound: ty::BuiltinBound,
                                  cause: traits::ObligationCause<'tcx>)
    {
1539
        self.inh.infcx.fulfillment_cx.borrow_mut()
1540
            .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1541 1542 1543 1544
    }

    pub fn register_predicate(&self,
                              obligation: traits::PredicateObligation<'tcx>)
1545
    {
1546 1547
        debug!("register_predicate({:?})",
               obligation);
1548
        self.inh.infcx.fulfillment_cx
1549
            .borrow_mut()
1550
            .register_predicate_obligation(self.infcx(), obligation);
1551 1552
    }

1553
    pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
N
Niko Matsakis 已提交
1554
        let t = ast_ty_to_ty(self, self, ast_t);
1555
        self.register_wf_obligation(t, ast_t.span, traits::MiscObligation);
1556
        t
B
Brian Anderson 已提交
1557 1558
    }

1559
    pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
1560
        match self.inh.tables.borrow().node_types.get(&ex.id) {
1561
            Some(&t) => t,
B
Brian Anderson 已提交
1562
            None => {
J
Jorge Aparicio 已提交
1563
                self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1564
                                            self.tag()));
B
Brian Anderson 已提交
1565 1566 1567
            }
        }
    }
1568

S
Steve Klabnik 已提交
1569
    /// Apply `adjustment` to the type of `expr`
1570
    pub fn adjust_expr_ty(&self,
1571
                          expr: &hir::Expr,
1572
                          adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
1573
                          -> Ty<'tcx>
1574 1575 1576
    {
        let raw_ty = self.expr_ty(expr);
        let raw_ty = self.infcx().shallow_resolve(raw_ty);
1577
        let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1578
        raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| {
1579
            self.inh.tables.borrow().method_map.get(&method_call)
1580 1581
                                        .map(|method| resolve_ty(method.ty))
        })
1582 1583
    }

1584
    pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1585
        match self.inh.tables.borrow().node_types.get(&id) {
1586
            Some(&t) => t,
1587
            None if self.err_count_since_creation() != 0 => self.tcx().types.err,
B
Brian Anderson 已提交
1588 1589
            None => {
                self.tcx().sess.bug(
J
Jorge Aparicio 已提交
1590
                    &format!("no type for node {}: {} in fcx {}",
1591
                            id, self.tcx().map.node_to_string(id),
1592
                            self.tag()));
B
Brian Anderson 已提交
1593 1594 1595
            }
        }
    }
1596

N
Niko Matsakis 已提交
1597
    pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
J
Jared Roesch 已提交
1598 1599 1600 1601
        // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if
        // it changes when we upgrade the snapshot compiler
        fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
                                        -> &'a NodeMap<ty::ItemSubsts<'tcx>> {
1602 1603 1604 1605
            &tables.item_substs
        }

        Ref::map(self.inh.tables.borrow(), project_item_susbts)
J
Jakub Bukaj 已提交
1606 1607
    }

1608 1609 1610 1611 1612
    pub fn opt_node_ty_substs<F>(&self,
                                 id: ast::NodeId,
                                 f: F) where
        F: FnOnce(&ty::ItemSubsts<'tcx>),
    {
1613
        match self.inh.tables.borrow().item_substs.get(&id) {
1614 1615
            Some(s) => { f(s) }
            None => { }
1616 1617
        }
    }
B
Brian Anderson 已提交
1618

1619 1620
    pub fn mk_subty(&self,
                    a_is_expected: bool,
1621
                    origin: infer::TypeOrigin,
1622 1623
                    sub: Ty<'tcx>,
                    sup: Ty<'tcx>)
1624
                    -> Result<(), TypeError<'tcx>> {
1625
        infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
B
Brian Anderson 已提交
1626 1627
    }

1628 1629
    pub fn mk_eqty(&self,
                   a_is_expected: bool,
1630
                   origin: infer::TypeOrigin,
1631 1632
                   sub: Ty<'tcx>,
                   sup: Ty<'tcx>)
1633
                   -> Result<(), TypeError<'tcx>> {
1634
        infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
B
Brian Anderson 已提交
1635 1636
    }

1637
    pub fn mk_subr(&self,
1638
                   origin: infer::SubregionOrigin<'tcx>,
1639
                   sub: ty::Region,
1640
                   sup: ty::Region) {
1641
        infer::mk_subr(self.infcx(), origin, sub, sup)
B
Brian Anderson 已提交
1642 1643
    }

J
Jorge Aparicio 已提交
1644 1645 1646 1647
    pub fn type_error_message<M>(&self,
                                 sp: Span,
                                 mk_msg: M,
                                 actual_ty: Ty<'tcx>,
1648
                                 err: Option<&TypeError<'tcx>>) where
J
Jorge Aparicio 已提交
1649 1650
        M: FnOnce(String) -> String,
    {
B
Brian Anderson 已提交
1651 1652 1653
        self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
    }

1654
    pub fn report_mismatched_types(&self,
1655
                                   sp: Span,
1656 1657
                                   e: Ty<'tcx>,
                                   a: Ty<'tcx>,
1658
                                   err: &TypeError<'tcx>) {
1659
        self.infcx().report_mismatched_types(sp, e, a, err)
1660
    }
1661

S
Steve Klabnik 已提交
1662 1663
    /// Registers an obligation for checking later, during regionck, that the type `ty` must
    /// outlive the region `r`.
1664
    pub fn register_region_obligation(&self,
1665
                                      ty: Ty<'tcx>,
1666 1667
                                      region: ty::Region,
                                      cause: traits::ObligationCause<'tcx>)
1668
    {
1669
        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1670
        fulfillment_cx.register_region_obligation(ty, region, cause);
1671 1672
    }

1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
    /// Registers an obligation for checking later, during regionck, that the type `ty` must
    /// outlive the region `r`.
    pub fn register_wf_obligation(&self,
                                  ty: Ty<'tcx>,
                                  span: Span,
                                  code: traits::ObligationCauseCode<'tcx>)
    {
        // WF obligations never themselves fail, so no real need to give a detailed cause:
        let cause = traits::ObligationCause::new(span, self.body_id, code);
        self.register_predicate(traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
    }

    pub fn register_old_wf_obligation(&self,
                                      ty: Ty<'tcx>,
                                      span: Span,
                                      code: traits::ObligationCauseCode<'tcx>)
    {
        // Registers an "old-style" WF obligation that uses the
        // implicator code.  This is basically a buggy version of
        // `register_wf_obligation` that is being kept around
        // temporarily just to help with phasing in the newer rules.
        //
        // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
        let cause = traits::ObligationCause::new(span, self.body_id, code);
        self.register_region_obligation(ty, ty::ReEmpty, cause);
    }

    /// Registers obligations that all types appearing in `substs` are well-formed.
1701
    pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
1702
    {
1703
        for &ty in &substs.types {
1704
            self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
1705 1706 1707
        }
    }

S
Steve Klabnik 已提交
1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
    /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
    /// type/region parameter was instantiated (`substs`), creates and registers suitable
    /// trait/region obligations.
    ///
    /// For example, if there is a function:
    ///
    /// ```
    /// fn foo<'a,T:'a>(...)
    /// ```
    ///
    /// and a reference:
    ///
    /// ```
    /// let f = foo;
    /// ```
    ///
    /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
    /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1726
    pub fn add_obligations_for_parameters(&self,
1727
                                          cause: traits::ObligationCause<'tcx>,
1728
                                          predicates: &ty::InstantiatedPredicates<'tcx>)
1729
    {
1730
        assert!(!predicates.has_escaping_regions());
1731

1732 1733
        debug!("add_obligations_for_parameters(predicates={:?})",
               predicates);
1734

1735
        for obligation in traits::predicates_for_generics(cause, predicates) {
1736 1737
            self.register_predicate(obligation);
        }
1738
    }
1739

1740 1741 1742
    // FIXME(arielb1): use this instead of field.ty everywhere
    pub fn field_ty(&self,
                    span: Span,
A
Ariel Ben-Yehuda 已提交
1743
                    field: ty::FieldDef<'tcx>,
1744 1745
                    substs: &Substs<'tcx>)
                    -> Ty<'tcx>
1746
    {
1747 1748
        self.normalize_associated_types_in(span,
                                           &field.ty(self.tcx(), substs))
1749
    }
N
Nick Cameron 已提交
1750

1751 1752
    // Only for fields! Returns <none> for methods>
    // Indifferent to privacy flags
N
Nick Cameron 已提交
1753 1754
    fn check_casts(&self) {
        let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1755 1756
        for cast in deferred_cast_checks.drain(..) {
            cast.check(self);
N
Nick Cameron 已提交
1757 1758
        }
    }
N
Nick Cameron 已提交
1759

J
Jared Roesch 已提交
1760 1761
    /// Apply "fallbacks" to some types
    /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
J
Jared Roesch 已提交
1762
    fn default_type_parameters(&self) {
1763 1764
        use middle::ty::error::UnconstrainedNumeric::Neither;
        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
J
Jared Roesch 已提交
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
        for ty in &self.infcx().unsolved_variables() {
            let resolved = self.infcx().resolve_type_vars_if_possible(ty);
            if self.infcx().type_var_diverges(resolved) {
                demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
            } else {
                match self.infcx().type_is_unconstrained_numeric(resolved) {
                    UnconstrainedInt => {
                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
                    },
                    UnconstrainedFloat => {
                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
                    }
                    Neither => { }
                }
            }
        }
    }

N
Nick Cameron 已提交
1783
    fn select_all_obligations_and_apply_defaults(&self) {
J
Jared Roesch 已提交
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
        if self.tcx().sess.features.borrow().default_type_parameter_fallback {
            self.new_select_all_obligations_and_apply_defaults();
        } else {
            self.old_select_all_obligations_and_apply_defaults();
        }
    }

    // Implements old type inference fallback algorithm
    fn old_select_all_obligations_and_apply_defaults(&self) {
        self.select_obligations_where_possible();
        self.default_type_parameters();
        self.select_obligations_where_possible();
    }

    fn new_select_all_obligations_and_apply_defaults(&self) {
1799 1800
        use middle::ty::error::UnconstrainedNumeric::Neither;
        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
N
Nick Cameron 已提交
1801

1802
        // For the time being this errs on the side of being memory wasteful but provides better
1803 1804
        // error reporting.
        // let type_variables = self.infcx().type_variables.clone();
1805

1806 1807
        // There is a possibility that this algorithm will have to run an arbitrary number of times
        // to terminate so we bound it by the compiler's recursion limit.
1808
        for _ in 0..self.tcx().sess.recursion_limit.get() {
1809 1810
            // First we try to solve all obligations, it is possible that the last iteration
            // has made it possible to make more progress.
1811 1812
            self.select_obligations_where_possible();

1813 1814 1815
            let mut conflicts = Vec::new();

            // Collect all unsolved type, integral and floating point variables.
1816
            let unsolved_variables = self.inh.infcx.unsolved_variables();
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826

            // We must collect the defaults *before* we do any unification. Because we have
            // directly attached defaults to the type variables any unification that occurs
            // will erase defaults causing conflicting defaults to be completely ignored.
            let default_map: FnvHashMap<_, _> =
                unsolved_variables
                    .iter()
                    .filter_map(|t| self.infcx().default(t).map(|d| (t, d)))
                    .collect();

1827 1828
            let mut unbound_tyvars = HashSet::new();

1829 1830 1831 1832 1833 1834
            debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);

            // We loop over the unsolved variables, resolving them and if they are
            // and unconstrainted numberic type we add them to the set of unbound
            // variables. We do this so we only apply literal fallback to type
            // variables without defaults.
1835 1836 1837 1838 1839 1840
            for ty in &unsolved_variables {
                let resolved = self.infcx().resolve_type_vars_if_possible(ty);
                if self.infcx().type_var_diverges(resolved) {
                    demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
                } else {
                    match self.infcx().type_is_unconstrained_numeric(resolved) {
1841
                        UnconstrainedInt | UnconstrainedFloat => {
1842 1843 1844 1845 1846 1847 1848
                            unbound_tyvars.insert(resolved);
                        },
                        Neither => {}
                    }
                }
            }

1849 1850
            // We now remove any numeric types that also have defaults, and instead insert
            // the type variable with a defined fallback.
1851
            for ty in &unsolved_variables {
1852
                if let Some(_default) = default_map.get(ty) {
1853 1854
                    let resolved = self.infcx().resolve_type_vars_if_possible(ty);

1855 1856
                    debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
                             ty, _default);
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874

                    match resolved.sty {
                        ty::TyInfer(ty::TyVar(_)) => {
                            unbound_tyvars.insert(ty);
                        }

                        ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
                            unbound_tyvars.insert(ty);
                            if unbound_tyvars.contains(resolved) {
                                unbound_tyvars.remove(resolved);
                            }
                        }

                        _ => {}
                    }
                }
            }

1875
            // If there are no more fallbacks to apply at this point we have applied all possible
1876
            // defaults and type inference will proceed as normal.
1877 1878 1879 1880
            if unbound_tyvars.is_empty() {
                break;
            }

1881 1882 1883 1884 1885 1886
            // Finally we go through each of the unbound type variables and unify them with
            // the proper fallback, reporting a conflicting default error if any of the
            // unifications fail. We know it must be a conflicting default because the
            // variable would only be in `unbound_tyvars` and have a concrete value if
            // it had been solved by previously applying a default.

J
Jared Roesch 已提交
1887 1888 1889
            // We wrap this in a transaction for error reporting, if we detect a conflict
            // we will rollback the inference context to its prior state so we can probe
            // for conflicts and correctly report them.
1890 1891


J
Jared Roesch 已提交
1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
            let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
                for ty in &unbound_tyvars {
                    if self.infcx().type_var_diverges(ty) {
                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
                    } else {
                        match self.infcx().type_is_unconstrained_numeric(ty) {
                            UnconstrainedInt => {
                                demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
                            },
                            UnconstrainedFloat => {
                                demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
                            }
                            Neither => {
                                if let Some(default) = default_map.get(ty) {
                                    let default = default.clone();
                                    match infer::mk_eqty(self.infcx(), false,
                                                         infer::Misc(default.origin_span),
                                                         ty, default.ty) {
                                        Ok(()) => {}
                                        Err(_) => {
                                            conflicts.push((*ty, default));
                                        }
1914 1915 1916 1917 1918 1919 1920
                                    }
                                }
                            }
                        }
                    }
                }

J
Jared Roesch 已提交
1921 1922 1923 1924 1925 1926 1927
                // If there are conflicts we rollback, otherwise commit
                if conflicts.len() > 0 {
                    Err(())
                } else {
                    Ok(())
                }
            });
1928

J
Jared Roesch 已提交
1929 1930 1931
            if conflicts.len() > 0 {
                // Loop through each conflicting default, figuring out the default that caused
                // a unification failure and then report an error for each.
1932 1933
                for (conflict, default) in conflicts {
                    let conflicting_default =
J
Jared Roesch 已提交
1934 1935
                        self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
                            .unwrap_or(type_variable::Default {
1936 1937
                                ty: self.infcx().next_ty_var(),
                                origin_span: codemap::DUMMY_SP,
1938
                                def_id: self.tcx().map.local_def_id(0) // what do I put here?
1939 1940
                            });

1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951
                    // This is to ensure that we elimnate any non-determinism from the error
                    // reporting by fixing an order, it doesn't matter what order we choose
                    // just that it is consistent.
                    let (first_default, second_default) =
                        if default.def_id < conflicting_default.def_id {
                            (default, conflicting_default)
                        } else {
                            (conflicting_default, default)
                        };


J
Jared Roesch 已提交
1952
                    self.infcx().report_conflicting_default_types(
1953 1954 1955
                        first_default.origin_span,
                        first_default,
                        second_default)
1956 1957
                }
            }
1958
        }
1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971

        self.select_obligations_where_possible();
    }

    // For use in error handling related to default type parameter fallback. We explicitly
    // apply the default that caused conflict first to a local version of the type variable
    // table then apply defaults until we find a conflict. That default must be the one
    // that caused conflict earlier.
    fn find_conflicting_default(&self,
                                unbound_vars: &HashSet<Ty<'tcx>>,
                                default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
                                conflict: Ty<'tcx>)
                                -> Option<type_variable::Default<'tcx>> {
1972 1973
        use middle::ty::error::UnconstrainedNumeric::Neither;
        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
1974

J
Jared Roesch 已提交
1975
        // Ensure that we apply the conflicting default first
1976 1977 1978 1979 1980 1981 1982
        let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
        unbound_tyvars.push(conflict);
        unbound_tyvars.extend(unbound_vars.iter());

        let mut result = None;
        // We run the same code as above applying defaults in order, this time when
        // we find the conflict we just return it for error reporting above.
J
Jared Roesch 已提交
1983 1984 1985

        // We also run this inside snapshot that never commits so we can do error
        // reporting for more then one conflict.
J
Jared Roesch 已提交
1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
        for ty in &unbound_tyvars {
            if self.infcx().type_var_diverges(ty) {
                demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
            } else {
                match self.infcx().type_is_unconstrained_numeric(ty) {
                    UnconstrainedInt => {
                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
                    },
                    UnconstrainedFloat => {
                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
                    },
                    Neither => {
                        if let Some(default) = default_map.get(ty) {
                            let default = default.clone();
                            match infer::mk_eqty(self.infcx(), false,
                                                 infer::Misc(default.origin_span),
                                                 ty, default.ty) {
                                Ok(()) => {}
                                Err(_) => {
                                    result = Some(default);
2006 2007 2008 2009 2010 2011
                                }
                            }
                        }
                    }
                }
            }
J
Jared Roesch 已提交
2012
        }
2013 2014

        return result;
N
Nick Cameron 已提交
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
    }

    fn select_all_obligations_or_error(&self) {
        debug!("select_all_obligations_or_error");

        // upvar inference should have ensured that all deferred call
        // resolutions are handled by now.
        assert!(self.inh.deferred_call_resolutions.borrow().is_empty());

        self.select_all_obligations_and_apply_defaults();
J
Jared Roesch 已提交
2025

2026
        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
J
Jared Roesch 已提交
2027
        match fulfillment_cx.select_all_or_error(self.infcx()) {
N
Nick Cameron 已提交
2028 2029 2030 2031 2032 2033 2034 2035
            Ok(()) => { }
            Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
        }
    }

    /// Select as many obligations as we can at present.
    fn select_obligations_where_possible(&self) {
        match
2036
            self.inh.infcx.fulfillment_cx
N
Nick Cameron 已提交
2037
            .borrow_mut()
J
Jared Roesch 已提交
2038
            .select_where_possible(self.infcx())
N
Nick Cameron 已提交
2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
        {
            Ok(()) => { }
            Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
        }
    }

    /// Try to select any fcx obligation that we haven't tried yet, in an effort
    /// to improve inference. You could just call
    /// `select_obligations_where_possible` except that it leads to repeated
    /// work.
    fn select_new_obligations(&self) {
        match
2051
            self.inh.infcx.fulfillment_cx
N
Nick Cameron 已提交
2052
            .borrow_mut()
J
Jared Roesch 已提交
2053
            .select_new_obligations(self.infcx())
N
Nick Cameron 已提交
2054 2055 2056 2057 2058 2059
        {
            Ok(()) => { }
            Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
        }
    }

B
Brian Anderson 已提交
2060 2061
}

N
Niko Matsakis 已提交
2062
impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
2063
    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
2064 2065 2066 2067
        Some(self.base_object_lifetime_default(span))
    }

    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
2068 2069 2070 2071 2072 2073 2074
        // RFC #599 specifies that object lifetime defaults take
        // precedence over other defaults. But within a fn body we
        // don't have a *default* region, rather we use inference to
        // find the *correct* region, which is strictly more general
        // (and anyway, within a fn body the right region may not even
        // be something the user can write explicitly, since it might
        // be some expression).
2075
        self.infcx().next_region_var(infer::MiscVariable(span))
N
Niko Matsakis 已提交
2076 2077
    }

2078
    fn anon_regions(&self, span: Span, count: usize)
2079
                    -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
2080
        Ok((0..count).map(|_| {
N
Niko Matsakis 已提交
2081
            self.infcx().next_region_var(infer::MiscVariable(span))
A
Aaron Turon 已提交
2082
        }).collect())
N
Niko Matsakis 已提交
2083 2084
    }
}
2085

2086
/// Whether `autoderef` requires types to resolve.
N
Niko Matsakis 已提交
2087
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2088
pub enum UnresolvedTypeAction {
2089 2090
    /// Produce an error and return `TyError` whenever a type cannot
    /// be resolved (i.e. it is `TyInfer`).
2091 2092 2093 2094 2095 2096
    Error,
    /// Go on without emitting any errors, and return the unresolved
    /// type. Useful for probing, e.g. in coercions.
    Ignore
}

S
Steve Klabnik 已提交
2097 2098 2099 2100 2101
/// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
/// whether to terminate the loop. Returns the final type and number of derefs that it performed.
///
/// Note: this method does not modify the adjustments table. The caller is responsible for
/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
2102 2103
pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
                                 sp: Span,
2104
                                 base_ty: Ty<'tcx>,
2105
                                 opt_expr: Option<&hir::Expr>,
2106
                                 unresolved_type_action: UnresolvedTypeAction,
2107 2108
                                 mut lvalue_pref: LvaluePreference,
                                 mut should_stop: F)
2109 2110
                                 -> (Ty<'tcx>, usize, Option<T>)
    where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
2111
{
2112 2113 2114
    debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
           base_ty,
           opt_expr,
2115 2116
           lvalue_pref);

2117
    let mut t = base_ty;
2118
    for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
2119 2120
        let resolved_t = match unresolved_type_action {
            UnresolvedTypeAction::Error => {
N
Nick Cameron 已提交
2121
                structurally_resolved_type(fcx, sp, t)
2122 2123 2124
            }
            UnresolvedTypeAction::Ignore => {
                // We can continue even when the type cannot be resolved
2125
                // (i.e. it is an inference variable) because `Ty::builtin_deref`
2126 2127 2128 2129 2130
                // and `try_overloaded_deref` both simply return `None`
                // in such a case without producing spurious errors.
                fcx.resolve_type_vars_if_possible(t)
            }
        };
2131
        if resolved_t.references_error() {
N
Nick Cameron 已提交
2132 2133
            return (resolved_t, autoderefs, None);
        }
2134

2135 2136 2137 2138 2139
        match should_stop(resolved_t, autoderefs) {
            Some(x) => return (resolved_t, autoderefs, Some(x)),
            None => {}
        }

B
Brian Anderson 已提交
2140
        // Otherwise, deref if type is derefable:
2141
        let mt = match resolved_t.builtin_deref(false, lvalue_pref) {
2142
            Some(mt) => Some(mt),
B
Brian Anderson 已提交
2143
            None => {
2144 2145
                let method_call =
                    opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157

                // Super subtle: it might seem as though we should
                // pass `opt_expr` to `try_overloaded_deref`, so that
                // the (implicit) autoref of using an overloaded deref
                // would get added to the adjustment table. However we
                // do not do that, because it's kind of a
                // "meta-adjustment" -- instead, we just leave it
                // unrecorded and know that there "will be" an
                // autoref. regionck and other bits of the code base,
                // when they encounter an overloaded autoderef, have
                // to do some reconstructive surgery. This is a pretty
                // complex mess that is begging for a proper MIR.
2158
                try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
B
Brian Anderson 已提交
2159
            }
2160 2161
        };
        match mt {
B
Brian Anderson 已提交
2162
            Some(mt) => {
2163
                t = mt.ty;
2164
                if mt.mutbl == hir::MutImmutable {
2165 2166
                    lvalue_pref = NoPreference;
                }
B
Brian Anderson 已提交
2167
            }
2168
            None => return (resolved_t, autoderefs, None)
B
Brian Anderson 已提交
2169
        }
2170
    }
2171 2172

    // We've reached the recursion limit, error gracefully.
2173
    span_err!(fcx.tcx().sess, sp, E0055,
2174 2175
        "reached the recursion limit while auto-dereferencing {:?}",
        base_ty);
2176
    (fcx.tcx().types.err, 0, None)
B
Brian Anderson 已提交
2177 2178
}

2179 2180 2181
fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  span: Span,
                                  method_call: Option<MethodCall>,
2182
                                  base_expr: Option<&hir::Expr>,
2183 2184
                                  base_ty: Ty<'tcx>,
                                  lvalue_pref: LvaluePreference)
2185
                                  -> Option<ty::TypeAndMut<'tcx>>
2186
{
2187 2188 2189
    // Try DerefMut first, if preferred.
    let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
        (PreferMutLvalue, Some(trait_did)) => {
2190
            method::lookup_in_trait(fcx, span, base_expr,
2191
                                    token::intern("deref_mut"), trait_did,
2192
                                    base_ty, None)
2193 2194 2195 2196 2197 2198 2199
        }
        _ => None
    };

    // Otherwise, fall back to Deref.
    let method = match (method, fcx.tcx().lang_items.deref_trait()) {
        (None, Some(trait_did)) => {
2200
            method::lookup_in_trait(fcx, span, base_expr,
2201
                                    token::intern("deref"), trait_did,
2202
                                    base_ty, None)
2203 2204 2205 2206
        }
        (method, _) => method
    };

2207
    make_overloaded_lvalue_return_type(fcx, method_call, method)
N
Nick Cameron 已提交
2208 2209
}

S
Steve Klabnik 已提交
2210 2211 2212
/// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
/// actual type we assign to the *expression* is `T`. So this function just peels off the return
/// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2213 2214 2215
fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                method_call: Option<MethodCall>,
                                                method: Option<MethodCallee<'tcx>>)
2216
                                                -> Option<ty::TypeAndMut<'tcx>>
2217
{
2218 2219
    match method {
        Some(method) => {
2220
            // extract method return type, which will be &T;
2221
            // all LB regions should have been instantiated during method lookup
2222
            let ret_ty = method.ty.fn_ret();
2223
            let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
2224 2225

            if let Some(method_call) = method_call {
2226
                fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
J
Jakub Bukaj 已提交
2227
            }
2228 2229

            // method returns &T, but the type as visible to user is T, so deref
2230
            ret_ty.builtin_deref(true, NoPreference)
2231
        }
N
Nick Cameron 已提交
2232 2233 2234 2235
        None => None,
    }
}

2236
fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2237 2238
                             expr: &hir::Expr,
                             base_expr: &'tcx hir::Expr,
2239 2240 2241 2242
                             base_ty: Ty<'tcx>,
                             idx_ty: Ty<'tcx>,
                             lvalue_pref: LvaluePreference)
                             -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2243
{
2244 2245 2246 2247
    // FIXME(#18741) -- this is almost but not quite the same as the
    // autoderef that normal method probing does. They could likely be
    // consolidated.

2248 2249 2250 2251 2252 2253 2254
    let (ty, autoderefs, final_mt) = autoderef(fcx,
                                               base_expr.span,
                                               base_ty,
                                               Some(base_expr),
                                               UnresolvedTypeAction::Error,
                                               lvalue_pref,
                                               |adj_ty, idx| {
2255 2256 2257
        try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
                       adj_ty, idx, false, lvalue_pref, idx_ty)
    });
2258 2259 2260 2261 2262

    if final_mt.is_some() {
        return final_mt;
    }

2263
    // After we have fully autoderef'd, if the resulting type is [T; n], then
2264
    // do a final unsized coercion to yield [T].
2265
    if let ty::TyArray(element_ty, _) = ty.sty {
2266
        let adjusted_ty = fcx.tcx().mk_slice(element_ty);
2267 2268 2269 2270
        try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
                       adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
    } else {
        None
2271 2272 2273
    }
}

S
Steve Klabnik 已提交
2274 2275 2276
/// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
/// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
/// This loop implements one step in that search; the autoderef loop is implemented by
2277
/// `lookup_indexing`.
2278 2279
fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            method_call: MethodCall,
2280 2281
                            expr: &hir::Expr,
                            base_expr: &'tcx hir::Expr,
2282
                            adjusted_ty: Ty<'tcx>,
2283 2284
                            autoderefs: usize,
                            unsize: bool,
2285 2286
                            lvalue_pref: LvaluePreference,
                            index_ty: Ty<'tcx>)
2287
                            -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2288
{
2289
    let tcx = fcx.tcx();
2290 2291 2292 2293 2294
    debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
                           autoderefs={}, unsize={}, index_ty={:?})",
           expr,
           base_expr,
           adjusted_ty,
2295 2296
           autoderefs,
           unsize,
2297
           index_ty);
2298 2299 2300

    let input_ty = fcx.infcx().next_ty_var();

2301
    // First, try built-in indexing.
2302
    match (adjusted_ty.builtin_index(), &index_ty.sty) {
2303
        (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
2304
            debug!("try_index_step: success, using built-in indexing");
2305 2306 2307
            // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
            assert!(!unsize);
            fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
2308
            return Some((tcx.types.usize, ty));
2309 2310 2311 2312
        }
        _ => {}
    }

2313
    // Try `IndexMut` first, if preferred.
2314
    let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2315
        (PreferMutLvalue, Some(trait_did)) => {
2316 2317 2318 2319 2320
            method::lookup_in_trait_adjusted(fcx,
                                             expr.span,
                                             Some(&*base_expr),
                                             token::intern("index_mut"),
                                             trait_did,
2321 2322
                                             autoderefs,
                                             unsize,
2323
                                             adjusted_ty,
2324
                                             Some(vec![input_ty]))
2325 2326 2327 2328 2329
        }
        _ => None,
    };

    // Otherwise, fall back to `Index`.
2330
    let method = match (method, tcx.lang_items.index_trait()) {
2331
        (None, Some(trait_did)) => {
2332 2333 2334 2335 2336
            method::lookup_in_trait_adjusted(fcx,
                                             expr.span,
                                             Some(&*base_expr),
                                             token::intern("index"),
                                             trait_did,
2337 2338
                                             autoderefs,
                                             unsize,
2339
                                             adjusted_ty,
2340
                                             Some(vec![input_ty]))
2341 2342 2343 2344
        }
        (method, _) => method,
    };

2345 2346 2347
    // If some lookup succeeds, write callee into table and extract index/element
    // type from the method signature.
    // If some lookup succeeded, install method in table
2348
    method.and_then(|method| {
2349
        debug!("try_index_step: success, using overloaded indexing");
2350 2351
        make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
            map(|ret| (input_ty, ret.ty))
2352
    })
2353 2354
}

2355 2356 2357
fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                         sp: Span,
                                         method_fn_ty: Ty<'tcx>,
2358 2359
                                         callee_expr: &'tcx hir::Expr,
                                         args_no_rcvr: &'tcx [P<hir::Expr>],
2360 2361
                                         tuple_arguments: TupleArgumentsFlag,
                                         expected: Expectation<'tcx>)
2362
                                         -> ty::FnOutput<'tcx> {
2363
    if method_fn_ty.references_error() {
2364
        let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2365 2366 2367

        let err_inputs = match tuple_arguments {
            DontTupleArguments => err_inputs,
2368
            TupleArguments => vec![fcx.tcx().mk_tup(err_inputs)],
2369 2370
        };

2371 2372
        check_argument_types(fcx,
                             sp,
2373
                             &err_inputs[..],
2374
                             &[],
2375
                             args_no_rcvr,
2376 2377
                             false,
                             tuple_arguments);
2378
        ty::FnConverging(fcx.tcx().types.err)
2379
    } else {
2380
        match method_fn_ty.sty {
2381
            ty::TyBareFn(_, ref fty) => {
2382
                // HACK(eddyb) ignore self in the definition (see above).
2383 2384 2385 2386 2387
                let expected_arg_tys = expected_types_for_fn_args(fcx,
                                                                  sp,
                                                                  expected,
                                                                  fty.sig.0.output,
                                                                  &fty.sig.0.inputs[1..]);
2388 2389
                check_argument_types(fcx,
                                     sp,
2390
                                     &fty.sig.0.inputs[1..],
2391
                                     &expected_arg_tys[..],
2392
                                     args_no_rcvr,
2393
                                     fty.sig.0.variadic,
2394
                                     tuple_arguments);
2395
                fty.sig.0.output
2396 2397 2398 2399 2400 2401 2402 2403 2404
            }
            _ => {
                fcx.tcx().sess.span_bug(callee_expr.span,
                                        "method without bare fn type");
            }
        }
    }
}

S
Steve Klabnik 已提交
2405 2406
/// Generic function that factors out common logic from function calls, method calls and overloaded
/// operators.
2407 2408 2409
fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  sp: Span,
                                  fn_inputs: &[Ty<'tcx>],
2410
                                  expected_arg_tys: &[Ty<'tcx>],
2411
                                  args: &'tcx [P<hir::Expr>],
2412 2413
                                  variadic: bool,
                                  tuple_arguments: TupleArgumentsFlag) {
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
    let tcx = fcx.ccx.tcx;

    // Grab the argument types, supplying fresh type variables
    // if the wrong number of arguments were supplied
    let supplied_arg_count = if tuple_arguments == DontTupleArguments {
        args.len()
    } else {
        1
    };

2424 2425 2426 2427 2428 2429
    // All the input types from the fn signature must outlive the call
    // so as to validate implied bounds.
    for &fn_input_ty in fn_inputs {
        fcx.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
    }

2430
    let mut expected_arg_tys = expected_arg_tys;
2431 2432 2433
    let expected_arg_count = fn_inputs.len();
    let formal_tys = if tuple_arguments == TupleArguments {
        let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2434
        match tuple_type.sty {
2435
            ty::TyTuple(ref arg_types) => {
2436
                if arg_types.len() != args.len() {
2437 2438 2439 2440 2441 2442
                    span_err!(tcx.sess, sp, E0057,
                        "this function takes {} parameter{} but {} parameter{} supplied",
                        arg_types.len(),
                        if arg_types.len() == 1 {""} else {"s"},
                        args.len(),
                        if args.len() == 1 {" was"} else {"s were"});
2443
                    expected_arg_tys = &[];
2444
                    err_args(fcx.tcx(), args.len())
2445
                } else {
2446 2447
                    expected_arg_tys = match expected_arg_tys.get(0) {
                        Some(&ty) => match ty.sty {
2448
                            ty::TyTuple(ref tys) => &**tys,
2449 2450 2451 2452
                            _ => &[]
                        },
                        None => &[]
                    };
2453 2454 2455 2456
                    (*arg_types).clone()
                }
            }
            _ => {
2457 2458 2459
                span_err!(tcx.sess, sp, E0059,
                    "cannot use call notation; the first type parameter \
                     for the function trait is neither a tuple nor unit");
2460
                expected_arg_tys = &[];
2461
                err_args(fcx.tcx(), args.len())
2462 2463 2464
            }
        }
    } else if expected_arg_count == supplied_arg_count {
2465
        fn_inputs.to_vec()
2466 2467
    } else if variadic {
        if supplied_arg_count >= expected_arg_count {
2468
            fn_inputs.to_vec()
2469
        } else {
2470
            span_err!(tcx.sess, sp, E0060,
2471 2472
                "this function takes at least {} parameter{} \
                 but {} parameter{} supplied",
2473 2474 2475 2476
                expected_arg_count,
                if expected_arg_count == 1 {""} else {"s"},
                supplied_arg_count,
                if supplied_arg_count == 1 {" was"} else {"s were"});
2477
            expected_arg_tys = &[];
2478
            err_args(fcx.tcx(), supplied_arg_count)
2479 2480
        }
    } else {
2481 2482 2483 2484 2485 2486
        span_err!(tcx.sess, sp, E0061,
            "this function takes {} parameter{} but {} parameter{} supplied",
            expected_arg_count,
            if expected_arg_count == 1 {""} else {"s"},
            supplied_arg_count,
            if supplied_arg_count == 1 {" was"} else {"s were"});
2487
        expected_arg_tys = &[];
2488
        err_args(fcx.tcx(), supplied_arg_count)
2489 2490
    };

2491
    debug!("check_argument_types: formal_tys={:?}",
2492
           formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2493 2494 2495 2496 2497 2498 2499 2500

    // Check the arguments.
    // We do this in a pretty awful way: first we typecheck any arguments
    // that are not anonymous functions, then we typecheck the anonymous
    // functions. This is so that we have more information about the types
    // of arguments when we typecheck the functions. This isn't really the
    // right way to do this.
    let xs = [false, true];
2501
    for check_blocks in &xs {
2502 2503 2504
        let check_blocks = *check_blocks;
        debug!("check_blocks={}", check_blocks);

2505 2506 2507
        // More awful hacks: before we check argument types, try to do
        // an "opportunistic" vtable resolution of any trait bounds on
        // the call. This helps coercions.
2508
        if check_blocks {
N
Nick Cameron 已提交
2509
            fcx.select_new_obligations();
2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523
        }

        // For variadic functions, we don't have a declared type for all of
        // the arguments hence we only do our usual type checking with
        // the arguments who's types we do know.
        let t = if variadic {
            expected_arg_count
        } else if tuple_arguments == TupleArguments {
            args.len()
        } else {
            supplied_arg_count
        };
        for (i, arg) in args.iter().take(t).enumerate() {
            let is_block = match arg.node {
2524
                hir::ExprClosure(..) => true,
2525 2526 2527 2528 2529
                _ => false
            };

            if is_block == check_blocks {
                debug!("checking the argument");
2530
                let formal_ty = formal_tys[i];
2531

2532 2533 2534
                // The special-cased logic below has three functions:
                // 1. Provide as good of an expected type as possible.
                let expected = expected_arg_tys.get(i).map(|&ty| {
2535
                    Expectation::rvalue_hint(fcx.tcx(), ty)
2536 2537
                });

2538 2539
                check_expr_with_unifier(fcx,
                                        &**arg,
2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
                                        expected.unwrap_or(ExpectHasType(formal_ty)),
                                        NoPreference, || {
                    // 2. Coerce to the most detailed type that could be coerced
                    //    to, which is `expected_ty` if `rvalue_hint` returns an
                    //    `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
                    let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
                    demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);

                    // 3. Relate the expected type and the formal one,
                    //    if the expected type was used for the coercion.
                    coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
                });
2552 2553 2554 2555 2556 2557 2558 2559
            }
        }
    }

    // We also need to make sure we at least write the ty of the other
    // arguments which we skipped above.
    if variadic {
        for arg in args.iter().skip(expected_arg_count) {
2560
            check_expr(fcx, &**arg);
2561 2562 2563

            // There are a few types which get autopromoted when passed via varargs
            // in C but we just error out instead and require explicit casts.
2564
            let arg_ty = structurally_resolved_type(fcx, arg.span,
2565
                                                    fcx.expr_ty(&**arg));
2566
            match arg_ty.sty {
2567
                ty::TyFloat(ast::TyF32) => {
2568 2569 2570 2571 2572 2573
                    fcx.type_error_message(arg.span,
                                           |t| {
                        format!("can't pass an {} to variadic \
                                 function, cast to c_double", t)
                    }, arg_ty, None);
                }
2574
                ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
2575 2576 2577 2578 2579 2580
                    fcx.type_error_message(arg.span, |t| {
                        format!("can't pass {} to variadic \
                                 function, cast to c_int",
                                       t)
                    }, arg_ty, None);
                }
2581
                ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
                    fcx.type_error_message(arg.span, |t| {
                        format!("can't pass {} to variadic \
                                 function, cast to c_uint",
                                       t)
                    }, arg_ty, None);
                }
                _ => {}
            }
        }
    }
}

2594
// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2595
fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2596
    (0..len).map(|_| tcx.types.err).collect()
2597 2598
}

2599
fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2600
                        call_expr: &hir::Expr,
2601
                        output: ty::FnOutput<'tcx>) {
J
Jakub Bukaj 已提交
2602 2603 2604 2605
    fcx.write_ty(call_expr.id, match output {
        ty::FnConverging(output_ty) => output_ty,
        ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
    });
2606 2607
}

B
Brian Anderson 已提交
2608
// AST fragment checking
2609
fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2610
                       lit: &ast::Lit,
2611 2612
                       expected: Expectation<'tcx>)
                       -> Ty<'tcx>
2613
{
B
Brian Anderson 已提交
2614 2615 2616
    let tcx = fcx.ccx.tcx;

    match lit.node {
2617 2618
        ast::LitStr(..) => tcx.mk_static_str(),
        ast::LitByteStr(ref v) => {
2619 2620
            tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
                            tcx.mk_array(tcx.types.u8, v.len()))
2621
        }
2622 2623 2624 2625 2626
        ast::LitByte(_) => tcx.types.u8,
        ast::LitChar(_) => tcx.types.char,
        ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
        ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
        ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2627
            let opt_ty = expected.to_option(fcx).and_then(|ty| {
2628
                match ty.sty {
2629 2630 2631 2632
                    ty::TyInt(_) | ty::TyUint(_) => Some(ty),
                    ty::TyChar => Some(tcx.types.u8),
                    ty::TyRawPtr(..) => Some(tcx.types.usize),
                    ty::TyBareFn(..) => Some(tcx.types.usize),
2633 2634 2635 2636
                    _ => None
                }
            });
            opt_ty.unwrap_or_else(
2637
                || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
2638
        }
2639 2640
        ast::LitFloat(_, t) => tcx.mk_mach_float(t),
        ast::LitFloatUnsuffixed(_) => {
2641
            let opt_ty = expected.to_option(fcx).and_then(|ty| {
2642
                match ty.sty {
2643
                    ty::TyFloat(_) => Some(ty),
2644 2645 2646 2647
                    _ => None
                }
            });
            opt_ty.unwrap_or_else(
2648
                || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
2649
        }
2650
        ast::LitBool(_) => tcx.types.bool
B
Brian Anderson 已提交
2651 2652 2653
    }
}

2654
pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2655
                                     expr: &'tcx hir::Expr,
2656
                                     expected: Ty<'tcx>) {
2657 2658 2659
    check_expr_with_unifier(
        fcx, expr, ExpectHasType(expected), NoPreference,
        || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
B
Brian Anderson 已提交
2660 2661
}

2662
fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2663
                                          expr: &'tcx hir::Expr,
2664
                                          expected: Ty<'tcx>) {
2665 2666 2667
    check_expr_with_unifier(
        fcx, expr, ExpectHasType(expected), NoPreference,
        || demand::coerce(fcx, expr.span, expected, expr));
B
Brian Anderson 已提交
2668 2669
}

2670
fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx hir::Expr,
2671
                                  expected: Ty<'tcx>) {
2672 2673 2674
    check_expr_with_unifier(
        fcx, expr, ExpectHasType(expected), NoPreference,
        || ())
2675
}
B
Brian Anderson 已提交
2676

2677
fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2678
                                         expr: &'tcx hir::Expr,
2679
                                         expected: Expectation<'tcx>) {
2680 2681 2682
    check_expr_with_unifier(
        fcx, expr, expected, NoPreference,
        || ())
2683 2684
}

2685
fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2686
                                                         expr: &'tcx hir::Expr,
2687 2688
                                                         expected: Expectation<'tcx>,
                                                         lvalue_pref: LvaluePreference)
2689
{
2690
    check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2691 2692
}

2693
fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx hir::Expr)  {
2694
    check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
B
Brian Anderson 已提交
2695 2696
}

2697
fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx hir::Expr,
2698
                                        lvalue_pref: LvaluePreference)  {
2699
    check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2700 2701
}

B
Brian Anderson 已提交
2702
// determine the `self` type, using fresh variables for all variables
2703
// declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
B
Brian Anderson 已提交
2704 2705
// would return ($0, $1) where $0 and $1 are freshly instantiated type
// variables.
2706 2707
pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              span: Span, // (potential) receiver for this impl
N
Niko Matsakis 已提交
2708
                              did: DefId)
2709
                              -> TypeAndSubsts<'tcx> {
2710
    let tcx = fcx.tcx();
B
Brian Anderson 已提交
2711

2712
    let ity = tcx.lookup_item_type(did);
2713 2714
    let (tps, rps, raw_ty) =
        (ity.generics.types.get_slice(subst::TypeSpace),
2715
         ity.generics.regions.get_slice(subst::TypeSpace),
2716
         ity.ty);
B
Brian Anderson 已提交
2717

2718 2719
    debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);

2720
    let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2721 2722 2723 2724
    let mut substs = subst::Substs::new(
        VecPerParamSpace::empty(),
        VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
    fcx.inh.infcx.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
2725
    let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2726

2727
    TypeAndSubsts { substs: substs, ty: substd_ty }
B
Brian Anderson 已提交
2728 2729
}

2730 2731 2732 2733 2734 2735 2736
/// Controls whether the arguments are tupled. This is used for the call
/// operator.
///
/// Tupling means that all call-side arguments are packed into a tuple and
/// passed as a single parameter. For example, if tupling is enabled, this
/// function:
///
2737
///     fn f(x: (isize, isize))
2738 2739 2740 2741 2742 2743 2744 2745
///
/// Can be called as:
///
///     f(1, 2);
///
/// Instead of:
///
///     f((1, 2));
2746
#[derive(Clone, Eq, PartialEq)]
2747 2748 2749 2750 2751
enum TupleArgumentsFlag {
    DontTupleArguments,
    TupleArguments,
}

2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
/// Unifies the return type with the expected type early, for more coercions
/// and forward type information on the argument expressions.
fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                        call_span: Span,
                                        expected_ret: Expectation<'tcx>,
                                        formal_ret: ty::FnOutput<'tcx>,
                                        formal_args: &[Ty<'tcx>])
                                        -> Vec<Ty<'tcx>> {
    let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
        if let ty::FnConverging(formal_ret_ty) = formal_ret {
            fcx.infcx().commit_regions_if_ok(|| {
                // Attempt to apply a subtyping relationship between the formal
                // return type (likely containing type variables if the function
                // is polymorphic) and the expected return type.
                // No argument expectations are produced if unification fails.
                let origin = infer::Misc(call_span);
                let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
                // FIXME(#15760) can't use try! here, FromError doesn't default
                // to identity so the resulting type is not constrained.
                if let Err(e) = ures {
                    return Err(e);
                }

                // Record all the argument types, with the substitutions
                // produced from the above subtyping unification.
                Ok(formal_args.iter().map(|ty| {
                    fcx.infcx().resolve_type_vars_if_possible(ty)
                }).collect())
            }).ok()
        } else {
            None
        }
    }).unwrap_or(vec![]);
2785 2786 2787
    debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
           formal_args, formal_ret,
           expected_args, expected_ret);
2788 2789 2790
    expected_args
}

2791 2792
/// Invariant:
/// If an expression has any sub-expressions that result in a type error,
2793
/// inspecting that expression's type with `ty.references_error()` will return
2794 2795 2796 2797 2798
/// true. Likewise, if an expression is known to diverge, inspecting its
/// type with `ty::type_is_bot` will return true (n.b.: since Rust is
/// strict, _|_ can appear in the type of an expression that does not,
/// itself, diverge: for example, fn() -> _|_.)
/// Note that inspecting a type's structure *directly* may expose the fact
2799
/// that there are actually multiple representations for `TyError`, so avoid
J
Jakub Bukaj 已提交
2800
/// that when err needs to be handled differently.
2801
fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2802
                                        expr: &'tcx hir::Expr,
2803 2804 2805 2806
                                        expected: Expectation<'tcx>,
                                        lvalue_pref: LvaluePreference,
                                        unifier: F) where
    F: FnOnce(),
2807
{
2808 2809
    debug!(">> typechecking: expr={:?} expected={:?}",
           expr, expected);
B
Brian Anderson 已提交
2810

2811
    // Checks a method call.
2812
    fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2813
                                   expr: &'tcx hir::Expr,
2814
                                   method_name: Spanned<ast::Name>,
2815 2816
                                   args: &'tcx [P<hir::Expr>],
                                   tps: &[P<hir::Ty>],
2817 2818
                                   expected: Expectation<'tcx>,
                                   lvalue_pref: LvaluePreference) {
2819
        let rcvr = &*args[0];
2820
        check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2821

T
Tim Chevalier 已提交
2822
        // no need to check for bot/err -- callee does that
2823 2824
        let expr_t = structurally_resolved_type(fcx,
                                                expr.span,
2825
                                                fcx.expr_ty(&*rcvr));
2826

2827
        let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2828
        let fn_ty = match method::lookup(fcx,
2829
                                         method_name.span,
2830
                                         method_name.node,
2831
                                         expr_t,
2832
                                         tps,
2833
                                         expr,
2834
                                         rcvr) {
2835
            Ok(method) => {
2836
                let method_ty = method.ty;
2837
                let method_call = MethodCall::expr(expr.id);
2838
                fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2839
                method_ty
2840
            }
2841
            Err(error) => {
2842
                method::report_error(fcx, method_name.span, expr_t,
2843
                                     method_name.node, Some(rcvr), error);
T
Tim Chevalier 已提交
2844
                fcx.write_error(expr.id);
2845
                fcx.tcx().types.err
2846
            }
2847
        };
2848

2849
        // Call the generic checker.
2850 2851 2852 2853
        let ret_ty = check_method_argument_types(fcx,
                                                 method_name.span,
                                                 fn_ty,
                                                 expr,
2854
                                                 &args[1..],
2855 2856
                                                 DontTupleArguments,
                                                 expected);
2857

2858
        write_call(fcx, expr, ret_ty);
2859 2860
    }

B
Brian Anderson 已提交
2861
    // A generic function for checking the then and else in an if
2862
    // or if-else.
2863
    fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2864 2865 2866
                                 cond_expr: &'tcx hir::Expr,
                                 then_blk: &'tcx hir::Block,
                                 opt_else_expr: Option<&'tcx hir::Expr>,
2867 2868 2869
                                 id: ast::NodeId,
                                 sp: Span,
                                 expected: Expectation<'tcx>) {
2870
        check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2871

2872
        let expected = expected.adjust_for_branches(fcx);
2873 2874 2875
        check_block_with_expected(fcx, then_blk, expected);
        let then_ty = fcx.node_ty(then_blk.id);

2876
        let branches_ty = match opt_else_expr {
2877
            Some(ref else_expr) => {
2878
                check_expr_with_expectation(fcx, &**else_expr, expected);
2879
                let else_ty = fcx.expr_ty(&**else_expr);
2880 2881 2882 2883 2884 2885 2886
                infer::common_supertype(fcx.infcx(),
                                        infer::IfExpression(sp),
                                        true,
                                        then_ty,
                                        else_ty)
            }
            None => {
2887 2888 2889 2890
                infer::common_supertype(fcx.infcx(),
                                        infer::IfExpressionWithNoElse(sp),
                                        false,
                                        then_ty,
2891
                                        fcx.tcx().mk_nil())
2892 2893
            }
        };
T
Tim Chevalier 已提交
2894

2895
        let cond_ty = fcx.expr_ty(cond_expr);
2896
        let if_ty = if cond_ty.references_error() {
2897
            fcx.tcx().types.err
2898 2899 2900 2901 2902
        } else {
            branches_ty
        };

        fcx.write_ty(id, if_ty);
B
Brian Anderson 已提交
2903 2904 2905
    }

    // Check field access expressions
2906
    fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2907
                            expr: &'tcx hir::Expr,
2908
                            lvalue_pref: LvaluePreference,
2909
                            base: &'tcx hir::Expr,
2910
                            field: &Spanned<ast::Name>) {
B
Brian Anderson 已提交
2911
        let tcx = fcx.ccx.tcx;
2912
        check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
B
Brian Anderson 已提交
2913 2914
        let expr_t = structurally_resolved_type(fcx, expr.span,
                                                fcx.expr_ty(base));
2915
        // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2916 2917 2918 2919 2920 2921 2922
        let (_, autoderefs, field_ty) = autoderef(fcx,
                                                  expr.span,
                                                  expr_t,
                                                  Some(base),
                                                  UnresolvedTypeAction::Error,
                                                  lvalue_pref,
                                                  |base_t, _| {
2923
                match base_t.sty {
2924
                    ty::TyStruct(base_def, substs) => {
2925
                        debug!("struct named {:?}",  base_t);
2926
                        base_def.struct_variant()
2927
                                .find_field_named(field.node)
2928
                                .map(|f| fcx.field_ty(expr.span, f, substs))
2929 2930
                    }
                    _ => None
B
Brian Anderson 已提交
2931
                }
2932
            });
2933 2934 2935
        match field_ty {
            Some(field_ty) => {
                fcx.write_ty(expr.id, field_ty);
2936
                fcx.write_autoderef_adjustment(base.id, autoderefs);
2937 2938 2939
                return;
            }
            None => {}
B
Brian Anderson 已提交
2940 2941
        }

2942
        if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
2943 2944 2945 2946
            fcx.type_error_message(
                field.span,
                |actual| {
                    format!("attempted to take value of method `{}` on type \
2947
                            `{}`", field.node, actual)
2948 2949
                },
                expr_t, None);
2950

2951
            tcx.sess.fileline_help(field.span,
2952 2953 2954 2955 2956 2957 2958 2959 2960
                               "maybe a `()` to call it is missing? \
                               If not, try an anonymous function");
        } else {
            fcx.type_error_message(
                expr.span,
                |actual| {
                    format!("attempted access of field `{}` on \
                            type `{}`, but no field with that \
                            name was found",
2961
                            field.node,
2962 2963 2964
                            actual)
                },
                expr_t, None);
2965
            if let ty::TyStruct(def, _) = expr_t.sty {
2966
                suggest_field_names(def.struct_variant(), field, tcx, vec![]);
2967
            }
B
Brian Anderson 已提交
2968 2969
        }

2970
        fcx.write_error(expr.id);
B
Brian Anderson 已提交
2971 2972
    }

2973
    // displays hints about the closest matches in field names
A
Ariel Ben-Yehuda 已提交
2974
    fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
2975
                                 field: &Spanned<ast::Name>,
2976
                                 tcx: &ty::ctxt<'tcx>,
2977
                                 skip : Vec<InternedString>) {
2978
        let name = field.node.as_str();
2979 2980
        // only find fits with at least one matching letter
        let mut best_dist = name.len();
2981
        let mut best = None;
2982
        for elem in &variant.fields {
2983 2984
            let n = elem.name.as_str();
            // ignore already set fields
2985
            if skip.iter().any(|x| *x == n) {
2986 2987
                continue;
            }
2988
            // ignore private fields from non-local crates
N
Niko Matsakis 已提交
2989
            if variant.did.krate != LOCAL_CRATE && elem.vis != Visibility::Public {
2990 2991
                continue;
            }
2992
            let dist = lev_distance(&n, &name);
2993 2994 2995 2996 2997 2998 2999
            if dist < best_dist {
                best = Some(n);
                best_dist = dist;
            }
        }
        if let Some(n) = best {
            tcx.sess.span_help(field.span,
3000
                &format!("did you mean `{}`?", n));
3001 3002 3003
        }
    }

3004
    // Check tuple index expressions
3005
    fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3006
                                expr: &'tcx hir::Expr,
3007
                                lvalue_pref: LvaluePreference,
3008
                                base: &'tcx hir::Expr,
3009
                                idx: codemap::Spanned<usize>) {
3010 3011 3012 3013 3014
        check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
        let expr_t = structurally_resolved_type(fcx, expr.span,
                                                fcx.expr_ty(base));
        let mut tuple_like = false;
        // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3015 3016 3017 3018 3019 3020 3021
        let (_, autoderefs, field_ty) = autoderef(fcx,
                                                  expr.span,
                                                  expr_t,
                                                  Some(base),
                                                  UnresolvedTypeAction::Error,
                                                  lvalue_pref,
                                                  |base_t, _| {
3022
                match base_t.sty {
3023
                    ty::TyStruct(base_def, substs) => {
3024
                        tuple_like = base_def.struct_variant().is_tuple_struct();
3025
                        if tuple_like {
3026
                            debug!("tuple struct named {:?}",  base_t);
3027 3028 3029 3030
                            base_def.struct_variant()
                                    .fields
                                    .get(idx.node)
                                    .map(|f| fcx.field_ty(expr.span, f, substs))
3031 3032 3033 3034
                        } else {
                            None
                        }
                    }
3035
                    ty::TyTuple(ref v) => {
3036 3037 3038 3039 3040 3041 3042 3043 3044
                        tuple_like = true;
                        if idx.node < v.len() { Some(v[idx.node]) } else { None }
                    }
                    _ => None
                }
            });
        match field_ty {
            Some(field_ty) => {
                fcx.write_ty(expr.id, field_ty);
3045
                fcx.write_autoderef_adjustment(base.id, autoderefs);
3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
                return;
            }
            None => {}
        }
        fcx.type_error_message(
            expr.span,
            |actual| {
                if tuple_like {
                    format!("attempted out-of-bounds tuple index `{}` on \
                                    type `{}`",
                                   idx.node,
                                   actual)
                } else {
                    format!("attempted tuple index `{}` on type `{}`, but the \
                                     type was not a tuple or tuple struct",
                                    idx.node,
                                    actual)
                }
            },
            expr_t, None);

        fcx.write_error(expr.id);
    }

3070 3071
    fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      ty: Ty<'tcx>,
A
Ariel Ben-Yehuda 已提交
3072
                                      variant: ty::VariantDef<'tcx>,
3073 3074
                                      field: &hir::Field,
                                      skip_fields: &[hir::Field]) {
3075
        fcx.type_error_message(
3076
            field.name.span,
3077 3078
            |actual| if let ty::TyEnum(..) = ty.sty {
                format!("struct variant `{}::{}` has no field named `{}`",
3079
                        actual, variant.name.as_str(), field.name.node)
3080 3081
            } else {
                format!("structure `{}` has no field named `{}`",
3082
                        actual, field.name.node)
3083 3084 3085 3086
            },
            ty,
            None);
        // prevent all specified fields from being suggested
3087 3088
        let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
        suggest_field_names(variant, &field.name, fcx.tcx(), skip_fields.collect());
3089 3090
    }

3091 3092 3093 3094
    fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          adt_ty: Ty<'tcx>,
                                          span: Span,
                                          variant: ty::VariantDef<'tcx>,
3095
                                          ast_fields: &'tcx [hir::Field],
3096
                                          check_completeness: bool) {
B
Brian Anderson 已提交
3097
        let tcx = fcx.ccx.tcx;
3098 3099 3100
        let substs = match adt_ty.sty {
            ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
            _ => tcx.sess.span_bug(span, "non-ADT passed to check_expr_struct_fields")
3101
        };
B
Brian Anderson 已提交
3102

3103 3104 3105
        let mut remaining_fields = FnvHashMap();
        for field in &variant.fields {
            remaining_fields.insert(field.name, field);
B
Brian Anderson 已提交
3106 3107
        }

T
Tim Chevalier 已提交
3108 3109
        let mut error_happened = false;

B
Brian Anderson 已提交
3110
        // Typecheck each field.
3111
        for field in ast_fields {
3112 3113
            let expected_field_type;

3114
            if let Some(v_field) = remaining_fields.remove(&field.name.node) {
3115 3116 3117 3118
                expected_field_type = fcx.field_ty(field.span, v_field, substs);
            } else {
                error_happened = true;
                expected_field_type = tcx.types.err;
3119 3120
                if let Some(_) = variant.find_field_named(field.name.node) {
                    span_err!(fcx.tcx().sess, field.name.span, E0062,
3121
                        "field `{}` specified more than once",
3122
                        field.name.node);
3123 3124
                } else {
                    report_unknown_field(fcx, adt_ty, variant, field, ast_fields);
B
Brian Anderson 已提交
3125 3126
                }
            }
3127

T
Tim Chevalier 已提交
3128 3129
            // Make sure to give a type to the field even if there's
            // an error, so we can continue typechecking
3130
            check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
T
Tim Chevalier 已提交
3131 3132
        }

B
Brian Anderson 已提交
3133
            // Make sure the programmer specified all the fields.
3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144
        if check_completeness &&
            !error_happened &&
            !remaining_fields.is_empty()
        {
            span_err!(tcx.sess, span, E0063,
                      "missing field{}: {}",
                      if remaining_fields.len() == 1 {""} else {"s"},
                      remaining_fields.keys()
                                      .map(|n| format!("`{}`", n))
                                      .collect::<Vec<_>>()
                                      .join(", "));
B
Brian Anderson 已提交
3145
        }
3146

B
Brian Anderson 已提交
3147 3148
    }

3149 3150
    fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                             id: ast::NodeId,
3151 3152
                                             fields: &'tcx [hir::Field],
                                             base_expr: &'tcx Option<P<hir::Expr>>) {
3153 3154 3155
        // Make sure to still write the types
        // otherwise we might ICE
        fcx.write_error(id);
3156
        for field in fields {
3157 3158
            check_expr(fcx, &*field.expr);
        }
3159
        match *base_expr {
3160 3161 3162 3163 3164
            Some(ref base) => check_expr(fcx, &**base),
            None => {}
        }
    }

3165
    fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
3166 3167 3168 3169
                                   expr: &hir::Expr,
                                   path: &hir::Path,
                                   fields: &'tcx [hir::Field],
                                   base_expr: &'tcx Option<P<hir::Expr>>)
3170
    {
3171 3172 3173 3174
        let tcx = fcx.tcx();

        // Find the relevant variant
        let def = lookup_full_def(tcx, path.span, expr.id);
3175
        let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185
            Some((adt, variant)) => (adt, variant),
            None => {
                span_err!(fcx.tcx().sess, path.span, E0071,
                          "`{}` does not name a structure",
                          pprust::path_to_string(path));
                check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
                return;
            }
        };

3186
        let expr_ty = fcx.instantiate_type(def.def_id(), path);
3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198
        fcx.write_ty(expr.id, expr_ty);

        check_expr_struct_fields(fcx, expr_ty, expr.span, variant, fields,
                                 base_expr.is_none());

        if let &Some(ref base_expr) = base_expr {
            check_expr_has_type(fcx, base_expr, expr_ty);
            if adt.adt_kind() == ty::AdtKind::Enum {
                span_err!(tcx.sess, base_expr.span, E0436,
                          "functional record update syntax requires a struct");
            }
        }
3199 3200
    }

3201
    type ExprCheckerWithTy = fn(&FnCtxt, &hir::Expr, Ty);
3202

B
Brian Anderson 已提交
3203 3204
    let tcx = fcx.ccx.tcx;
    let id = expr.id;
3205
    match expr.node {
3206 3207 3208 3209 3210 3211 3212 3213 3214 3215
      hir::ExprBox(ref subexpr) => {
        let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
            match ty.sty {
                ty::TyBox(ty) => Expectation::rvalue_hint(tcx, ty),
                _ => NoExpectation
            }
        });
        check_expr_with_expectation(fcx, subexpr, expected_inner);
        let referent_ty = fcx.expr_ty(&**subexpr);
        fcx.write_ty(id, tcx.mk_box(referent_ty));
3216 3217
      }

3218
      hir::ExprLit(ref lit) => {
3219
        let typ = check_lit(fcx, &**lit, expected);
B
Brian Anderson 已提交
3220 3221
        fcx.write_ty(id, typ);
      }
3222
      hir::ExprBinary(op, ref lhs, ref rhs) => {
3223
        op::check_binop(fcx, expr, op, lhs, rhs);
B
Brian Anderson 已提交
3224
      }
3225
      hir::ExprAssignOp(op, ref lhs, ref rhs) => {
3226
        op::check_binop_assign(fcx, expr, op, lhs, rhs);
B
Brian Anderson 已提交
3227
      }
3228
      hir::ExprUnary(unop, ref oprnd) => {
3229 3230 3231
        let expected_inner = match unop {
            hir::UnNot | hir::UnNeg => {
                expected
B
Brian Anderson 已提交
3232
            }
3233 3234 3235 3236
            hir::UnDeref => {
                NoExpectation
            }
        };
3237
        let lvalue_pref = match unop {
3238
            hir::UnDeref => lvalue_pref,
3239 3240
            _ => NoPreference
        };
3241 3242
        check_expr_with_expectation_and_lvalue_pref(
            fcx, &**oprnd, expected_inner, lvalue_pref);
3243
        let mut oprnd_t = fcx.expr_ty(&**oprnd);
B
Brian Koropoff 已提交
3244

3245
        if !oprnd_t.references_error() {
T
Tim Chevalier 已提交
3246
            match unop {
3247
                hir::UnDeref => {
3248
                    oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3249
                    oprnd_t = match oprnd_t.builtin_deref(true, NoPreference) {
3250
                        Some(mt) => mt.ty,
3251 3252
                        None => match try_overloaded_deref(fcx, expr.span,
                                                           Some(MethodCall::expr(expr.id)),
3253
                                                           Some(&**oprnd), oprnd_t, lvalue_pref) {
3254 3255
                            Some(mt) => mt.ty,
                            None => {
3256 3257 3258 3259
                                fcx.type_error_message(expr.span, |actual| {
                                    format!("type `{}` cannot be \
                                            dereferenced", actual)
                                }, oprnd_t, None);
3260
                                tcx.types.err
T
Tim Chevalier 已提交
3261 3262
                            }
                        }
3263
                    };
T
Tim Chevalier 已提交
3264
                }
3265
                hir::UnNot => {
J
Jakub Bukaj 已提交
3266 3267
                    oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                         oprnd_t);
3268
                    if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
3269 3270 3271
                        oprnd_t = op::check_user_unop(fcx, "!", "not",
                                                      tcx.lang_items.not_trait(),
                                                      expr, &**oprnd, oprnd_t, unop);
T
Tim Chevalier 已提交
3272 3273
                    }
                }
3274
                hir::UnNeg => {
J
Jakub Bukaj 已提交
3275 3276
                    oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                         oprnd_t);
3277
                    if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
3278 3279 3280
                        oprnd_t = op::check_user_unop(fcx, "-", "neg",
                                                      tcx.lang_items.neg_trait(),
                                                      expr, &**oprnd, oprnd_t, unop);
T
Tim Chevalier 已提交
3281
                    }
B
Brian Anderson 已提交
3282 3283 3284 3285 3286
                }
            }
        }
        fcx.write_ty(id, oprnd_t);
      }
3287
      hir::ExprAddrOf(mutbl, ref oprnd) => {
3288
        let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3289
            match ty.sty {
3290
                ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
3291
                    if fcx.tcx().expr_is_lval(&**oprnd) {
3292 3293 3294 3295 3296
                        // Lvalues may legitimately have unsized types.
                        // For example, dereferences of a fat pointer and
                        // the last field of a struct can be unsized.
                        ExpectHasType(mt.ty)
                    } else {
3297
                        Expectation::rvalue_hint(tcx, mt.ty)
3298 3299
                    }
                }
3300 3301
                _ => NoExpectation
            }
3302
        });
3303
        let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
3304 3305 3306 3307
        check_expr_with_expectation_and_lvalue_pref(fcx,
                                                    &**oprnd,
                                                    hint,
                                                    lvalue_pref);
B
Brian Anderson 已提交
3308

3309
        let tm = ty::TypeAndMut { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3310
        let oprnd_t = if tm.ty.references_error() {
3311
            tcx.types.err
J
Jakub Bukaj 已提交
3312
        } else {
N
Nick Cameron 已提交
3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325
            // Note: at this point, we cannot say what the best lifetime
            // is to use for resulting pointer.  We want to use the
            // shortest lifetime possible so as to avoid spurious borrowck
            // errors.  Moreover, the longest lifetime will depend on the
            // precise details of the value whose address is being taken
            // (and how long it is valid), which we don't know yet until type
            // inference is complete.
            //
            // Therefore, here we simply generate a region variable.  The
            // region inferencer will then select the ultimate value.
            // Finally, borrowck is charged with guaranteeing that the
            // value whose address was taken can actually be made to live
            // as long as it needs to live.
3326
            let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3327
            tcx.mk_ref(tcx.mk_region(region), tm)
T
Tim Chevalier 已提交
3328
        };
B
Brian Anderson 已提交
3329 3330
        fcx.write_ty(id, oprnd_t);
      }
3331
      hir::ExprPath(ref maybe_qself, ref path) => {
3332 3333 3334
          let opt_self_ty = maybe_qself.as_ref().map(|qself| {
              fcx.to_ty(&qself.ty)
          });
3335

3336 3337
          let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
              d
3338
          } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
3339 3340
                // Create some fake resolution that can't possibly be a type.
                def::PathResolution {
3341
                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
3342 3343 3344 3345
                    last_private: LastMod(AllPublic),
                    depth: path.segments.len()
                }
            } else {
3346
              tcx.sess.span_bug(expr.span,
3347
                                &format!("unbound path {:?}", expr))
3348
          };
3349

3350 3351 3352
          if let Some((opt_ty, segments, def)) =
                  resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
                                          expr.span, expr.id) {
3353 3354 3355 3356
              let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
                                                                            expr.span,
                                                                            def);
              instantiate_path(fcx,
3357
                               segments,
3358 3359
                               scheme,
                               &predicates,
3360
                               opt_ty,
3361 3362 3363
                               def,
                               expr.span,
                               id);
3364
          }
3365 3366 3367

          // We always require that the type provided as the value for
          // a type parameter outlives the moment of instantiation.
3368 3369 3370
          fcx.opt_node_ty_substs(expr.id, |item_substs| {
              fcx.add_wf_bounds(&item_substs.substs, expr);
          });
B
Brian Anderson 已提交
3371
      }
3372
      hir::ExprInlineAsm(ref ia) => {
3373
          for &(_, ref input) in &ia.inputs {
3374
              check_expr(fcx, &**input);
3375
          }
3376
          for &(_, ref out, _) in &ia.outputs {
3377
              check_expr(fcx, &**out);
3378
          }
3379 3380
          fcx.write_nil(id);
      }
3381 3382 3383
      hir::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
      hir::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
      hir::ExprRet(ref expr_opt) => {
J
Jakub Bukaj 已提交
3384 3385 3386 3387 3388
        match fcx.ret_ty {
            ty::FnConverging(result_type) => {
                match *expr_opt {
                    None =>
                        if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3389
                                                    result_type, fcx.tcx().mk_nil()) {
J
Jakub Bukaj 已提交
3390
                            span_err!(tcx.sess, expr.span, E0069,
3391 3392
                                "`return;` in a function whose return type is \
                                 not `()`");
J
Jakub Bukaj 已提交
3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404
                        },
                    Some(ref e) => {
                        check_expr_coercable_to_type(fcx, &**e, result_type);
                    }
                }
            }
            ty::FnDiverging => {
                if let Some(ref e) = *expr_opt {
                    check_expr(fcx, &**e);
                }
                span_err!(tcx.sess, expr.span, E0166,
                    "`return` in a function declared as diverging");
B
Brian Anderson 已提交
3405 3406
            }
        }
J
Jakub Bukaj 已提交
3407
        fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
B
Brian Anderson 已提交
3408
      }
3409
      hir::ExprAssign(ref lhs, ref rhs) => {
3410
        check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
K
klutzy 已提交
3411 3412

        let tcx = fcx.tcx();
3413
        if !tcx.expr_is_lval(&**lhs) {
3414
            span_err!(tcx.sess, expr.span, E0070,
3415
                "invalid left-hand side expression");
K
klutzy 已提交
3416 3417
        }

3418
        let lhs_ty = fcx.expr_ty(&**lhs);
3419
        check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3420
        let rhs_ty = fcx.expr_ty(&**rhs);
3421

3422 3423
        fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);

3424
        if lhs_ty.references_error() || rhs_ty.references_error() {
T
Tim Chevalier 已提交
3425
            fcx.write_error(id);
3426
        } else {
T
Tim Chevalier 已提交
3427 3428
            fcx.write_nil(id);
        }
B
Brian Anderson 已提交
3429
      }
3430
      hir::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3431
        check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3432
                        id, expr.span, expected);
B
Brian Anderson 已提交
3433
      }
3434
      hir::ExprWhile(ref cond, ref body, _) => {
3435
        check_expr_has_type(fcx, &**cond, tcx.types.bool);
3436 3437
        check_block_no_value(fcx, &**body);
        let cond_ty = fcx.expr_ty(&**cond);
3438
        let body_ty = fcx.node_ty(body.id);
3439
        if cond_ty.references_error() || body_ty.references_error() {
T
Tim Chevalier 已提交
3440 3441 3442 3443 3444
            fcx.write_error(id);
        }
        else {
            fcx.write_nil(id);
        }
B
Brian Anderson 已提交
3445
      }
3446
      hir::ExprLoop(ref body, _) => {
3447
        check_block_no_value(fcx, &**body);
3448
        if !may_break(tcx, expr.id, &**body) {
J
Jakub Bukaj 已提交
3449
            fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3450
        } else {
T
Tim Chevalier 已提交
3451 3452
            fcx.write_nil(id);
        }
B
Brian Anderson 已提交
3453
      }
3454
      hir::ExprMatch(ref discrim, ref arms, match_src) => {
3455
        _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
B
Brian Anderson 已提交
3456
      }
3457
      hir::ExprClosure(capture, ref decl, ref body) => {
3458
          closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3459
      }
3460
      hir::ExprBlock(ref b) => {
3461
        check_block_with_expected(fcx, &**b, expected);
3462
        fcx.write_ty(id, fcx.node_ty(b.id));
B
Brian Anderson 已提交
3463
      }
3464
      hir::ExprCall(ref callee, ref args) => {
3465
          callee::check_call(fcx, expr, &**callee, &args[..], expected);
3466 3467 3468 3469

          // we must check that return type of called functions is WF:
          let ret_ty = fcx.expr_ty(expr);
          fcx.register_wf_obligation(ret_ty, expr.span, traits::MiscObligation);
B
Brian Anderson 已提交
3470
      }
3471 3472
      hir::ExprMethodCall(name, ref tps, ref args) => {
          check_method_call(fcx, expr, name, &args[..], &tps[..], expected, lvalue_pref);
3473 3474 3475 3476 3477
          let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
          let args_err = arg_tys.fold(false, |rest_err, a| rest_err || a.references_error());
          if args_err {
              fcx.write_error(id);
          }
3478
      }
3479 3480
      hir::ExprCast(ref e, ref t) => {
        if let hir::TyFixedLengthVec(_, ref count_expr) = t.node {
3481
            check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3482
        }
N
Nick Cameron 已提交
3483 3484 3485

        // Find the type of `e`. Supply hints based on the type we are casting to,
        // if appropriate.
A
Ariel Ben-Yehuda 已提交
3486 3487 3488 3489
        let t_cast = fcx.to_ty(t);
        let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
        check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
        let t_expr = fcx.expr_ty(e);
N
Nick Cameron 已提交
3490 3491

        // Eagerly check for some obvious errors.
3492
        if t_expr.references_error() {
N
Nick Cameron 已提交
3493
            fcx.write_error(id);
A
Ariel Ben-Yehuda 已提交
3494 3495
        } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
            report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
N
Nick Cameron 已提交
3496 3497 3498
        } else {
            // Write a type for the whole expression, assuming everything is going
            // to work out Ok.
A
Ariel Ben-Yehuda 已提交
3499
            fcx.write_ty(id, t_cast);
N
Nick Cameron 已提交
3500 3501 3502

            // Defer other checks until we're done type checking.
            let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
A
Ariel Ben-Yehuda 已提交
3503
            let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
3504
            deferred_cast_checks.push(cast_check);
N
Nick Cameron 已提交
3505
        }
B
Brian Anderson 已提交
3506
      }
3507
      hir::ExprVec(ref args) => {
3508
        let uty = expected.to_option(fcx).and_then(|uty| {
3509
            match uty.sty {
3510
                ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3511
                _ => None
N
Nick Cameron 已提交
3512
            }
3513
        });
N
Nick Cameron 已提交
3514 3515 3516

        let typ = match uty {
            Some(uty) => {
3517
                for e in args {
N
Nick Cameron 已提交
3518 3519 3520 3521 3522
                    check_expr_coercable_to_type(fcx, &**e, uty);
                }
                uty
            }
            None => {
3523
                let t: Ty = fcx.infcx().next_ty_var();
3524
                for e in args {
N
Nick Cameron 已提交
3525 3526 3527 3528 3529
                    check_expr_has_type(fcx, &**e, t);
                }
                t
            }
        };
3530
        let typ = tcx.mk_array(typ, args.len());
B
Brian Anderson 已提交
3531 3532
        fcx.write_ty(id, typ);
      }
3533
      hir::ExprRepeat(ref element, ref count_expr) => {
3534
        check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3535
        let count = fcx.tcx().eval_repeat_count(&**count_expr);
N
Nick Cameron 已提交
3536

N
Nick Cameron 已提交
3537 3538
        let uty = match expected {
            ExpectHasType(uty) => {
3539
                match uty.sty {
3540
                    ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3541
                    _ => None
N
Nick Cameron 已提交
3542 3543 3544 3545
                }
            }
            _ => None
        };
N
Nick Cameron 已提交
3546 3547 3548 3549 3550 3551 3552

        let (element_ty, t) = match uty {
            Some(uty) => {
                check_expr_coercable_to_type(fcx, &**element, uty);
                (uty, uty)
            }
            None => {
3553
                let t: Ty = fcx.infcx().next_ty_var();
N
Nick Cameron 已提交
3554 3555 3556 3557 3558
                check_expr_has_type(fcx, &**element, t);
                (fcx.expr_ty(&**element), t)
            }
        };

3559 3560 3561 3562 3563 3564 3565 3566 3567 3568
        if count > 1 {
            // For [foo, ..n] where n > 1, `foo` must have
            // Copy type:
            fcx.require_type_meets(
                t,
                expr.span,
                traits::RepeatVec,
                ty::BoundCopy);
        }

3569
        if element_ty.references_error() {
T
Tim Chevalier 已提交
3570
            fcx.write_error(id);
N
Nick Cameron 已提交
3571
        } else {
3572
            let t = tcx.mk_array(t, count);
T
Tim Chevalier 已提交
3573 3574
            fcx.write_ty(id, t);
        }
B
Brian Anderson 已提交
3575
      }
3576
      hir::ExprTup(ref elts) => {
3577
        let flds = expected.only_has_type(fcx).and_then(|ty| {
3578
            match ty.sty {
3579
                ty::TyTuple(ref flds) => Some(&flds[..]),
3580 3581
                _ => None
            }
B
Brian Anderson 已提交
3582
        });
T
Tim Chevalier 已提交
3583
        let mut err_field = false;
3584

3585
        let elt_ts = elts.iter().enumerate().map(|(i, e)| {
N
Nick Cameron 已提交
3586 3587
            let t = match flds {
                Some(ref fs) if i < fs.len() => {
3588
                    let ety = fs[i];
N
Nick Cameron 已提交
3589 3590 3591 3592
                    check_expr_coercable_to_type(fcx, &**e, ety);
                    ety
                }
                _ => {
N
Nick Cameron 已提交
3593
                    check_expr_with_expectation(fcx, &**e, NoExpectation);
N
Nick Cameron 已提交
3594 3595 3596
                    fcx.expr_ty(&**e)
                }
            };
3597
            err_field = err_field || t.references_error();
T
Tim Chevalier 已提交
3598
            t
3599
        }).collect();
J
Jakub Bukaj 已提交
3600
        if err_field {
T
Tim Chevalier 已提交
3601
            fcx.write_error(id);
3602
        } else {
3603
            let typ = tcx.mk_tup(elt_ts);
T
Tim Chevalier 已提交
3604 3605
            fcx.write_ty(id, typ);
        }
B
Brian Anderson 已提交
3606
      }
3607
      hir::ExprStruct(ref path, ref fields, ref base_expr) => {
3608
        check_expr_struct(fcx, expr, path, fields, base_expr);
3609

3610
        fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
B
Brian Anderson 已提交
3611
      }
3612
      hir::ExprField(ref base, ref field) => {
3613
        check_field(fcx, expr, lvalue_pref, &**base, field);
B
Brian Anderson 已提交
3614
      }
3615
      hir::ExprTupField(ref base, idx) => {
3616
        check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3617
      }
3618
      hir::ExprIndex(ref base, ref idx) => {
3619
          check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3620 3621
          check_expr(fcx, &**idx);

3622
          let base_t = fcx.expr_ty(&**base);
3623 3624
          let idx_t = fcx.expr_ty(&**idx);

3625
          if base_t.references_error() {
3626
              fcx.write_ty(id, base_t);
3627
          } else if idx_t.references_error() {
3628
              fcx.write_ty(id, idx_t);
3629
          } else {
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647
              let base_t = structurally_resolved_type(fcx, expr.span, base_t);
              match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
                  Some((index_ty, element_ty)) => {
                      let idx_expr_ty = fcx.expr_ty(idx);
                      demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
                      fcx.write_ty(id, element_ty);
                  }
                  None => {
                      check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
                      fcx.type_error_message(
                          expr.span,
                          |actual| {
                              format!("cannot index a value of type `{}`",
                                      actual)
                          },
                          base_t,
                          None);
                      fcx.write_ty(id, fcx.tcx().types.err);
N
Nick Cameron 已提交
3648 3649 3650 3651
                  }
              }
          }
       }
3652
       hir::ExprRange(ref start, ref end) => {
3653
          let t_start = start.as_ref().map(|e| {
N
Nick Cameron 已提交
3654
            check_expr(fcx, &**e);
3655 3656 3657 3658 3659 3660 3661 3662
            fcx.expr_ty(&**e)
          });
          let t_end = end.as_ref().map(|e| {
            check_expr(fcx, &**e);
            fcx.expr_ty(&**e)
          });

          let idx_type = match (t_start, t_end) {
N
Niko Matsakis 已提交
3663 3664 3665
              (Some(ty), None) | (None, Some(ty)) => {
                  Some(ty)
              }
3666 3667
              (Some(t_start), Some(t_end)) if (t_start.references_error() ||
                                               t_end.references_error()) => {
N
Niko Matsakis 已提交
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677
                  Some(fcx.tcx().types.err)
              }
              (Some(t_start), Some(t_end)) => {
                  Some(infer::common_supertype(fcx.infcx(),
                                               infer::RangeExpression(expr.span),
                                               true,
                                               t_start,
                                               t_end))
              }
              _ => None
N
Nick Cameron 已提交
3678
          };
N
Nick Cameron 已提交
3679

N
Nick Cameron 已提交
3680
          // Note that we don't check the type of start/end satisfy any
3681
          // bounds because right now the range structs do not have any. If we add
N
Nick Cameron 已提交
3682 3683
          // some bounds, then we'll need to check `t_start` against them here.

N
Nick Cameron 已提交
3684
          let range_type = match idx_type {
3685
            Some(idx_type) if idx_type.references_error() => {
N
Niko Matsakis 已提交
3686
                fcx.tcx().types.err
3687
            }
N
Nick Cameron 已提交
3688 3689 3690 3691 3692 3693 3694 3695 3696 3697
            Some(idx_type) => {
                // Find the did from the appropriate lang item.
                let did = match (start, end) {
                    (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
                    (&Some(_), &None) => tcx.lang_items.range_from_struct(),
                    (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
                    (&None, &None) => {
                        tcx.sess.span_bug(expr.span, "full range should be dealt with above")
                    }
                };
N
Nick Cameron 已提交
3698

N
Nick Cameron 已提交
3699
                if let Some(did) = did {
3700
                    let def = tcx.lookup_adt_def(did);
3701
                    let predicates = tcx.lookup_predicates(did);
N
Nick Cameron 已提交
3702
                    let substs = Substs::new_type(vec![idx_type], vec![]);
3703
                    let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
N
Nick Cameron 已提交
3704 3705 3706 3707 3708 3709
                    fcx.add_obligations_for_parameters(
                        traits::ObligationCause::new(expr.span,
                                                     fcx.body_id,
                                                     traits::ItemObligation(did)),
                        &bounds);

3710
                    tcx.mk_struct(def, tcx.mk_substs(substs))
N
Nick Cameron 已提交
3711
                } else {
B
Brian Anderson 已提交
3712
                    span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
N
Niko Matsakis 已提交
3713
                    fcx.tcx().types.err
N
Nick Cameron 已提交
3714 3715 3716
                }
            }
            None => {
N
Nick Cameron 已提交
3717 3718
                // Neither start nor end => RangeFull
                if let Some(did) = tcx.lang_items.range_full_struct() {
3719 3720 3721 3722
                    tcx.mk_struct(
                        tcx.lookup_adt_def(did),
                        tcx.mk_substs(Substs::empty())
                    )
N
Nick Cameron 已提交
3723
                } else {
B
Brian Anderson 已提交
3724
                    span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
N
Niko Matsakis 已提交
3725
                    fcx.tcx().types.err
N
Nick Cameron 已提交
3726
                }
N
Nick Cameron 已提交
3727
            }
N
Nick Cameron 已提交
3728
          };
N
Nick Cameron 已提交
3729

N
Nick Cameron 已提交
3730
          fcx.write_ty(id, range_type);
N
Nick Cameron 已提交
3731 3732
       }

B
Brian Anderson 已提交
3733 3734
    }

3735
    debug!("type of expr({}) {} is...", expr.id,
3736
           pprust::expr_to_string(expr));
3737 3738 3739
    debug!("... {:?}, expected is {:?}",
           fcx.expr_ty(expr),
           expected);
B
Brian Anderson 已提交
3740 3741 3742 3743

    unifier();
}

3744 3745 3746
pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                             path_res: def::PathResolution,
                                             opt_self_ty: Option<Ty<'tcx>>,
3747
                                             path: &'a hir::Path,
3748 3749 3750
                                             span: Span,
                                             node_id: ast::NodeId)
                                             -> Option<(Option<Ty<'tcx>>,
3751
                                                        &'a [hir::PathSegment],
3752 3753
                                                        def::Def)>
{
3754 3755 3756 3757 3758 3759 3760 3761 3762

    // Associated constants can't depend on generic types.
    fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                def: def::Def,
                                                ty: Ty<'tcx>,
                                                span: Span,
                                                node_id: ast::NodeId) -> bool {
        match def {
            def::DefAssociatedConst(..) => {
3763
                if ty.has_param_types() || ty.has_self_ty() {
3764 3765 3766
                    span_err!(fcx.sess(), span, E0329,
                              "Associated consts cannot depend \
                               on type parameters or Self.");
3767 3768 3769 3770 3771 3772 3773 3774 3775
                    fcx.write_error(node_id);
                    return true;
                }
            }
            _ => {}
        }
        false
    }

3776 3777
    // If fully resolved already, we don't have to do anything.
    if path_res.depth == 0 {
3778
        if let Some(ty) = opt_self_ty {
3779 3780 3781
            if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
                                              span, node_id) {
                return None;
3782 3783
            }
        }
3784 3785 3786
        Some((opt_self_ty, &path.segments, path_res.base_def))
    } else {
        let mut def = path_res.base_def;
S
Simonas Kazlauskas 已提交
3787
        let ty_segments = path.segments.split_last().unwrap().1;
3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798
        let base_ty_end = path.segments.len() - path_res.depth;
        let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
                                                     PathParamMode::Optional,
                                                     &mut def,
                                                     opt_self_ty,
                                                     &ty_segments[..base_ty_end],
                                                     &ty_segments[base_ty_end..]);
        let item_segment = path.segments.last().unwrap();
        let item_name = item_segment.identifier.name;
        match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
            Ok((def, lp)) => {
3799 3800
                if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
                    return None;
3801
                }
3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820
                // Write back the new resolution.
                fcx.ccx.tcx.def_map.borrow_mut()
                       .insert(node_id, def::PathResolution {
                   base_def: def,
                   last_private: path_res.last_private.or(lp),
                   depth: 0
                });
                Some((Some(ty), slice::ref_slice(item_segment), def))
            }
            Err(error) => {
                method::report_error(fcx, span, ty,
                                     item_name, None, error);
                fcx.write_error(node_id);
                None
            }
        }
    }
}

3821
impl<'tcx> Expectation<'tcx> {
3822 3823 3824 3825 3826 3827
    /// Provide an expectation for an rvalue expression given an *optional*
    /// hint, which is not required for type safety (the resulting type might
    /// be checked higher up, as is the case with `&expr` and `box expr`), but
    /// is useful in determining the concrete type.
    ///
    /// The primary use case is where the expected type is a fat pointer,
3828
    /// like `&[isize]`. For example, consider the following statement:
3829
    ///
3830
    ///    let x: &[isize] = &[1, 2, 3];
3831 3832
    ///
    /// In this case, the expected type for the `&[1, 2, 3]` expression is
3833 3834 3835
    /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
    /// expectation `ExpectHasType([isize])`, that would be too strong --
    /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3836
    /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3837
    /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3838 3839 3840
    /// which still is useful, because it informs integer literals and the like.
    /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
    /// for examples of where this comes up,.
3841 3842
    fn rvalue_hint(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
        match tcx.struct_tail(ty).sty {
3843
            ty::TySlice(_) | ty::TyTrait(..) => {
3844 3845 3846 3847 3848 3849
                ExpectRvalueLikeUnsized(ty)
            }
            _ => ExpectHasType(ty)
        }
    }

3850 3851 3852
    // Resolves `expected` by a single level if it is a variable. If
    // there is no expected type or resolution is not possible (e.g.,
    // no constraints yet present), just returns `None`.
3853
    fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3854 3855 3856 3857 3858 3859
        match self {
            NoExpectation => {
                NoExpectation
            }
            ExpectCastableToType(t) => {
                ExpectCastableToType(
3860
                    fcx.infcx().resolve_type_vars_if_possible(&t))
3861 3862 3863
            }
            ExpectHasType(t) => {
                ExpectHasType(
3864
                    fcx.infcx().resolve_type_vars_if_possible(&t))
3865
            }
3866 3867 3868 3869
            ExpectRvalueLikeUnsized(t) => {
                ExpectRvalueLikeUnsized(
                    fcx.infcx().resolve_type_vars_if_possible(&t))
            }
3870 3871 3872
        }
    }

3873
    fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3874
        match self.resolve(fcx) {
3875
            NoExpectation => None,
3876 3877
            ExpectCastableToType(ty) |
            ExpectHasType(ty) |
3878
            ExpectRvalueLikeUnsized(ty) => Some(ty),
3879 3880 3881
        }
    }

3882
    fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3883
        match self.resolve(fcx) {
3884 3885
            ExpectHasType(ty) => Some(ty),
            _ => None
3886 3887 3888 3889
        }
    }
}

3890
pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3891 3892
                                       local: &'tcx hir::Local,
                                       init: &'tcx hir::Expr)
3893
{
3894 3895 3896
    let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);

    let local_ty = fcx.local_ty(init.span, local.id);
3897
    if let Some(m) = ref_bindings {
3898 3899 3900 3901 3902 3903 3904 3905
        // Somewhat subtle: if we have a `ref` binding in the pattern,
        // we want to avoid introducing coercions for the RHS. This is
        // both because it helps preserve sanity and, in the case of
        // ref mut, for soundness (issue #23116). In particular, in
        // the latter case, we need to be clear that the type of the
        // referent for the reference that results is *equal to* the
        // type of the lvalue it is referencing, and not some
        // supertype thereof.
3906
        check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
3907 3908
        let init_ty = fcx.expr_ty(init);
        demand::eqtype(fcx, init.span, init_ty, local_ty);
3909 3910
    } else {
        check_expr_coercable_to_type(fcx, init, local_ty)
3911
    };
B
Brian Anderson 已提交
3912 3913
}

3914
pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx hir::Local)  {
B
Brian Anderson 已提交
3915 3916
    let tcx = fcx.ccx.tcx;

3917 3918
    let t = fcx.local_ty(local.span, local.id);
    fcx.write_ty(local.id, t);
B
Brian Anderson 已提交
3919

3920
    if let Some(ref init) = local.init {
3921
        check_decl_initializer(fcx, local, &**init);
3922
        let init_ty = fcx.expr_ty(&**init);
3923
        if init_ty.references_error() {
3924
            fcx.write_ty(local.id, init_ty);
B
Brian Anderson 已提交
3925 3926 3927
        }
    }

3928
    let pcx = pat_ctxt {
B
Brian Anderson 已提交
3929
        fcx: fcx,
3930
        map: pat_id_map(&tcx.def_map, &*local.pat),
B
Brian Anderson 已提交
3931
    };
3932
    _match::check_pat(&pcx, &*local.pat, t);
3933
    let pat_ty = fcx.node_ty(local.pat.id);
3934
    if pat_ty.references_error() {
3935
        fcx.write_ty(local.id, pat_ty);
T
Tim Chevalier 已提交
3936
    }
B
Brian Anderson 已提交
3937 3938
}

3939
pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx hir::Stmt)  {
3940
    let node_id;
T
Tim Chevalier 已提交
3941 3942
    let mut saw_bot = false;
    let mut saw_err = false;
B
Brian Anderson 已提交
3943
    match stmt.node {
3944
      hir::StmtDecl(ref decl, id) => {
B
Brian Anderson 已提交
3945
        node_id = id;
3946
        match decl.node {
3947
          hir::DeclLocal(ref l) => {
3948
              check_decl_local(fcx, &**l);
3949
              let l_t = fcx.node_ty(l.id);
J
Jakub Bukaj 已提交
3950
              saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
3951
              saw_err = saw_err || l_t.references_error();
3952
          }
3953
          hir::DeclItem(_) => {/* ignore for now */ }
B
Brian Anderson 已提交
3954 3955
        }
      }
3956
      hir::StmtExpr(ref expr, id) => {
B
Brian Anderson 已提交
3957
        node_id = id;
T
Tim Chevalier 已提交
3958
        // Check with expected type of ()
3959
        check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
3960
        let expr_ty = fcx.expr_ty(&**expr);
J
Jakub Bukaj 已提交
3961
        saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
3962
        saw_err = saw_err || expr_ty.references_error();
B
Brian Anderson 已提交
3963
      }
3964
      hir::StmtSemi(ref expr, id) => {
B
Brian Anderson 已提交
3965
        node_id = id;
3966 3967
        check_expr(fcx, &**expr);
        let expr_ty = fcx.expr_ty(&**expr);
J
Jakub Bukaj 已提交
3968
        saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
3969
        saw_err |= expr_ty.references_error();
B
Brian Anderson 已提交
3970 3971
      }
    }
T
Tim Chevalier 已提交
3972
    if saw_bot {
J
Jakub Bukaj 已提交
3973
        fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
T
Tim Chevalier 已提交
3974 3975 3976 3977 3978 3979 3980
    }
    else if saw_err {
        fcx.write_error(node_id);
    }
    else {
        fcx.write_nil(node_id)
    }
B
Brian Anderson 已提交
3981 3982
}

3983
pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx hir::Block)  {
3984
    check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
3985
    let blkty = fcx.node_ty(blk.id);
3986
    if blkty.references_error() {
3987
        fcx.write_error(blk.id);
J
Jakub Bukaj 已提交
3988
    } else {
3989
        let nilty = fcx.tcx().mk_nil();
B
Brian Anderson 已提交
3990 3991 3992 3993
        demand::suptype(fcx, blk.span, nilty, blkty);
    }
}

3994
fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3995
                                       blk: &'tcx hir::Block,
3996
                                       expected: Expectation<'tcx>) {
P
Patrick Walton 已提交
3997 3998
    let prev = {
        let mut fcx_ps = fcx.ps.borrow_mut();
N
Niko Matsakis 已提交
3999 4000
        let unsafety_state = fcx_ps.recurse(blk);
        replace(&mut *fcx_ps, unsafety_state)
P
Patrick Walton 已提交
4001
    };
4002

4003
    let mut warned = false;
J
Jakub Bukaj 已提交
4004
    let mut any_diverges = false;
4005
    let mut any_err = false;
4006
    for s in &blk.stmts {
4007
        check_stmt(fcx, &**s);
4008
        let s_id = ::rustc_front::util::stmt_id(&**s);
4009
        let s_ty = fcx.node_ty(s_id);
J
Jakub Bukaj 已提交
4010
        if any_diverges && !warned && match s.node {
4011
            hir::StmtDecl(ref decl, _) => {
4012
                match decl.node {
4013
                    hir::DeclLocal(_) => true,
4014 4015
                    _ => false,
                }
T
Tim Chevalier 已提交
4016
            }
4017
            hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
4018 4019 4020 4021 4022 4023 4024 4025 4026
        } {
            fcx.ccx
                .tcx
                .sess
                .add_lint(lint::builtin::UNREACHABLE_CODE,
                          s_id,
                          s.span,
                          "unreachable statement".to_string());
            warned = true;
B
Brian Anderson 已提交
4027
        }
J
Jakub Bukaj 已提交
4028
        any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4029
        any_err = any_err || s_ty.references_error();
4030 4031 4032 4033
    }
    match blk.expr {
        None => if any_err {
            fcx.write_error(blk.id);
J
Jakub Bukaj 已提交
4034 4035
        } else if any_diverges {
            fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4036
        } else {
4037 4038
            fcx.write_nil(blk.id);
        },
4039
        Some(ref e) => {
J
Jakub Bukaj 已提交
4040
            if any_diverges && !warned {
4041 4042 4043 4044 4045 4046 4047 4048 4049 4050
                fcx.ccx
                    .tcx
                    .sess
                    .add_lint(lint::builtin::UNREACHABLE_CODE,
                              e.id,
                              e.span,
                              "unreachable expression".to_string());
            }
            let ety = match expected {
                ExpectHasType(ety) => {
4051
                    check_expr_coercable_to_type(fcx, &**e, ety);
4052
                    ety
N
Nick Cameron 已提交
4053
                }
4054
                _ => {
4055 4056
                    check_expr_with_expectation(fcx, &**e, expected);
                    fcx.expr_ty(&**e)
N
Nick Cameron 已提交
4057
                }
4058
            };
N
Nick Cameron 已提交
4059

4060 4061
            if any_err {
                fcx.write_error(blk.id);
J
Jakub Bukaj 已提交
4062 4063 4064 4065
            } else if any_diverges {
                fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
            } else {
                fcx.write_ty(blk.id, ety);
N
Nick Cameron 已提交
4066
            }
4067 4068
        }
    };
4069

E
Erick Tryzelaar 已提交
4070
    *fcx.ps.borrow_mut() = prev;
B
Brian Anderson 已提交
4071 4072
}

4073 4074 4075
/// Checks a constant appearing in a type. At the moment this is just the
/// length expression in a fixed-length vector, but someday it might be
/// extended to type-level numeric literals.
4076
fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4077
                                expr: &'tcx hir::Expr,
4078
                                expected_type: Ty<'tcx>) {
4079 4080
    let tables = RefCell::new(ty::Tables::empty());
    let inh = static_inherited_fields(ccx, &tables);
4081
    let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4082 4083 4084
    check_const_with_ty(&fcx, expr.span, expr, expected_type);
}

4085 4086
fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                        sp: Span,
4087
                        e: &'tcx hir::Expr,
4088
                        id: ast::NodeId) {
4089 4090
    let tables = RefCell::new(ty::Tables::empty());
    let inh = static_inherited_fields(ccx, &tables);
4091
    let rty = ccx.tcx.node_id_to_type(id);
J
Jakub Bukaj 已提交
4092
    let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4093
    let declty = fcx.ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
E
Eduard Burtescu 已提交
4094
    check_const_with_ty(&fcx, sp, e, declty);
B
Brian Anderson 已提交
4095 4096
}

4097 4098
fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                 _: Span,
4099
                                 e: &'tcx hir::Expr,
4100
                                 declty: Ty<'tcx>) {
4101
    // Gather locals in statics (because of block expressions).
4102
    // This is technically unnecessary because locals in static items are forbidden,
4103
    // but prevents type checking from blowing up before const checking can properly
4104
    // emit an error.
4105
    GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4106

N
Nick Cameron 已提交
4107 4108
    check_expr_with_hint(fcx, e, declty);
    demand::coerce(fcx, e.span, declty, e);
4109 4110 4111 4112

    fcx.select_all_obligations_and_apply_defaults();
    upvar::closure_analyze_const(&fcx, e);
    fcx.select_obligations_where_possible();
N
Nick Cameron 已提交
4113
    fcx.check_casts();
4114 4115
    fcx.select_all_obligations_or_error();

B
Brian Anderson 已提交
4116 4117 4118 4119
    regionck::regionck_expr(fcx, e);
    writeback::resolve_type_vars_in_expr(fcx, e);
}

4120 4121
/// Checks whether a type can be represented in memory. In particular, it
/// identifies types that contain themselves without indirection through a
4122
/// pointer, which would mean their size is unbounded.
E
Eduard Burtescu 已提交
4123
pub fn check_representable(tcx: &ty::ctxt,
4124 4125
                           sp: Span,
                           item_id: ast::NodeId,
N
Nick Cameron 已提交
4126
                           designation: &str) -> bool {
4127
    let rty = tcx.node_id_to_type(item_id);
4128 4129 4130 4131 4132 4133

    // Check that it is possible to represent this type. This call identifies
    // (1) types that contain themselves and (2) types that contain a different
    // recursive type. It is only necessary to throw an error on those that
    // contain themselves. For case 2, there must be an inner type that will be
    // caught by case 1.
4134
    match rty.is_representable(tcx, sp) {
4135 4136 4137 4138 4139 4140 4141
        Representability::SelfRecursive => {
            span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
            tcx.sess.fileline_help(
                sp, "wrap the inner value in a box to make it representable");
            return false
        }
        Representability::Representable | Representability::ContainsRecursive => (),
4142
    }
N
Nick Cameron 已提交
4143
    return true
4144 4145
}

E
Eduard Burtescu 已提交
4146
pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4147
    let t = tcx.node_id_to_type(id);
4148
    match t.sty {
4149
        ty::TyStruct(def, substs) => {
4150
            let fields = &def.struct_variant().fields;
S
Seo Sanghyeon 已提交
4151
            if fields.is_empty() {
4152
                span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
S
Seo Sanghyeon 已提交
4153 4154
                return;
            }
4155 4156
            let e = fields[0].ty(tcx, substs);
            if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
4157
                span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
S
Seo Sanghyeon 已提交
4158 4159
                return;
            }
H
Huon Wilson 已提交
4160 4161 4162 4163 4164 4165 4166 4167
            match e.sty {
                ty::TyParam(_) => { /* struct<T>(T, T, T, T) is ok */ }
                _ if e.is_machine()  => { /* struct(u8, u8, u8, u8) is ok */ }
                _ => {
                    span_err!(tcx.sess, sp, E0077,
                              "SIMD vector element type should be machine type");
                    return;
                }
S
Seo Sanghyeon 已提交
4168 4169 4170 4171
            }
        }
        _ => ()
    }
B
Brian Anderson 已提交
4172 4173
}

4174 4175
pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                    sp: Span,
4176
                                    vs: &'tcx [P<hir::Variant>],
4177
                                    id: ast::NodeId) {
4178

E
Eduard Burtescu 已提交
4179
    fn disr_in_range(ccx: &CrateCtxt,
4180 4181
                     ty: attr::IntType,
                     disr: ty::Disr) -> bool {
4182
        fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4183
            match ty {
4184 4185 4186 4187 4188
                ast::TyU8 => disr as u8 as Disr == disr,
                ast::TyU16 => disr as u16 as Disr == disr,
                ast::TyU32 => disr as u32 as Disr == disr,
                ast::TyU64 => disr as u64 as Disr == disr,
                ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4189 4190
            }
        }
4191
        fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4192
            match ty {
4193 4194 4195 4196 4197
                ast::TyI8 => disr as i8 as Disr == disr,
                ast::TyI16 => disr as i16 as Disr == disr,
                ast::TyI32 => disr as i32 as Disr == disr,
                ast::TyI64 => disr as i64 as Disr == disr,
                ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4198 4199 4200 4201 4202 4203 4204 4205
            }
        }
        match ty {
            attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
            attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
        }
    }

4206
    fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4207
                          vs: &'tcx [P<hir::Variant>],
4208
                          id: ast::NodeId,
4209
                          hint: attr::ReprAttr) {
A
Aaron Turon 已提交
4210
        #![allow(trivial_numeric_casts)]
4211

4212
        let rty = ccx.tcx.node_id_to_type(id);
4213
        let mut disr_vals: Vec<ty::Disr> = Vec::new();
B
Brian Anderson 已提交
4214

4215 4216
        let tables = RefCell::new(ty::Tables::empty());
        let inh = static_inherited_fields(ccx, &tables);
4217
        let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
B
Brian Anderson 已提交
4218

4219
        let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint));
4220 4221 4222 4223 4224
        for v in vs {
            if let Some(ref e) = v.node.disr_expr {
                check_const_with_ty(&fcx, e.span, e, repr_type_ty);
            }
        }
B
Brian Anderson 已提交
4225

4226
        let def_id = ccx.tcx.map.local_def_id(id);
4227

4228
        let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
4229
        for (v, variant) in vs.iter().zip(variants.iter()) {
4230
            let current_disr_val = variant.disr_val;
B
Brian Anderson 已提交
4231

4232
            // Check for duplicate discriminant values
4233 4234 4235 4236
            match disr_vals.iter().position(|&x| x == current_disr_val) {
                Some(i) => {
                    span_err!(ccx.tcx.sess, v.span, E0081,
                        "discriminant value `{}` already exists", disr_vals[i]);
4237 4238
                    let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
                    span_note!(ccx.tcx.sess, ccx.tcx.map.span(variant_i_node_id),
4239 4240 4241
                        "conflicting discriminant here")
                }
                None => {}
4242 4243 4244 4245 4246 4247
            }
            // Check for unrepresentable discriminant values
            match hint {
                attr::ReprAny | attr::ReprExtern => (),
                attr::ReprInt(sp, ity) => {
                    if !disr_in_range(ccx, ity, current_disr_val) {
4248 4249 4250 4251
                        span_err!(ccx.tcx.sess, v.span, E0082,
                            "discriminant value outside specified type");
                        span_note!(ccx.tcx.sess, sp,
                            "discriminant type specified here");
4252 4253
                    }
                }
4254 4255 4256
                attr::ReprSimd => {
                    ccx.tcx.sess.bug("range_to_inttype: found ReprSimd on an enum");
                }
4257 4258 4259
                attr::ReprPacked => {
                    ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
                }
4260 4261
            }
            disr_vals.push(current_disr_val);
B
Brian Anderson 已提交
4262 4263 4264
        }
    }

4265 4266
    let def_id = ccx.tcx.map.local_def_id(id);
    let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny);
4267

4268
    if hint != attr::ReprAny && vs.len() <= 1 {
4269 4270 4271
        if vs.len() == 1 {
            span_err!(ccx.tcx.sess, sp, E0083,
                "unsupported representation for univariant enum");
4272
        } else {
4273 4274
            span_err!(ccx.tcx.sess, sp, E0084,
                "unsupported representation for zero-variant enum");
4275
        };
4276
    }
B
Brian Anderson 已提交
4277

4278
    do_check(ccx, vs, id, hint);
B
Brian Anderson 已提交
4279

4280
    check_representable(ccx.tcx, sp, id, "enum");
B
Brian Anderson 已提交
4281 4282 4283
}

// Returns the type parameter count and the type for the given definition.
4284 4285 4286 4287
fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                sp: Span,
                                                defn: def::Def)
                                                -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
B
Brian Anderson 已提交
4288
    match defn {
4289
        def::DefLocal(_, nid) | def::DefUpvar(_, nid, _, _) => {
4290 4291 4292 4293
            let typ = fcx.local_ty(sp, nid);
            (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
             ty::GenericPredicates::empty())
        }
4294
        def::DefFn(id, _) | def::DefMethod(id) |
4295
        def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4296
        def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id) => {
4297
            (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
4298
        }
4299
        def::DefTrait(_) |
4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
        def::DefTy(..) |
        def::DefAssociatedTy(..) |
        def::DefPrimTy(_) |
        def::DefTyParam(..) |
        def::DefMod(..) |
        def::DefForeignMod(..) |
        def::DefUse(..) |
        def::DefLabel(..) |
        def::DefSelfTy(..) => {
            fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
        }
B
Brian Anderson 已提交
4311 4312 4313 4314 4315
    }
}

// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
4316
pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4317
                                  segments: &[hir::PathSegment],
4318
                                  type_scheme: TypeScheme<'tcx>,
4319
                                  type_predicates: &ty::GenericPredicates<'tcx>,
4320
                                  opt_self_ty: Option<Ty<'tcx>>,
4321 4322 4323
                                  def: def::Def,
                                  span: Span,
                                  node_id: ast::NodeId) {
4324
    debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
4325
           segments,
4326
           def,
4327
           node_id,
4328
           type_scheme);
4329 4330 4331 4332 4333 4334 4335 4336

    // We need to extract the type parameters supplied by the user in
    // the path `path`. Due to the current setup, this is a bit of a
    // tricky-process; the problem is that resolve only tells us the
    // end-point of the path resolution, and not the intermediate steps.
    // Luckily, we can (at least for now) deduce the intermediate steps
    // just from the end-point.
    //
4337
    // There are basically four cases to consider:
4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357
    //
    // 1. Reference to a *type*, such as a struct or enum:
    //
    //        mod a { struct Foo<T> { ... } }
    //
    //    Because we don't allow types to be declared within one
    //    another, a path that leads to a type will always look like
    //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
    //    that only the final segment can have type parameters, and
    //    they are located in the TypeSpace.
    //
    //    *Note:* Generally speaking, references to types don't
    //    actually pass through this function, but rather the
    //    `ast_ty_to_ty` function in `astconv`. However, in the case
    //    of struct patterns (and maybe literals) we do invoke
    //    `instantiate_path` to get the general type of an instance of
    //    a struct. (In these cases, there are actually no type
    //    parameters permitted at present, but perhaps we will allow
    //    them in the future.)
    //
4358
    // 1b. Reference to an enum variant or tuple-like struct:
4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386
    //
    //        struct foo<T>(...)
    //        enum E<T> { foo(...) }
    //
    //    In these cases, the parameters are declared in the type
    //    space.
    //
    // 2. Reference to a *fn item*:
    //
    //        fn foo<T>() { }
    //
    //    In this case, the path will again always have the form
    //    `a::b::foo::<T>` where only the final segment should have
    //    type parameters. However, in this case, those parameters are
    //    declared on a value, and hence are in the `FnSpace`.
    //
    // 3. Reference to a *method*:
    //
    //        impl<A> SomeStruct<A> {
    //            fn foo<B>(...)
    //        }
    //
    //    Here we can have a path like
    //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
    //    may appear in two places. The penultimate segment,
    //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
    //    final segment, `foo::<B>` contains parameters in fn space.
    //
4387 4388 4389 4390 4391 4392 4393 4394 4395 4396
    // 4. Reference to an *associated const*:
    //
    // impl<A> AnotherStruct<A> {
    // const FOO: B = BAR;
    // }
    //
    // The path in this case will look like
    // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
    // only will have parameters in TypeSpace.
    //
4397
    // The first step then is to categorize the segments appropriately.
B
Brian Anderson 已提交
4398

4399
    assert!(!segments.is_empty());
4400

4401
    let mut ufcs_associated = None;
A
Aaron Turon 已提交
4402
    let mut segment_spaces: Vec<_>;
4403 4404 4405 4406 4407 4408
    match def {
        // Case 1 and 1b. Reference to a *type* or *enum variant*.
        def::DefSelfTy(..) |
        def::DefStruct(..) |
        def::DefVariant(..) |
        def::DefTy(..) |
4409
        def::DefAssociatedTy(..) |
4410
        def::DefTrait(..) |
4411 4412 4413 4414
        def::DefPrimTy(..) |
        def::DefTyParam(..) => {
            // Everything but the final segment should have no
            // parameters at all.
U
Ulrik Sverdrup 已提交
4415
            segment_spaces = vec![None; segments.len() - 1];
4416
            segment_spaces.push(Some(subst::TypeSpace));
B
Brian Anderson 已提交
4417
        }
4418

4419 4420
        // Case 2. Reference to a top-level value.
        def::DefFn(..) |
4421
        def::DefConst(..) |
4422
        def::DefStatic(..) => {
U
Ulrik Sverdrup 已提交
4423
            segment_spaces = vec![None; segments.len() - 1];
4424 4425
            segment_spaces.push(Some(subst::FnSpace));
        }
B
Brian Anderson 已提交
4426

4427
        // Case 3. Reference to a method.
4428 4429 4430 4431
        def::DefMethod(def_id) => {
            let container = fcx.tcx().impl_or_trait_item(def_id).container();
            match container {
                ty::TraitContainer(trait_did) => {
4432 4433
                    callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
                }
4434
                ty::ImplContainer(_) => {}
4435 4436
            }

4437
            if segments.len() >= 2 {
U
Ulrik Sverdrup 已提交
4438
                segment_spaces = vec![None; segments.len() - 2];
4439 4440 4441 4442
                segment_spaces.push(Some(subst::TypeSpace));
                segment_spaces.push(Some(subst::FnSpace));
            } else {
                // `<T>::method` will end up here, and so can `T::method`.
4443
                let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4444
                segment_spaces = vec![Some(subst::FnSpace)];
4445
                ufcs_associated = Some((container, self_ty));
4446
            }
4447 4448
        }

4449 4450 4451 4452
        def::DefAssociatedConst(def_id) => {
            let container = fcx.tcx().impl_or_trait_item(def_id).container();
            match container {
                ty::TraitContainer(trait_did) => {
4453 4454
                    callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
                }
4455
                ty::ImplContainer(_) => {}
4456 4457 4458
            }

            if segments.len() >= 2 {
U
Ulrik Sverdrup 已提交
4459
                segment_spaces = vec![None; segments.len() - 2];
4460 4461 4462
                segment_spaces.push(Some(subst::TypeSpace));
                segment_spaces.push(None);
            } else {
4463 4464
                // `<T>::CONST` will end up here, and so can `T::CONST`.
                let self_ty = opt_self_ty.expect("UFCS sugared const missing Self");
4465
                segment_spaces = vec![None];
4466
                ufcs_associated = Some((container, self_ty));
4467
            }
4468 4469
        }

4470 4471 4472 4473 4474 4475 4476 4477 4478
        // Other cases. Various nonsense that really shouldn't show up
        // here. If they do, an error will have been reported
        // elsewhere. (I hope)
        def::DefMod(..) |
        def::DefForeignMod(..) |
        def::DefLocal(..) |
        def::DefUse(..) |
        def::DefLabel(..) |
        def::DefUpvar(..) => {
U
Ulrik Sverdrup 已提交
4479
            segment_spaces = vec![None; segments.len()];
4480
        }
4481
    }
4482
    assert_eq!(segment_spaces.len(), segments.len());
4483

4484 4485 4486
    // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
    // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
    // type parameters are not mandatory.
4487
    let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none();
4488

4489
    debug!("segment_spaces={:?}", segment_spaces);
4490 4491 4492

    // Next, examine the definition, and determine how many type
    // parameters we expect from each space.
4493 4494
    let type_defs = &type_scheme.generics.types;
    let region_defs = &type_scheme.generics.regions;
4495 4496 4497 4498 4499 4500

    // Now that we have categorized what space the parameters for each
    // segment belong to, let's sort out the parameters that the user
    // provided (if any) into their appropriate spaces. We'll also report
    // errors if type parameters are provided in an inappropriate place.
    let mut substs = Substs::empty();
4501
    for (opt_space, segment) in segment_spaces.iter().zip(segments) {
4502 4503
        match *opt_space {
            None => {
4504
                prohibit_type_params(fcx.tcx(), slice::ref_slice(segment));
4505
            }
4506

4507 4508 4509
            Some(space) => {
                push_explicit_parameters_from_segment_to_substs(fcx,
                                                                space,
4510
                                                                span,
4511 4512 4513 4514
                                                                type_defs,
                                                                region_defs,
                                                                segment,
                                                                &mut substs);
4515 4516
            }
        }
4517
    }
4518
    if let Some(self_ty) = opt_self_ty {
4519 4520 4521
        if type_defs.len(subst::SelfSpace) == 1 {
            substs.types.push(subst::SelfSpace, self_ty);
        }
4522
    }
4523

4524 4525 4526 4527 4528 4529
    // Now we have to compare the types that the user *actually*
    // provided against the types that were *expected*. If the user
    // did not provide any types, then we want to substitute inference
    // variables. If the user provided some types, we may still need
    // to add defaults. If the user provided *too many* types, that's
    // a problem.
4530
    for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
4531
        adjust_type_parameters(fcx, span, space, type_defs,
4532
                               require_type_space, &mut substs);
4533
        assert_eq!(substs.types.len(space), type_defs.len(space));
4534 4535

        adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4536
        assert_eq!(substs.regions().len(space), region_defs.len(space));
4537
    }
4538

4539
    // The things we are substituting into the type should not contain
4540
    // escaping late-bound regions, and nor should the base type scheme.
4541
    assert!(!substs.has_regions_escaping_depth(0));
4542
    assert!(!type_scheme.has_escaping_regions());
4543

4544 4545
    // Add all the obligations that are required, substituting and
    // normalized appropriately.
4546
    let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4547
    fcx.add_obligations_for_parameters(
N
Niko Matsakis 已提交
4548
        traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4549
        &bounds);
4550

4551 4552
    // Substitute the values for the type parameters into the type of
    // the referenced item.
4553
    let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4554

4555

4556
    if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated {
4557 4558 4559 4560
        // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
        // is inherent, there is no `Self` parameter, instead, the impl needs
        // type parameters, which we can infer by unifying the provided `Self`
        // with the substituted impl type.
4561
        let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
4562 4563 4564 4565 4566 4567 4568 4569 4570
        assert_eq!(substs.types.len(subst::TypeSpace),
                   impl_scheme.generics.types.len(subst::TypeSpace));
        assert_eq!(substs.regions().len(subst::TypeSpace),
                   impl_scheme.generics.regions.len(subst::TypeSpace));

        let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
        if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
            fcx.tcx().sess.span_bug(span,
            &format!(
4571 4572 4573
                "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                self_ty,
                impl_ty));
4574 4575 4576
        }
    }

4577 4578 4579
    debug!("instantiate_path: type of {:?} is {:?}",
           node_id,
           ty_substituted);
4580 4581 4582
    fcx.write_ty(node_id, ty_substituted);
    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
    return;
4583

S
Steve Klabnik 已提交
4584 4585 4586 4587 4588 4589 4590 4591 4592
    /// Finds the parameters that the user provided and adds them to `substs`. If too many
    /// parameters are provided, then reports an error and clears the output vector.
    ///
    /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
    /// use inference variables. This seems less likely to lead to derived errors.
    ///
    /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
    /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
    /// here because we can easily use the precise span of the N+1'th parameter.
4593 4594
    fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
        fcx: &FnCtxt<'a, 'tcx>,
4595
        space: subst::ParamSpace,
4596
        span: Span,
4597
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4598
        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4599
        segment: &hir::PathSegment,
4600
        substs: &mut Substs<'tcx>)
4601
    {
4602
        match segment.parameters {
4603
            hir::AngleBracketedParameters(ref data) => {
4604
                push_explicit_angle_bracketed_parameters_from_segment_to_substs(
N
Nick Cameron 已提交
4605
                    fcx, space, type_defs, region_defs, data, substs);
4606 4607
            }

4608
            hir::ParenthesizedParameters(ref data) => {
B
Brian Anderson 已提交
4609
                span_err!(fcx.tcx().sess, span, E0238,
4610
                    "parenthesized parameters may only be used with a trait");
4611 4612 4613 4614 4615 4616
                push_explicit_parenthesized_parameters_from_segment_to_substs(
                    fcx, space, span, type_defs, data, substs);
            }
        }
    }

4617 4618
    fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
        fcx: &FnCtxt<'a, 'tcx>,
4619
        space: subst::ParamSpace,
4620
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4621
        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4622
        data: &hir::AngleBracketedParameterData,
4623
        substs: &mut Substs<'tcx>)
4624
    {
4625
        {
4626 4627
            let type_count = type_defs.len(space);
            assert_eq!(substs.types.len(space), 0);
4628
            for (i, typ) in data.types.iter().enumerate() {
4629
                let t = fcx.to_ty(&**typ);
4630 4631 4632
                if i < type_count {
                    substs.types.push(space, t);
                } else if i == type_count {
4633 4634
                    span_err!(fcx.tcx().sess, typ.span, E0087,
                        "too many type parameters provided: \
4635 4636 4637 4638 4639 4640
                         expected at most {} parameter{}, \
                         found {} parameter{}",
                         type_count,
                         if type_count == 1 {""} else {"s"},
                         data.types.len(),
                         if data.types.len() == 1 {""} else {"s"});
4641
                    substs.types.truncate(space, 0);
4642 4643 4644 4645 4646
                    break;
                }
            }
        }

4647
        if !data.bindings.is_empty() {
N
Nick Cameron 已提交
4648 4649 4650
            span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
                      "unexpected binding of associated item in expression path \
                       (only allowed in type paths)");
4651 4652 4653
        }

        {
4654 4655
            let region_count = region_defs.len(space);
            assert_eq!(substs.regions().len(space), 0);
4656
            for (i, lifetime) in data.lifetimes.iter().enumerate() {
4657 4658 4659 4660
                let r = ast_region_to_region(fcx.tcx(), lifetime);
                if i < region_count {
                    substs.mut_regions().push(space, r);
                } else if i == region_count {
4661 4662
                    span_err!(fcx.tcx().sess, lifetime.span, E0088,
                        "too many lifetime parameters provided: \
4663
                         expected {} parameter{}, found {} parameter{}",
4664
                        region_count,
4665 4666 4667
                        if region_count == 1 {""} else {"s"},
                        data.lifetimes.len(),
                        if data.lifetimes.len() == 1 {""} else {"s"});
4668
                    substs.mut_regions().truncate(space, 0);
4669
                    break;
4670 4671
                }
            }
4672
        }
4673
    }
4674

S
Steve Klabnik 已提交
4675 4676 4677 4678 4679 4680
    /// As with
    /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
    /// but intended for `Foo(A,B) -> C` form. This expands to
    /// roughly the same thing as `Foo<(A,B),C>`. One important
    /// difference has to do with the treatment of anonymous
    /// regions, which are translated into bound regions (NYI).
4681 4682
    fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
        fcx: &FnCtxt<'a, 'tcx>,
4683 4684
        space: subst::ParamSpace,
        span: Span,
4685
        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4686
        data: &hir::ParenthesizedParameterData,
4687
        substs: &mut Substs<'tcx>)
4688 4689 4690 4691 4692 4693 4694 4695 4696
    {
        let type_count = type_defs.len(space);
        if type_count < 2 {
            span_err!(fcx.tcx().sess, span, E0167,
                      "parenthesized form always supplies 2 type parameters, \
                      but only {} parameter(s) were expected",
                      type_count);
        }

4697
        let input_tys: Vec<Ty> =
4698 4699
            data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();

4700
        let tuple_ty = fcx.tcx().mk_tup(input_tys);
4701 4702 4703 4704 4705

        if type_count >= 1 {
            substs.types.push(space, tuple_ty);
        }

4706
        let output_ty: Option<Ty> =
4707 4708 4709
            data.output.as_ref().map(|ty| fcx.to_ty(&**ty));

        let output_ty =
4710
            output_ty.unwrap_or(fcx.tcx().mk_nil());
4711 4712 4713 4714 4715 4716

        if type_count >= 2 {
            substs.types.push(space, output_ty);
        }
    }

4717 4718
    fn adjust_type_parameters<'a, 'tcx>(
        fcx: &FnCtxt<'a, 'tcx>,
4719 4720
        span: Span,
        space: ParamSpace,
4721
        defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4722
        require_type_space: bool,
4723
        substs: &mut Substs<'tcx>)
4724
    {
4725 4726
        let provided_len = substs.types.len(space);
        let desired = defs.get_slice(space);
4727 4728 4729 4730
        let required_len = desired.iter()
                              .take_while(|d| d.default.is_none())
                              .count();

4731
        debug!("adjust_type_parameters(space={:?}, \
4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744
               provided_len={}, \
               desired_len={}, \
               required_len={})",
               space,
               provided_len,
               desired.len(),
               required_len);

        // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
        assert!(provided_len <= desired.len());

        // Nothing specified at all: supply inference variables for
        // everything.
4745
        if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
J
Jared Roesch 已提交
4746
            substs.types.replace(space, Vec::new());
4747
            fcx.infcx().type_vars_for_defs(span, space, substs, &desired[..]);
4748
            return;
4749 4750
        }

4751 4752 4753 4754 4755
        // Too few parameters specified: report an error and use Err
        // for everything.
        if provided_len < required_len {
            let qualifier =
                if desired.len() != required_len { "at least " } else { "" };
4756
            span_err!(fcx.tcx().sess, span, E0089,
4757 4758 4759 4760 4761 4762
                "too few type parameters provided: expected {}{} parameter{}, \
                 found {} parameter{}",
                qualifier, required_len,
                if required_len == 1 {""} else {"s"},
                provided_len,
                if provided_len == 1 {""} else {"s"});
U
Ulrik Sverdrup 已提交
4763
            substs.types.replace(space, vec![fcx.tcx().types.err; desired.len()]);
4764 4765
            return;
        }
4766

4767 4768 4769 4770 4771 4772 4773
        // Otherwise, add in any optional parameters that the user
        // omitted. The case of *too many* parameters is handled
        // already by
        // push_explicit_parameters_from_segment_to_substs(). Note
        // that the *default* type are expressed in terms of all prior
        // parameters, so we have to substitute as we go with the
        // partial substitution that we have built up.
4774
        for i in provided_len..desired.len() {
4775 4776 4777 4778
            let default = desired[i].default.unwrap();
            let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
            substs.types.push(space, default);
        }
4779
        assert_eq!(substs.types.len(space), desired.len());
B
Brian Anderson 已提交
4780

4781
        debug!("Final substs: {:?}", substs);
4782
    }
4783

4784 4785 4786 4787 4788 4789 4790
    fn adjust_region_parameters(
        fcx: &FnCtxt,
        span: Span,
        space: ParamSpace,
        defs: &VecPerParamSpace<ty::RegionParameterDef>,
        substs: &mut Substs)
    {
4791 4792
        let provided_len = substs.mut_regions().len(space);
        let desired = defs.get_slice(space);
4793 4794

        // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4795
        assert!(provided_len <= desired.len());
4796 4797

        // If nothing was provided, just use inference variables.
4798 4799 4800 4801
        if provided_len == 0 {
            substs.mut_regions().replace(
                space,
                fcx.infcx().region_vars_for_defs(span, desired));
4802 4803 4804 4805
            return;
        }

        // If just the right number were provided, everybody is happy.
4806
        if provided_len == desired.len() {
4807 4808
            return;
        }
4809

4810 4811
        // Otherwise, too few were provided. Report an error and then
        // use inference variables.
4812
        span_err!(fcx.tcx().sess, span, E0090,
4813 4814 4815 4816 4817 4818
            "too few lifetime parameters provided: expected {} parameter{}, \
             found {} parameter{}",
            desired.len(),
            if desired.len() == 1 {""} else {"s"},
            provided_len,
            if provided_len == 1 {""} else {"s"});
4819

4820 4821 4822
        substs.mut_regions().replace(
            space,
            fcx.infcx().region_vars_for_defs(span, desired));
4823
    }
B
Brian Anderson 已提交
4824 4825
}

4826 4827 4828 4829 4830
fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                  sp: Span,
                                                  ty: Ty<'tcx>,
                                                  f: F) -> Ty<'tcx>
    where F: Fn() -> Ty<'tcx>
4831 4832
{
    let mut ty = fcx.resolve_type_vars_if_possible(ty);
4833

4834
    if ty.is_ty_var() {
4835 4836 4837
        let alternative = f();

        // If not, error.
4838
        if alternative.is_ty_var() || alternative.references_error() {
4839 4840 4841 4842 4843 4844 4845 4846 4847
            fcx.type_error_message(sp, |_actual| {
                "the type of this value must be known in this context".to_string()
            }, ty, None);
            demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
            ty = fcx.tcx().types.err;
        } else {
            demand::suptype(fcx, sp, alternative, ty);
            ty = alternative;
        }
4848 4849 4850
    }

    ty
B
Brian Anderson 已提交
4851 4852
}

4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864
// Resolves `typ` by a single level if `typ` is a type variable.  If no
// resolution is possible, then an error is reported.
pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                            sp: Span,
                                            ty: Ty<'tcx>)
                                            -> Ty<'tcx>
{
    structurally_resolve_type_or_else(fcx, sp, ty, || {
        fcx.tcx().types.err
    })
}

B
Brian Anderson 已提交
4865
// Returns true if b contains a break that can exit from b
4866
pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool {
B
Brian Anderson 已提交
4867 4868
    // First: is there an unlabeled break immediately
    // inside the loop?
4869
    (loop_query(&*b, |e| {
4870
        match *e {
4871
            hir::ExprBreak(None) => true,
B
Brian Anderson 已提交
4872 4873 4874
            _ => false
        }
    })) ||
4875 4876
    // Second: is there a labeled break with label
    // <id> nested anywhere inside the loop?
B
Brian Anderson 已提交
4877
    (block_query(b, |e| {
4878
        if let hir::ExprBreak(Some(_)) = e.node {
4879 4880 4881 4882 4883
            lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
        } else {
            false
        }
    }))
B
Brian Anderson 已提交
4884 4885
}

4886 4887
pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                       span: Span,
4888
                                       tps: &OwnedSlice<hir::TyParam>,
4889
                                       ty: Ty<'tcx>) {
4890 4891
    debug!("check_bounds_are_used(n_tps={}, ty={:?})",
           tps.len(),  ty);
B
Brian Anderson 已提交
4892 4893

    // make a vector of booleans initially false, set to true when used
4894
    if tps.is_empty() { return; }
U
Ulrik Sverdrup 已提交
4895
    let mut tps_used = vec![false; tps.len()];
B
Brian Anderson 已提交
4896

4897 4898 4899 4900 4901 4902
    for leaf_ty in ty.walk() {
        if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
            debug!("Found use of ty param num {}", idx);
            tps_used[idx as usize] = true;
        }
    }
B
Brian Anderson 已提交
4903

D
Daniel Micay 已提交
4904
    for (i, b) in tps_used.iter().enumerate() {
B
Brian Anderson 已提交
4905
        if !*b {
4906 4907
            span_err!(ccx.tcx.sess, span, E0091,
                "type parameter `{}` is unused",
4908
                tps[i].name);
B
Brian Anderson 已提交
4909 4910 4911
        }
    }
}