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

S
Steve Klabnik 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
//! # Type Coercion
//!
//! Under certain circumstances we will coerce from one type to another,
//! for example by auto-borrowing.  This occurs in situations where the
//! compiler has a firm 'expected type' that was supplied from the user,
//! and where the actual type is similar to that expected type in purpose
//! but not in representation (so actual subtyping is inappropriate).
//!
//! ## Reborrowing
//!
//! Note that if we are expecting a reference, we will *reborrow*
//! even if the argument provided was already a reference.  This is
//! useful for freezing mut/const things (that is, when the expected is &T
//! but you have &const T or &mut T) and also for avoiding the linearity
//! of mut things (when the expected is &mut T and you have &mut T).  See
//! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
//! examples of where this is useful.
//!
//! ## Subtle note
//!
//! When deciding what type coercions to consider, we do not attempt to
//! resolve any type variables we may encounter.  This is because `b`
//! represents the expected type "as the user wrote it", meaning that if
//! the user defined a generic function like
//!
//!    fn foo<A>(a: A, b: A) { ... }
//!
//! and then we wrote `foo(&1, @2)`, we will not auto-borrow
//! either argument.  In older code we went to some lengths to
//! resolve the `b` variable, which could mean that we'd
//! auto-borrow later arguments but not earlier ones, which
//! seems very confusing.
//!
//! ## Subtler note
//!
//! However, right now, if the user manually specifies the
//! values for the type variables, as so:
//!
//!    foo::<&int>(@1, @2)
//!
//! then we *will* auto-borrow, because we can't distinguish this from a
//! function that declared `&int`.  This is inconsistent but it's easiest
//! at the moment. The right thing to do, I think, is to consider the
//! *unsubstituted* type when deciding whether to auto-borrow, but the
//! *substituted* type when considering the bounds and so forth. But most
//! of our methods don't give access to the unsubstituted type, and
//! rightly so because they'd be error-prone.  So maybe the thing to do is
//! to actually determine the kind of coercions that should occur
//! separately and pass them in.  Or maybe it's ok as is.  Anyway, it's
//! sort of a minor point so I've opted to leave it for later---after all
//! we may want to adjust precisely when coercions occur.
62

63
use check::{Diverges, FnCtxt};
64

65
use rustc::hir;
66
use rustc::hir::def_id::DefId;
67 68
use rustc::infer::{Coercion, InferResult, InferOk, TypeTrace};
use rustc::infer::type_variable::TypeVariableOrigin;
69
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
70
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
E
est31 已提交
71
use rustc::ty::{self, LvaluePreference, TypeAndMut,
72
                Ty, ClosureSubsts};
73 74
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
75
use rustc::ty::relate::RelateResult;
76
use rustc::ty::subst::Subst;
77
use errors::DiagnosticBuilder;
78
use syntax::abi;
E
est31 已提交
79
use syntax::feature_gate;
80
use syntax::ptr::P;
81

N
Nick Cameron 已提交
82
use std::collections::VecDeque;
83
use std::ops::Deref;
84

85
struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
86
    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
87
    cause: ObligationCause<'tcx>,
88
    use_lub: bool,
89 90
}

91 92 93 94 95 96 97
impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
    type Target = FnCtxt<'a, 'gcx, 'tcx>;
    fn deref(&self) -> &Self::Target {
        &self.fcx
    }
}

98
type CoerceResult<'tcx> = InferResult<'tcx, Adjustment<'tcx>>;
99 100 101 102 103 104 105 106

fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
                       to_mutbl: hir::Mutability)
                       -> RelateResult<'tcx, ()> {
    match (from_mutbl, to_mutbl) {
        (hir::MutMutable, hir::MutMutable) |
        (hir::MutImmutable, hir::MutImmutable) |
        (hir::MutMutable, hir::MutImmutable) => Ok(()),
107
        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability),
108 109
    }
}
110

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
fn identity<'tcx>() -> Adjust<'tcx> {
    Adjust::DerefRef {
        autoderefs: 0,
        autoref: None,
        unsize: false,
    }
}

fn success<'tcx>(kind: Adjust<'tcx>,
                 target: Ty<'tcx>,
                 obligations: traits::PredicateObligations<'tcx>)
                 -> CoerceResult<'tcx> {
    Ok(InferOk {
        value: Adjustment {
            kind,
            target
        },
        obligations
    })
}

132
impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
133
    fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
134 135
        Coerce {
            fcx: fcx,
136
            cause: cause,
137
            use_lub: false,
138 139 140
        }
    }

141
    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
142
        self.commit_if_ok(|_| {
143
            let trace = TypeTrace::types(&self.cause, false, a, b);
144
            if self.use_lub {
145
                self.lub(false, trace, &a, &b)
146
            } else {
147
                self.sub(false, trace, &a, &b)
148
            }
149 150 151
        })
    }

152 153 154 155 156 157
    /// Unify two types (using sub or lub) and produce a specific coercion.
    fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, kind: Adjust<'tcx>)
                 -> CoerceResult<'tcx> {
        self.unify(&a, &b).and_then(|InferOk { value: ty, obligations }| {
            success(kind, ty, obligations)
        })
158 159
    }

160 161 162 163 164
    fn coerce<E>(&self,
                 exprs: &[E],
                 a: Ty<'tcx>,
                 b: Ty<'tcx>)
                 -> CoerceResult<'tcx>
165
        where E: AsCoercionSite
166
    {
167
        let a = self.shallow_resolve(a);
168
        debug!("Coerce.tys({:?} => {:?})", a, b);
169 170 171

        // Just ignore error types.
        if a.references_error() || b.references_error() {
172
            return success(identity(), b, vec![]);
173 174
        }

A
Andrew Cann 已提交
175
        if a.is_never() {
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
            // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
            // type variable, we want `?T` to fallback to `!` if not
            // otherwise constrained. An example where this arises:
            //
            //     let _: Option<?T> = Some({ return; });
            //
            // here, we would coerce from `!` to `?T`.
            let b = self.shallow_resolve(b);
            return if self.shallow_resolve(b).is_ty_var() {
                // micro-optimization: no need for this if `b` is
                // already resolved in some way.
                let diverging_ty = self.next_diverging_ty_var(
                    TypeVariableOrigin::AdjustmentType(self.cause.span));
                self.unify_and(&b, &diverging_ty, Adjust::NeverToAny)
            } else {
                success(Adjust::NeverToAny, b, vec![])
            };
A
Andrew Cann 已提交
193 194
        }

N
Nick Cameron 已提交
195
        // Consider coercing the subtype to a DST
196
        let unsize = self.coerce_unsized(a, b);
N
Nick Cameron 已提交
197 198 199 200
        if unsize.is_ok() {
            return unsize;
        }

201 202 203 204
        // Examine the supertype and consider auto-borrowing.
        //
        // Note: does not attempt to resolve type variables we encounter.
        // See above for details.
205
        match b.sty {
206
            ty::TyRawPtr(mt_b) => {
207
                return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
208 209
            }

210
            ty::TyRef(r_b, mt_b) => {
211
                return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
212 213
            }

214 215
            _ => {}
        }
216

217
        match a.sty {
V
Vadim Petrochenkov 已提交
218
            ty::TyFnDef(.., a_f) => {
219 220 221
                // Function items are coercible to any closure
                // type; function pointers are not (that would
                // require double indirection).
T
Taylor Cramer 已提交
222
                // Additionally, we permit coercion of function
223
                // items to drop the unsafe qualifier.
224
                self.coerce_from_fn_item(a, a_f, b)
225
            }
226
            ty::TyFnPtr(a_f) => {
227 228 229 230
                // We permit coercion of fn pointers to drop the
                // unsafe qualifier.
                self.coerce_from_fn_pointer(a, a_f, b)
            }
231 232 233 234 235
            ty::TyClosure(def_id_a, substs_a) => {
                // Non-capturing closures are coercible to
                // function pointers
                self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
            }
236
            _ => {
237
                // Otherwise, just use unification rules.
238
                self.unify_and(a, b, identity())
239 240
            }
        }
241 242
    }

243 244 245
    /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
    /// To match `A` with `B`, autoderef will be performed,
    /// calling `deref`/`deref_mut` where necessary.
246 247 248 249 250 251 252 253
    fn coerce_borrowed_pointer<E>(&self,
                                  exprs: &[E],
                                  a: Ty<'tcx>,
                                  b: Ty<'tcx>,
                                  r_b: &'tcx ty::Region,
                                  mt_b: TypeAndMut<'tcx>)
                                  -> CoerceResult<'tcx>
        where E: AsCoercionSite
254
    {
255 256

        debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
257

258 259 260 261 262 263
        // If we have a parameter of type `&M T_a` and the value
        // provided is `expr`, we will be adding an implicit borrow,
        // meaning that we convert `f(expr)` to `f(&M *expr)`.  Therefore,
        // to type check, we will construct the type that `&M*expr` would
        // yield.

N
Niko Matsakis 已提交
264
        let (r_a, mt_a) = match a.sty {
265
            ty::TyRef(r_a, mt_a) => {
J
Jorge Aparicio 已提交
266
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Niko Matsakis 已提交
267
                (r_a, mt_a)
S
Seo Sanghyeon 已提交
268
            }
269
            _ => return self.unify_and(a, b, identity()),
270
        };
271

272
        let span = self.cause.span;
273

274
        let mut first_error = None;
275
        let mut r_borrow_var = None;
276
        let mut autoderef = self.autoderef(span, a);
277
        let mut found = None;
278 279 280

        for (referent_ty, autoderefs) in autoderef.by_ref() {
            if autoderefs == 0 {
281 282
                // Don't let this pass, otherwise it would cause
                // &T to autoref to &&T.
283
                continue;
284
            }
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

            // At this point, we have deref'd `a` to `referent_ty`.  So
            // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
            // In the autoderef loop for `&'a mut Vec<T>`, we would get
            // three callbacks:
            //
            // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
            // - `Vec<T>` -- 1 deref
            // - `[T]` -- 2 deref
            //
            // At each point after the first callback, we want to
            // check to see whether this would match out target type
            // (`&'b mut [T]`) if we autoref'd it. We can't just
            // compare the referent types, though, because we still
            // have to consider the mutability. E.g., in the case
            // we've been considering, we have an `&mut` reference, so
            // the `T` in `[T]` needs to be unified with equality.
            //
            // Therefore, we construct reference types reflecting what
            // the types will be after we do the final auto-ref and
            // compare those. Note that this means we use the target
            // mutability [1], since it may be that we are coercing
            // from `&mut T` to `&U`.
            //
309
            // One fine point concerns the region that we use. We
310 311 312 313
            // choose the region such that the region of the final
            // type that results from `unify` will be the region we
            // want for the autoref:
            //
314 315 316
            // - if in sub mode, that means we want to use `'b` (the
            //   region from the target reference) for both
            //   pointers [2]. This is because sub mode (somewhat
317 318 319 320 321
            //   arbitrarily) returns the subtype region.  In the case
            //   where we are coercing to a target type, we know we
            //   want to use that target type region (`'b`) because --
            //   for the program to type-check -- it must be the
            //   smaller of the two.
322 323 324 325 326 327 328 329
            //   - One fine point. It may be surprising that we can
            //     use `'b` without relating `'a` and `'b`. The reason
            //     that this is ok is that what we produce is
            //     effectively a `&'b *x` expression (if you could
            //     annotate the region of a borrow), and regionck has
            //     code that adds edges from the region of a borrow
            //     (`'b`, here) into the regions in the borrowed
            //     expression (`*x`, here).  (Search for "link".)
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
            // - if in lub mode, things can get fairly complicated. The
            //   easiest thing is just to make a fresh
            //   region variable [4], which effectively means we defer
            //   the decision to region inference (and regionck, which will add
            //   some more edges to this variable). However, this can wind up
            //   creating a crippling number of variables in some cases --
            //   e.g. #32278 -- so we optimize one particular case [3].
            //   Let me try to explain with some examples:
            //   - The "running example" above represents the simple case,
            //     where we have one `&` reference at the outer level and
            //     ownership all the rest of the way down. In this case,
            //     we want `LUB('a, 'b)` as the resulting region.
            //   - However, if there are nested borrows, that region is
            //     too strong. Consider a coercion from `&'a &'x Rc<T>` to
            //     `&'b T`. In this case, `'a` is actually irrelevant.
            //     The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
            //     we get spurious errors (`run-pass/regions-lub-ref-ref-rc.rs`).
            //     (The errors actually show up in borrowck, typically, because
            //     this extra edge causes the region `'a` to be inferred to something
            //     too big, which then results in borrowck errors.)
            //   - We could track the innermost shared reference, but there is already
            //     code in regionck that has the job of creating links between
            //     the region of a borrow and the regions in the thing being
            //     borrowed (here, `'a` and `'x`), and it knows how to handle
            //     all the various cases. So instead we just make a region variable
            //     and let regionck figure it out.
            let r = if !self.use_lub {
                r_b // [2] above
358
            } else if autoderefs == 1 {
359 360
                r_a // [3] above
            } else {
361 362
                if r_borrow_var.is_none() {
                    // create var lazilly, at most once
363
                    let coercion = Coercion(span);
364
                    let r = self.next_region_var(coercion);
365
                    r_borrow_var = Some(r); // [4] above
366 367 368
                }
                r_borrow_var.unwrap()
            };
369 370 371 372 373
            let derefd_ty_a = self.tcx.mk_ref(r,
                                              TypeAndMut {
                                                  ty: referent_ty,
                                                  mutbl: mt_b.mutbl, // [1] above
                                              });
374
            match self.unify(derefd_ty_a, b) {
375 376
                Ok(ok) => {
                    found = Some((ok, autoderefs));
377 378
                    break;
                }
379 380 381 382
                Err(err) => {
                    if first_error.is_none() {
                        first_error = Some(err);
                    }
383 384
                }
            }
385
        }
386

387 388 389 390 391
        // Extract type or return an error. We return the first error
        // we got, which should be from relating the "base" type
        // (e.g., in example above, the failure from relating `Vec<T>`
        // to the target type), since that should be the least
        // confusing.
392
        let (InferOk { value: ty, mut obligations }, autoderefs) = match found {
393
            Some(d) => d,
394
            None => {
395 396 397
                let err = first_error.expect("coerce_borrowed_pointer had no error");
                debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
                return Err(err);
398
            }
399 400
        };

N
Niko Matsakis 已提交
401 402 403 404 405 406 407 408 409 410 411 412
        if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
            // As a special case, if we would produce `&'a *x`, that's
            // a total no-op. We end up with the type `&'a T` just as
            // we started with.  In that case, just skip it
            // altogether. This is just an optimization.
            //
            // Note that for `&mut`, we DO want to reborrow --
            // otherwise, this would be a move, which might be an
            // error. For example `foo(self.x)` where `self` and
            // `self.x` both have `&mut `type would be a move of
            // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
            // which is a borrow.
413
            assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
414
            return success(identity(), ty, obligations);
N
Niko Matsakis 已提交
415
        }
416 417 418

        // Now apply the autoref. We have to extract the region out of
        // the final ref type we got.
419
        let r_borrow = match ty.sty {
420
            ty::TyRef(r_borrow, _) => r_borrow,
421
            _ => span_bug!(span, "expected a ref type, got {:?}", ty),
422
        };
423
        let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl));
424
        debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
425 426 427
               ty,
               autoderefs,
               autoref);
428 429

        let pref = LvaluePreference::from_mutbl(mt_b.mutbl);
430
        obligations.extend(autoderef.finalize_as_infer_ok(pref, exprs).obligations);
431 432

        success(Adjust::DerefRef {
433 434 435
            autoderefs: autoderefs,
            autoref: autoref,
            unsize: false,
436
        }, ty, obligations)
437 438 439
    }


440 441
    // &[T; n] or &mut [T; n] -> &[T]
    // or &mut [T; n] -> &mut [T]
N
Nick Cameron 已提交
442
    // or &Concrete -> &Trait, etc.
443 444
    fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> {
        debug!("coerce_unsized(source={:?}, target={:?})", source, target);
N
Nick Cameron 已提交
445

446 447
        let traits = (self.tcx.lang_items.unsize_trait(),
                      self.tcx.lang_items.coerce_unsized_trait());
N
Nick Cameron 已提交
448 449 450 451
        let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
            (u, cu)
        } else {
            debug!("Missing Unsize or CoerceUnsized traits");
452
            return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
453
        };
454

N
Nick Cameron 已提交
455 456 457
        // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
        // a DST unless we have to. This currently comes out in the wash since
        // we can't unify [T] with U. But to properly support DST, we need to allow
N
Nick Cameron 已提交
458
        // that, at which point we will need extra checks on the target here.
N
Nick Cameron 已提交
459

N
Nick Cameron 已提交
460 461
        // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
        let (source, reborrow) = match (&source.sty, &target.sty) {
462
            (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
J
Jorge Aparicio 已提交
463
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Nick Cameron 已提交
464

465
                let coercion = Coercion(self.cause.span);
466
                let r_borrow = self.next_region_var(coercion);
467
                (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl)))
468
            }
469
            (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
J
Jorge Aparicio 已提交
470
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
471
                (mt_a.ty, Some(AutoBorrow::RawPtr(mt_b.mutbl)))
472
            }
473
            _ => (source, None),
N
Nick Cameron 已提交
474
        };
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
        let coerce_source = source.adjust_for_autoref(self.tcx, reborrow);

        let adjust = Adjust::DerefRef {
            autoderefs: if reborrow.is_some() { 1 } else { 0 },
            autoref: reborrow,
            unsize: true,
        };

        // Setup either a subtyping or a LUB relationship between
        // the `CoerceUnsized` target type and the expected type.
        // We only have the latter, so we use an inference variable
        // for the former and let type inference do the rest.
        let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
        let coerce_target = self.next_ty_var(origin);
        let mut coercion = self.unify_and(coerce_target, target, adjust)?;
N
Nick Cameron 已提交
490

491
        let mut selcx = traits::SelectionContext::new(self);
N
Nick Cameron 已提交
492 493 494 495 496

        // Use a FIFO queue for this custom fulfillment procedure.
        let mut queue = VecDeque::new();

        // Create an obligation for `Source: CoerceUnsized<Target>`.
497
        let cause = ObligationCause::misc(self.cause.span, self.body_id);
498
        queue.push_back(self.tcx
499 500
            .predicate_for_trait_def(cause, coerce_unsized_did, 0,
                                     coerce_source, &[coerce_target]));
N
Nick Cameron 已提交
501 502 503 504 505 506

        // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
        // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
        // inference might unify those two inner type variables later.
        let traits = [coerce_unsized_did, unsize_did];
        while let Some(obligation) = queue.pop_front() {
507
            debug!("coerce_unsized resolve step: {:?}", obligation);
508 509
            let trait_ref = match obligation.predicate {
                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
N
Nick Cameron 已提交
510
                _ => {
511
                    coercion.obligations.push(obligation);
N
Nick Cameron 已提交
512 513 514 515 516
                    continue;
                }
            };
            match selcx.select(&obligation.with(trait_ref)) {
                // Uncertain or unimplemented.
517 518
                Ok(None) |
                Err(traits::Unimplemented) => {
N
Nick Cameron 已提交
519
                    debug!("coerce_unsized: early return - can't prove obligation");
520
                    return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
521
                }
N
Nick Cameron 已提交
522 523 524

                // Object safety violations or miscellaneous.
                Err(err) => {
525
                    self.report_selection_error(&obligation, &err);
N
Nick Cameron 已提交
526 527 528 529 530 531
                    // Treat this like an obligation and follow through
                    // with the unsizing - the lack of a coercion should
                    // be silent, as it causes a type mismatch later.
                }

                Ok(Some(vtable)) => {
532 533 534
                    for obligation in vtable.nested_obligations() {
                        queue.push_back(obligation);
                    }
N
Nick Cameron 已提交
535
                }
N
Nick Cameron 已提交
536
            }
N
Nick Cameron 已提交
537 538
        }

539
        Ok(coercion)
N
Nick Cameron 已提交
540
    }
541

542 543
    fn coerce_from_safe_fn(&self,
                           a: Ty<'tcx>,
544
                           fn_ty_a: ty::PolyFnSig<'tcx>,
545 546 547
                           b: Ty<'tcx>,
                           to_unsafe: Adjust<'tcx>,
                           normal: Adjust<'tcx>)
548 549
                           -> CoerceResult<'tcx> {
        if let ty::TyFnPtr(fn_ty_b) = b.sty {
550
            match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
551 552
                (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                    let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
553
                    return self.unify_and(unsafe_a, b, to_unsafe);
554 555 556 557
                }
                _ => {}
            }
        }
558
        self.unify_and(a, b, normal)
559 560
    }

561
    fn coerce_from_fn_pointer(&self,
562
                              a: Ty<'tcx>,
563
                              fn_ty_a: ty::PolyFnSig<'tcx>,
564 565 566 567 568
                              b: Ty<'tcx>)
                              -> CoerceResult<'tcx> {
        //! Attempts to coerce from the type of a Rust function item
        //! into a closure or a `proc`.
        //!
569

570
        let b = self.shallow_resolve(b);
571
        debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
572

573 574
        self.coerce_from_safe_fn(a, fn_ty_a, b,
            Adjust::UnsafeFnPointer, identity())
575 576
    }

577 578
    fn coerce_from_fn_item(&self,
                           a: Ty<'tcx>,
579
                           fn_ty_a: ty::PolyFnSig<'tcx>,
580
                           b: Ty<'tcx>)
581
                           -> CoerceResult<'tcx> {
582 583 584
        //! Attempts to coerce from the type of a Rust function item
        //! into a closure or a `proc`.
        //!
585

586
        let b = self.shallow_resolve(b);
587
        debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
588

589 590
        match b.sty {
            ty::TyFnPtr(_) => {
591
                let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
592 593
                self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b,
                    Adjust::ReifyFnPointer, Adjust::ReifyFnPointer)
594
            }
595
            _ => self.unify_and(a, b, identity()),
596
        }
597 598
    }

599 600 601 602 603 604 605 606 607 608 609 610
    fn coerce_closure_to_fn(&self,
                           a: Ty<'tcx>,
                           def_id_a: DefId,
                           substs_a: ClosureSubsts<'tcx>,
                           b: Ty<'tcx>)
                           -> CoerceResult<'tcx> {
        //! Attempts to coerce from the type of a non-capturing closure
        //! into a function pointer.
        //!

        let b = self.shallow_resolve(b);

E
est31 已提交
611
        let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap();
612 613
        match b.sty {
            ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
E
est31 已提交
614 615 616 617 618 619
                if !self.tcx.sess.features.borrow().closure_to_fn_coercion {
                    feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
                                                   "closure_to_fn_coercion",
                                                   self.cause.span,
                                                   feature_gate::GateIssue::Language,
                                                   feature_gate::CLOSURE_TO_FN_COERCION);
620
                    return self.unify_and(a, b, identity());
E
est31 已提交
621
                }
622 623 624 625
                // We coerce the closure, which has fn type
                //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                // to
                //     `fn(arg0,arg1,...) -> _`
626
                let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
E
est31 已提交
627 628 629
                let converted_sig = sig.map_bound(|s| {
                    let params_iter = match s.inputs()[0].sty {
                        ty::TyTuple(params, _) => {
630 631 632 633
                            params.into_iter().cloned()
                        }
                        _ => bug!(),
                    };
634 635 636 637 638 639 640
                    self.tcx.mk_fn_sig(
                        params_iter,
                        s.output(),
                        s.variadic,
                        hir::Unsafety::Normal,
                        abi::Abi::Rust
                    )
641
                });
642
                let pointer_ty = self.tcx.mk_fn_ptr(converted_sig);
643 644
                debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                       a, b, pointer_ty);
645
                self.unify_and(pointer_ty, b, Adjust::ClosureFnPointer)
646
            }
647
            _ => self.unify_and(a, b, identity()),
648 649 650
        }
    }

651 652 653
    fn coerce_unsafe_ptr(&self,
                         a: Ty<'tcx>,
                         b: Ty<'tcx>,
654
                         mutbl_b: hir::Mutability)
655
                         -> CoerceResult<'tcx> {
656
        debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
657

658 659 660
        let (is_ref, mt_a) = match a.sty {
            ty::TyRef(_, mt) => (true, mt),
            ty::TyRawPtr(mt) => (false, mt),
661
            _ => {
662
                return self.unify_and(a, b, identity());
663 664 665
            }
        };

666
        // Check that the types which they point at are compatible.
667 668 669 670
        let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut {
            mutbl: mutbl_b,
            ty: mt_a.ty,
        });
J
Jorge Aparicio 已提交
671
        coerce_mutbls(mt_a.mutbl, mutbl_b)?;
672
        // Although references and unsafe ptrs have the same
673
        // representation, we still register an Adjust::DerefRef so that
674
        // regionck knows that the region for `a` must be valid here.
675 676 677 678 679 680 681 682 683 684 685
        self.unify_and(a_unsafe, b, if is_ref {
            Adjust::DerefRef {
                autoderefs: 1,
                autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
                unsize: false,
            }
        } else if mt_a.mutbl != mutbl_b {
            Adjust::MutToConstPointer
        } else {
            identity()
        })
686
    }
687 688
}

689
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
690 691 692 693 694 695
    /// Attempt to coerce an expression to a type, and return the
    /// adjusted type of the expression, if successful.
    /// Adjustments are only recorded if the coercion succeeded.
    /// The expressions *must not* have any pre-existing adjustments.
    pub fn try_coerce(&self,
                      expr: &hir::Expr,
696
                      expr_ty: Ty<'tcx>,
697
                      expr_diverges: Diverges,
698 699
                      target: Ty<'tcx>)
                      -> RelateResult<'tcx, Ty<'tcx>> {
700
        let source = self.resolve_type_vars_with_obligations(expr_ty);
701
        debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
702

703 704 705 706 707 708 709
        // Special-ish case: we can coerce any type `T` into the `!`
        // type, but only if the source expression diverges.
        if target.is_never() && expr_diverges.always() {
            debug!("permit coercion to `!` because expr diverges");
            return Ok(target);
        }

710
        let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
711
        let coerce = Coerce::new(self, cause);
712
        self.commit_if_ok(|_| {
713
            let ok = coerce.coerce(&[expr], source, target)?;
714
            let adjustment = self.register_infer_ok_obligations(ok);
715 716
            if !adjustment.is_identity() {
                debug!("Success, coerced with {:?}", adjustment);
717 718 719
                if self.tables.borrow().adjustments.get(&expr.id).is_some() {
                    bug!("expr already has an adjustment on it!");
                }
720
                self.write_adjustment(expr.id, adjustment);
721
            }
722 723 724 725 726

            // We should now have added sufficient adjustments etc to
            // ensure that the type of expression, post-adjustment, is
            // a subtype of target.
            Ok(target)
727
        })
728 729
    }

730 731 732
    /// Given some expressions, their known unified type and another expression,
    /// tries to unify the types, potentially inserting coercions on any of the
    /// provided expressions and returns their LUB (aka "common supertype").
733 734 735
    ///
    /// This is really an internal helper. From outside the coercion
    /// module, you should instantiate a `CoerceMany` instance.
736 737 738 739 740
    fn try_find_coercion_lub<E>(&self,
                                cause: &ObligationCause<'tcx>,
                                exprs: &[E],
                                prev_ty: Ty<'tcx>,
                                new: &hir::Expr,
741 742
                                new_ty: Ty<'tcx>,
                                new_diverges: Diverges)
743 744
                                -> RelateResult<'tcx, Ty<'tcx>>
        where E: AsCoercionSite
745
    {
746
        let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
747
        let new_ty = self.resolve_type_vars_with_obligations(new_ty);
748
        debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
749

750 751 752 753 754 755 756
        // Special-ish case: we can coerce any type `T` into the `!`
        // type, but only if the source expression diverges.
        if prev_ty.is_never() && new_diverges.always() {
            debug!("permit coercion to `!` because expr diverges");
            return Ok(prev_ty);
        }

757
        let trace = TypeTrace::types(cause, true, prev_ty, new_ty);
758

759 760 761
        // Special-case that coercion alone cannot handle:
        // Two function item types of differing IDs or Substs.
        match (&prev_ty.sty, &new_ty.sty) {
762
            (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
763 764
                // The signature must always match.
                let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
765
                              .map(|ok| self.register_infer_ok_obligations(ok))?;
766 767 768 769 770

                if a_def_id == b_def_id {
                    // Same function, maybe the parameters match.
                    let substs = self.commit_if_ok(|_| {
                        self.lub(true, trace.clone(), &a_substs, &b_substs)
771
                            .map(|ok| self.register_infer_ok_obligations(ok))
772 773 774 775 776 777 778 779 780
                    });

                    if let Ok(substs) = substs {
                        // We have a LUB of prev_ty and new_ty, just return it.
                        return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
                    }
                }

                // Reify both sides and return the reified fn pointer type.
781
                let fn_ptr = self.tcx.mk_fn_ptr(fty);
782
                for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
783 784
                    // No adjustments can produce a fn item, so this should never trip.
                    assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
785 786 787 788
                    self.write_adjustment(expr.id, Adjustment {
                        kind: Adjust::ReifyFnPointer,
                        target: fn_ptr
                    });
789
                }
790
                return Ok(fn_ptr);
791 792 793 794
            }
            _ => {}
        }

795
        let mut coerce = Coerce::new(self, cause.clone());
796 797 798 799 800 801
        coerce.use_lub = true;

        // First try to coerce the new expression to the type of the previous ones,
        // but only if the new expression has no coercion already applied to it.
        let mut first_error = None;
        if !self.tables.borrow().adjustments.contains_key(&new.id) {
802
            let result = self.commit_if_ok(|_| coerce.coerce(&[new], new_ty, prev_ty));
803
            match result {
804 805
                Ok(ok) => {
                    let adjustment = self.register_infer_ok_obligations(ok);
806 807 808
                    if !adjustment.is_identity() {
                        self.write_adjustment(new.id, adjustment);
                    }
809
                    return Ok(adjustment.target);
810
                }
811
                Err(e) => first_error = Some(e),
812
            }
813 814
        }

815 816 817
        // Then try to coerce the previous expressions to the type of the new one.
        // This requires ensuring there are no coercions applied to *any* of the
        // previous expressions, other than noop reborrows (ignoring lifetimes).
818 819
        for expr in exprs {
            let expr = expr.as_coercion_site();
820 821 822 823 824 825
            let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) {
                Some(Adjust::DerefRef {
                    autoderefs: 1,
                    autoref: Some(AutoBorrow::Ref(_, mutbl_adj)),
                    unsize: false
                }) => {
826 827 828 829 830 831
                    match self.node_ty(expr.id).sty {
                        ty::TyRef(_, mt_orig) => {
                            // Reborrow that we can safely ignore.
                            mutbl_adj == mt_orig.mutbl
                        }
                        _ => false,
832
                    }
833
                }
834
                Some(Adjust::NeverToAny) => true,
835
                Some(_) => false,
836
                None => true,
837 838 839 840 841
            };

            if !noop {
                return self.commit_if_ok(|_| {
                    self.lub(true, trace.clone(), &prev_ty, &new_ty)
842
                        .map(|ok| self.register_infer_ok_obligations(ok))
843
                });
844 845
            }
        }
846

847
        match self.commit_if_ok(|_| coerce.coerce(&exprs, prev_ty, new_ty)) {
848 849 850 851 852 853 854
            Err(_) => {
                // Avoid giving strange errors on failed attempts.
                if let Some(e) = first_error {
                    Err(e)
                } else {
                    self.commit_if_ok(|_| {
                        self.lub(true, trace, &prev_ty, &new_ty)
855
                            .map(|ok| self.register_infer_ok_obligations(ok))
856
                    })
857 858
                }
            }
859 860
            Ok(ok) => {
                let adjustment = self.register_infer_ok_obligations(ok);
861
                if !adjustment.is_identity() {
862
                    let mut tables = self.tables.borrow_mut();
863 864
                    for expr in exprs {
                        let expr = expr.as_coercion_site();
865 866 867 868 869 870
                        if let Some(&mut Adjustment {
                            kind: Adjust::NeverToAny,
                            ref mut target
                        }) = tables.adjustments.get_mut(&expr.id) {
                            *target = adjustment.target;
                            continue;
871
                        }
872
                        tables.adjustments.insert(expr.id, adjustment);
873 874
                    }
                }
875
                Ok(adjustment.target)
876
            }
877
        }
878 879
    }
}
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

/// CoerceMany encapsulates the pattern you should use when you have
/// many expressions that are all getting coerced to a common
/// type. This arises, for example, when you have a match (the result
/// of each arm is coerced to a common type). It also arises in less
/// obvious places, such as when you have many `break foo` expressions
/// that target the same loop, or the various `return` expressions in
/// a function.
///
/// The basic protocol is as follows:
///
/// - Instantiate the `CoerceMany` with an initial `expected_ty`.
///   This will also serve as the "starting LUB". The expectation is
///   that this type is something which all of the expressions *must*
///   be coercible to. Use a fresh type variable if needed.
/// - For each expression whose result is to be coerced, invoke `coerce()` with.
///   - In some cases we wish to coerce "non-expressions" whose types are implicitly
///     unit. This happens for example if you have a `break` with no expression,
///     or an `if` with no `else`. In that case, invoke `coerce_forced_unit()`.
///   - `coerce()` and `coerce_forced_unit()` may report errors. They hide this
///     from you so that you don't have to worry your pretty head about it.
///     But if an error is reported, the final type will be `err`.
///   - Invoking `coerce()` may cause us to go and adjust the "adjustments" on
///     previously coerced expressions.
/// - When all done, invoke `complete()`. This will return the LUB of
///   all your expressions.
///   - WARNING: I don't believe this final type is guaranteed to be
///     related to your initial `expected_ty` in any particular way,
///     although it will typically be a subtype, so you should check it.
///   - Invoking `complete()` may cause us to go and adjust the "adjustments" on
///     previously coerced expressions.
///
/// Example:
///
/// ```
/// let mut coerce = CoerceMany::new(expected_ty);
/// for expr in exprs {
///     let expr_ty = fcx.check_expr_with_expectation(expr, expected);
///     coerce.coerce(fcx, &cause, expr, expr_ty);
/// }
/// let final_ty = coerce.complete(fcx);
/// ```
922 923 924
pub struct CoerceMany<'gcx, 'tcx, 'exprs, E>
    where 'gcx: 'tcx, E: 'exprs + AsCoercionSite,
{
925 926
    expected_ty: Ty<'tcx>,
    final_ty: Option<Ty<'tcx>>,
927 928 929 930 931 932
    expressions: Expressions<'gcx, 'exprs, E>,
    pushed: usize,
}

/// The type of a `CoerceMany` that is storing up the expressions into
/// a buffer. We use this in `check/mod.rs` for things like `break`.
933
pub type DynamicCoerceMany<'gcx, 'tcx> = CoerceMany<'gcx, 'tcx, 'gcx, P<hir::Expr>>;
934 935 936 937 938 939

enum Expressions<'gcx, 'exprs, E>
    where E: 'exprs + AsCoercionSite,
{
    Dynamic(Vec<&'gcx hir::Expr>),
    UpFront(&'exprs [E]),
940 941
}

942 943 944 945 946 947
impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
    where 'gcx: 'tcx, E: 'exprs + AsCoercionSite,
{
    /// The usual case; collect the set of expressions dynamically.
    /// If the full set of coercion sites is known before hand,
    /// consider `with_coercion_sites()` instead to avoid allocation.
948
    pub fn new(expected_ty: Ty<'tcx>) -> Self {
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
        Self::make(expected_ty, Expressions::Dynamic(vec![]))
    }

    /// As an optimization, you can create a `CoerceMany` with a
    /// pre-existing slice of expressions. In this case, you are
    /// expected to pass each element in the slice to `coerce(...)` in
    /// order. This is used with arrays in particular to avoid
    /// needlessly cloning the slice.
    pub fn with_coercion_sites(expected_ty: Ty<'tcx>,
                               coercion_sites: &'exprs [E])
                      -> Self {
        Self::make(expected_ty, Expressions::UpFront(coercion_sites))
    }

    fn make(expected_ty: Ty<'tcx>, expressions: Expressions<'gcx, 'exprs, E>) -> Self {
964 965 966
        CoerceMany {
            expected_ty,
            final_ty: None,
967 968
            expressions,
            pushed: 0,
969 970 971 972
        }
    }

    pub fn is_empty(&self) -> bool {
973
        self.pushed == 0
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
    }

    /// Return the "expected type" with which this coercion was
    /// constructed.  This represents the "downward propagated" type
    /// that was given to us at the start of typing whatever construct
    /// we are typing (e.g., the match expression).
    ///
    /// Typically, this is used as the expected type when
    /// type-checking each of the alternative expressions whose types
    /// we are trying to merge.
    pub fn expected_ty(&self) -> Ty<'tcx> {
        self.expected_ty
    }

    /// Returns the current "merged type", representing our best-guess
    /// at the LUB of the expressions we've seen so far (if any). This
    /// isn't *final* until you call `self.final()`, which will return
    /// the merged type.
    pub fn merged_ty(&self) -> Ty<'tcx> {
        self.final_ty.unwrap_or(self.expected_ty)
    }

    /// Indicates that the value generated by `expression`, which is
    /// of type `expression_ty`, is one of the possibility that we
    /// could coerce from. This will record `expression` and later
    /// calls to `coerce` may come back and add adjustments and things
    /// if necessary.
    pub fn coerce<'a>(&mut self,
                      fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                      cause: &ObligationCause<'tcx>,
                      expression: &'gcx hir::Expr,
1005 1006
                      expression_ty: Ty<'tcx>,
                      expression_diverges: Diverges)
1007
    {
1008
        self.coerce_inner(fcx, cause, Some(expression), expression_ty, expression_diverges, None)
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
    }

    /// Indicates that one of the inputs is a "forced unit". This
    /// occurs in a case like `if foo { ... };`, where the issing else
    /// generates a "forced unit". Another example is a `loop { break;
    /// }`, where the `break` has no argument expression. We treat
    /// these cases slightly differently for error-reporting
    /// purposes. Note that these tend to correspond to cases where
    /// the `()` expression is implicit in the source, and hence we do
    /// not take an expression argument.
1019 1020 1021 1022
    ///
    /// The `augment_error` gives you a chance to extend the error
    /// message, in case any results (e.g., we use this to suggest
    /// removing a `;`).
1023 1024
    pub fn coerce_forced_unit<'a>(&mut self,
                                  fcx: &FnCtxt<'a, 'gcx, 'tcx>,
1025 1026
                                  cause: &ObligationCause<'tcx>,
                                  augment_error: &mut FnMut(&mut DiagnosticBuilder))
1027 1028 1029 1030
    {
        self.coerce_inner(fcx,
                          cause,
                          None,
1031
                          fcx.tcx.mk_nil(),
1032 1033
                          Diverges::Maybe,
                          Some(augment_error))
1034 1035 1036 1037 1038 1039 1040 1041 1042
    }

    /// The inner coercion "engine". If `expression` is `None`, this
    /// is a forced-unit case, and hence `expression_ty` must be
    /// `Nil`.
    fn coerce_inner<'a>(&mut self,
                        fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                        cause: &ObligationCause<'tcx>,
                        expression: Option<&'gcx hir::Expr>,
1043
                        mut expression_ty: Ty<'tcx>,
1044 1045
                        expression_diverges: Diverges,
                        augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>)
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
    {
        // Incorporate whatever type inference information we have
        // until now; in principle we might also want to process
        // pending obligations, but doing so should only improve
        // compatibility (hopefully that is true) by helping us
        // uncover never types better.
        if expression_ty.is_ty_var() {
            expression_ty = fcx.infcx.shallow_resolve(expression_ty);
        }

        // If we see any error types, just propagate that error
        // upwards.
        if expression_ty.references_error() || self.merged_ty().references_error() {
            self.final_ty = Some(fcx.tcx.types.err);
            return;
        }

        // Handle the actual type unification etc.
        let result = if let Some(expression) = expression {
1065
            if self.pushed == 0 {
1066 1067
                // Special-case the first expression we are coercing.
                // To be honest, I'm not entirely sure why we do this.
1068
                fcx.try_coerce(expression, expression_ty, expression_diverges, self.expected_ty)
1069
            } else {
1070 1071 1072 1073 1074 1075
                match self.expressions {
                    Expressions::Dynamic(ref exprs) =>
                        fcx.try_find_coercion_lub(cause,
                                                  exprs,
                                                  self.merged_ty(),
                                                  expression,
1076 1077
                                                  expression_ty,
                                                  expression_diverges),
1078 1079 1080 1081 1082
                    Expressions::UpFront(ref coercion_sites) =>
                        fcx.try_find_coercion_lub(cause,
                                                  &coercion_sites[0..self.pushed],
                                                  self.merged_ty(),
                                                  expression,
1083 1084
                                                  expression_ty,
                                                  expression_diverges),
1085
                }
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
            }
        } else {
            // this is a hack for cases where we default to `()` because
            // the expression etc has been omitted from the source. An
            // example is an `if let` without an else:
            //
            //     if let Some(x) = ... { }
            //
            // we wind up with a second match arm that is like `_ =>
            // ()`.  That is the case we are considering here. We take
            // a different path to get the right "expected, found"
            // message and so forth (and because we know that
            // `expression_ty` will be unit).
            //
            // Another example is `break` with no argument expression.
            assert!(expression_ty.is_nil());
            assert!(expression_ty.is_nil(), "if let hack without unit type");
            fcx.eq_types(true, cause, expression_ty, self.merged_ty())
               .map(|infer_ok| {
                   fcx.register_infer_ok_obligations(infer_ok);
                   expression_ty
               })
        };

        match result {
            Ok(v) => {
                self.final_ty = Some(v);
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
                if let Some(e) = expression {
                    match self.expressions {
                        Expressions::Dynamic(ref mut buffer) => buffer.push(e),
                        Expressions::UpFront(coercion_sites) => {
                            // if the user gave us an array to validate, check that we got
                            // the next expression in the list, as expected
                            assert_eq!(coercion_sites[self.pushed].as_coercion_site().id, e.id);
                        }
                    }
                    self.pushed += 1;
                }
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
            }
            Err(err) => {
                let (expected, found) = if expression.is_none() {
                    // In the case where this is a "forced unit", like
                    // `break`, we want to call the `()` "expected"
                    // since it is implied by the syntax.
                    assert!(expression_ty.is_nil());
                    (expression_ty, self.final_ty.unwrap_or(self.expected_ty))
                } else {
                    // Otherwise, the "expected" type for error
                    // reporting is the current unification type,
                    // which is basically the LUB of the expressions
                    // we've seen so far (combined with the expected
                    // type)
                    (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                };

1141
                let mut db;
1142 1143
                match cause.code {
                    ObligationCauseCode::ReturnNoExpression => {
1144 1145 1146 1147
                        db = struct_span_err!(
                            fcx.tcx.sess, cause.span, E0069,
                            "`return;` in a function whose return type is not `()`");
                        db.span_label(cause.span, &format!("return type is not ()"));
1148 1149
                    }
                    _ => {
1150
                        db = fcx.report_mismatched_types(cause, expected, found, err);
1151 1152 1153
                    }
                }

1154 1155 1156 1157 1158 1159
                if let Some(mut augment_error) = augment_error {
                    augment_error(&mut db);
                }

                db.emit();

1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
                self.final_ty = Some(fcx.tcx.types.err);
            }
        }
    }

    pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
        if let Some(final_ty) = self.final_ty {
            final_ty
        } else {
            // If we only had inputs that were of type `!` (or no
            // inputs at all), then the final type is `!`.
1171
            assert_eq!(self.pushed, 0);
1172 1173 1174 1175
            fcx.tcx.types.never
        }
    }
}
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213

/// Something that can be converted into an expression to which we can
/// apply a coercion.
pub trait AsCoercionSite {
    fn as_coercion_site(&self) -> &hir::Expr;
}

impl AsCoercionSite for hir::Expr {
    fn as_coercion_site(&self) -> &hir::Expr {
        self
    }
}

impl AsCoercionSite for P<hir::Expr> {
    fn as_coercion_site(&self) -> &hir::Expr {
        self
    }
}

impl<'a, T> AsCoercionSite for &'a T
    where T: AsCoercionSite
{
    fn as_coercion_site(&self) -> &hir::Expr {
        (**self).as_coercion_site()
    }
}

impl AsCoercionSite for ! {
    fn as_coercion_site(&self) -> &hir::Expr {
        unreachable!()
    }
}

impl AsCoercionSite for hir::Arm {
    fn as_coercion_site(&self) -> &hir::Expr {
        &self.body
    }
}