coercion.rs 52.5 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
use rustc::infer::{Coercion, InferResult, InferOk};
G
Guillaume Gomez 已提交
68 69
use rustc::infer::type_variable::TypeVariableOrigin;
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;
79
use syntax::feature_gate;
80
use syntax::ptr::P;
81
use syntax_pos;
82

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

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

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

99
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
100 101 102 103 104 105 106 107

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(()),
108
        (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability),
109 110
    }
}
111

112
fn identity(_: Ty) -> Vec<Adjustment> { vec![] }
113

114 115
fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
    move |target| vec![Adjustment { kind, target }]
116 117
}

118 119
fn success<'tcx>(adj: Vec<Adjustment<'tcx>>,
                 target: Ty<'tcx>,
120 121 122
                 obligations: traits::PredicateObligations<'tcx>)
                 -> CoerceResult<'tcx> {
    Ok(InferOk {
123
        value: (adj, target),
124 125 126 127
        obligations
    })
}

128
impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
129
    fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
130
        Coerce {
131 132
            fcx,
            cause,
133
            use_lub: false,
134 135 136
        }
    }

137
    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
138
        self.commit_if_ok(|_| {
139
            if self.use_lub {
140 141
                self.at(&self.cause, self.fcx.param_env)
                    .lub(b, a)
142
            } else {
143 144 145
                self.at(&self.cause, self.fcx.param_env)
                    .sup(b, a)
                    .map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
146
            }
147 148 149
        })
    }

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

160
    fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
161
        let a = self.shallow_resolve(a);
162
        debug!("Coerce.tys({:?} => {:?})", a, b);
163 164 165

        // Just ignore error types.
        if a.references_error() || b.references_error() {
166
            return success(vec![], b, vec![]);
167 168
        }

A
Andrew Cann 已提交
169
        if a.is_never() {
170 171 172 173 174 175 176 177 178 179 180 181 182
            // 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));
183
                self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
184
            } else {
185
                success(simple(Adjust::NeverToAny)(b), b, vec![])
186
            };
A
Andrew Cann 已提交
187 188
        }

N
Nick Cameron 已提交
189
        // Consider coercing the subtype to a DST
190
        let unsize = self.coerce_unsized(a, b);
N
Nick Cameron 已提交
191
        if unsize.is_ok() {
N
Niko Matsakis 已提交
192
            debug!("coerce: unsize successful");
N
Nick Cameron 已提交
193 194
            return unsize;
        }
N
Niko Matsakis 已提交
195
        debug!("coerce: unsize failed");
N
Nick Cameron 已提交
196

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

206
            ty::TyRef(r_b, mt_b) => {
207
                return self.coerce_borrowed_pointer(a, b, r_b, mt_b);
208 209
            }

210 211
            _ => {}
        }
212

213
        match a.sty {
214
            ty::TyFnDef(..) => {
215 216 217
                // Function items are coercible to any closure
                // type; function pointers are not (that would
                // require double indirection).
T
Taylor Cramer 已提交
218
                // Additionally, we permit coercion of function
219
                // items to drop the unsafe qualifier.
220
                self.coerce_from_fn_item(a, b)
221
            }
222
            ty::TyFnPtr(a_f) => {
223 224 225 226
                // We permit coercion of fn pointers to drop the
                // unsafe qualifier.
                self.coerce_from_fn_pointer(a, a_f, b)
            }
227 228 229 230 231
            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)
            }
232
            _ => {
233
                // Otherwise, just use unification rules.
234
                self.unify_and(a, b, identity)
235 236
            }
        }
237 238
    }

239 240 241
    /// 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.
242 243 244 245 246 247
    fn coerce_borrowed_pointer(&self,
                               a: Ty<'tcx>,
                               b: Ty<'tcx>,
                               r_b: ty::Region<'tcx>,
                               mt_b: TypeAndMut<'tcx>)
                               -> CoerceResult<'tcx> {
248 249

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

251 252 253 254 255 256
        // 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 已提交
257
        let (r_a, mt_a) = match a.sty {
258
            ty::TyRef(r_a, mt_a) => {
J
Jorge Aparicio 已提交
259
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
N
Niko Matsakis 已提交
260
                (r_a, mt_a)
S
Seo Sanghyeon 已提交
261
            }
262
            _ => return self.unify_and(a, b, identity),
263
        };
264

265
        let span = self.cause.span;
266

267
        let mut first_error = None;
268
        let mut r_borrow_var = None;
269
        let mut autoderef = self.autoderef(span, a);
270
        let mut found = None;
271 272 273

        for (referent_ty, autoderefs) in autoderef.by_ref() {
            if autoderefs == 0 {
274 275
                // Don't let this pass, otherwise it would cause
                // &T to autoref to &&T.
276
                continue;
277
            }
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301

            // 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`.
            //
302
            // One fine point concerns the region that we use. We
303 304 305 306
            // choose the region such that the region of the final
            // type that results from `unify` will be the region we
            // want for the autoref:
            //
307 308 309
            // - 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
310 311 312 313 314
            //   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.
315 316 317 318 319 320 321 322
            //   - 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".)
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
            // - 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
351
            } else if autoderefs == 1 {
352 353
                r_a // [3] above
            } else {
354 355
                if r_borrow_var.is_none() {
                    // create var lazilly, at most once
356
                    let coercion = Coercion(span);
357
                    let r = self.next_region_var(coercion);
358
                    r_borrow_var = Some(r); // [4] above
359 360 361
                }
                r_borrow_var.unwrap()
            };
362 363 364 365 366
            let derefd_ty_a = self.tcx.mk_ref(r,
                                              TypeAndMut {
                                                  ty: referent_ty,
                                                  mutbl: mt_b.mutbl, // [1] above
                                              });
367
            match self.unify(derefd_ty_a, b) {
368
                Ok(ok) => {
369
                    found = Some(ok);
370 371
                    break;
                }
372 373 374 375
                Err(err) => {
                    if first_error.is_none() {
                        first_error = Some(err);
                    }
376 377
                }
            }
378
        }
379

380 381 382 383 384
        // 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.
385
        let InferOk { value: ty, mut obligations } = match found {
386
            Some(d) => d,
387
            None => {
388 389 390
                let err = first_error.expect("coerce_borrowed_pointer had no error");
                debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
                return Err(err);
391
            }
392 393
        };

394
        if ty == a && mt_a.mutbl == hir::MutImmutable && autoderef.step_count() == 1 {
N
Niko Matsakis 已提交
395 396 397 398 399 400 401 402 403 404 405
            // 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.
406
            assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
407
            return success(vec![], ty, obligations);
N
Niko Matsakis 已提交
408
        }
409

410 411 412 413 414 415
        let pref = LvaluePreference::from_mutbl(mt_b.mutbl);
        let InferOk { value: mut adjustments, obligations: o }
            = autoderef.adjust_steps_as_infer_ok(pref);
        obligations.extend(o);
        obligations.extend(autoderef.into_obligations());

416 417
        // Now apply the autoref. We have to extract the region out of
        // the final ref type we got.
418
        let r_borrow = match ty.sty {
419
            ty::TyRef(r_borrow, _) => r_borrow,
420
            _ => span_bug!(span, "expected a ref type, got {:?}", ty),
421
        };
422 423 424 425
        adjustments.push(Adjustment {
            kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)),
            target: ty
        });
426

427
        debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}",
428
               ty,
429
               adjustments);
430

431
        success(adjustments, ty, obligations)
432 433 434
    }


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

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

N
Nick Cameron 已提交
450 451 452
        // 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 已提交
453
        // that, at which point we will need extra checks on the target here.
N
Nick Cameron 已提交
454

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

460
                let coercion = Coercion(self.cause.span);
461
                let r_borrow = self.next_region_var(coercion);
462 463 464 465 466 467 468 469 470 471
                Some((Adjustment {
                    kind: Adjust::Deref(None),
                    target: mt_a.ty
                }, Adjustment {
                    kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)),
                    target:  self.tcx.mk_ref(r_borrow, ty::TypeAndMut {
                        mutbl: mt_b.mutbl,
                        ty: mt_a.ty
                    })
                }))
472
            }
473
            (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
J
Jorge Aparicio 已提交
474
                coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
475 476 477 478 479 480 481 482 483 484 485

                Some((Adjustment {
                    kind: Adjust::Deref(None),
                    target: mt_a.ty
                }, Adjustment {
                    kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b.mutbl)),
                    target:  self.tcx.mk_ptr(ty::TypeAndMut {
                        mutbl: mt_b.mutbl,
                        ty: mt_a.ty
                    })
                }))
486
            }
487
            _ => None,
N
Nick Cameron 已提交
488
        };
489
        let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target);
490 491 492 493 494 495 496

        // 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);
497 498 499 500 501 502 503 504 505 506 507
        let mut coercion = self.unify_and(coerce_target, target, |target| {
            let unsize = Adjustment {
                kind: Adjust::Unsize,
                target
            };
            match reborrow {
                None => vec![unsize],
                Some((ref deref, ref autoref)) => {
                    vec![deref.clone(), autoref.clone(), unsize]
                }
            }
508
        })?;
N
Nick Cameron 已提交
509

510
        let mut selcx = traits::SelectionContext::new(self);
N
Nick Cameron 已提交
511 512 513 514 515

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

        // Create an obligation for `Source: CoerceUnsized<Target>`.
516
        let cause = ObligationCause::misc(self.cause.span, self.body_id);
N
Niko Matsakis 已提交
517 518 519 520 521 522
        queue.push_back(self.tcx.predicate_for_trait_def(self.fcx.param_env,
                                                         cause,
                                                         coerce_unsized_did,
                                                         0,
                                                         coerce_source,
                                                         &[coerce_target]));
N
Nick Cameron 已提交
523

524 525
        let mut has_unsized_tuple_coercion = false;

N
Nick Cameron 已提交
526 527 528 529 530
        // 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() {
531
            debug!("coerce_unsized resolve step: {:?}", obligation);
532
            let trait_ref = match obligation.predicate {
533 534 535 536 537 538 539 540 541
                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                    if unsize_did == tr.def_id() {
                        if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty {
                            debug!("coerce_unsized: found unsized tuple coercion");
                            has_unsized_tuple_coercion = true;
                        }
                    }
                    tr.clone()
                }
N
Nick Cameron 已提交
542
                _ => {
543
                    coercion.obligations.push(obligation);
N
Nick Cameron 已提交
544 545 546 547 548
                    continue;
                }
            };
            match selcx.select(&obligation.with(trait_ref)) {
                // Uncertain or unimplemented.
549 550
                Ok(None) |
                Err(traits::Unimplemented) => {
N
Nick Cameron 已提交
551
                    debug!("coerce_unsized: early return - can't prove obligation");
552
                    return Err(TypeError::Mismatch);
N
Nick Cameron 已提交
553
                }
N
Nick Cameron 已提交
554 555 556

                // Object safety violations or miscellaneous.
                Err(err) => {
557
                    self.report_selection_error(&obligation, &err);
N
Nick Cameron 已提交
558 559 560 561 562 563
                    // 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)) => {
564 565 566
                    for obligation in vtable.nested_obligations() {
                        queue.push_back(obligation);
                    }
N
Nick Cameron 已提交
567
                }
N
Nick Cameron 已提交
568
            }
N
Nick Cameron 已提交
569 570
        }

571 572 573 574 575 576 577 578
        if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion {
            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
                                           "unsized_tuple_coercion",
                                           self.cause.span,
                                           feature_gate::GateIssue::Language,
                                           feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION);
        }

579
        Ok(coercion)
N
Nick Cameron 已提交
580
    }
581

582 583 584 585 586 587 588
    fn coerce_from_safe_fn<F, G>(&self,
                                 a: Ty<'tcx>,
                                 fn_ty_a: ty::PolyFnSig<'tcx>,
                                 b: Ty<'tcx>,
                                 to_unsafe: F,
                                 normal: G)
                                 -> CoerceResult<'tcx>
589 590
        where F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
              G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>
591
    {
592
        if let ty::TyFnPtr(fn_ty_b) = b.sty {
593
            match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
594 595
                (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                    let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
596
                    return self.unify_and(unsafe_a, b, to_unsafe);
597 598 599 600
                }
                _ => {}
            }
        }
601
        self.unify_and(a, b, normal)
602 603
    }

604
    fn coerce_from_fn_pointer(&self,
605
                              a: Ty<'tcx>,
606
                              fn_ty_a: ty::PolyFnSig<'tcx>,
607 608 609 610 611
                              b: Ty<'tcx>)
                              -> CoerceResult<'tcx> {
        //! Attempts to coerce from the type of a Rust function item
        //! into a closure or a `proc`.
        //!
612

613
        let b = self.shallow_resolve(b);
614
        debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
615

616
        self.coerce_from_safe_fn(a, fn_ty_a, b,
617
            simple(Adjust::UnsafeFnPointer), identity)
618 619
    }

620 621 622
    fn coerce_from_fn_item(&self,
                           a: Ty<'tcx>,
                           b: Ty<'tcx>)
623
                           -> CoerceResult<'tcx> {
624 625 626
        //! Attempts to coerce from the type of a Rust function item
        //! into a closure or a `proc`.
        //!
627

628
        let b = self.shallow_resolve(b);
629
        debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
630

631 632
        match b.sty {
            ty::TyFnPtr(_) => {
633 634 635 636 637 638 639 640 641 642 643
                let a_sig = a.fn_sig(self.tcx);
                let InferOk { value: a_sig, mut obligations } =
                    self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);

                let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
                let InferOk { value, obligations: o2 } =
                    self.coerce_from_safe_fn(a_fn_pointer, a_sig, b,
                        simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?;

                obligations.extend(o2);
                Ok(InferOk { value, obligations })
644
            }
645
            _ => self.unify_and(a, b, identity),
646
        }
647 648
    }

649 650 651 652 653 654 655 656 657 658 659 660
    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 已提交
661
        let node_id_a = self.tcx.hir.as_local_node_id(def_id_a).unwrap();
662 663 664 665 666 667
        match b.sty {
            ty::TyFnPtr(_) if self.tcx.with_freevars(node_id_a, |v| v.is_empty()) => {
                // We coerce the closure, which has fn type
                //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                // to
                //     `fn(arg0,arg1,...) -> _`
668
                let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
E
est31 已提交
669 670 671
                let converted_sig = sig.map_bound(|s| {
                    let params_iter = match s.inputs()[0].sty {
                        ty::TyTuple(params, _) => {
672 673 674 675
                            params.into_iter().cloned()
                        }
                        _ => bug!(),
                    };
676 677 678 679 680 681 682
                    self.tcx.mk_fn_sig(
                        params_iter,
                        s.output(),
                        s.variadic,
                        hir::Unsafety::Normal,
                        abi::Abi::Rust
                    )
683
                });
684
                let pointer_ty = self.tcx.mk_fn_ptr(converted_sig);
685 686
                debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                       a, b, pointer_ty);
687
                self.unify_and(pointer_ty, b, simple(Adjust::ClosureFnPointer))
688
            }
689
            _ => self.unify_and(a, b, identity),
690 691 692
        }
    }

693 694 695
    fn coerce_unsafe_ptr(&self,
                         a: Ty<'tcx>,
                         b: Ty<'tcx>,
696
                         mutbl_b: hir::Mutability)
697
                         -> CoerceResult<'tcx> {
698
        debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
699

700 701 702
        let (is_ref, mt_a) = match a.sty {
            ty::TyRef(_, mt) => (true, mt),
            ty::TyRawPtr(mt) => (false, mt),
703
            _ => {
704
                return self.unify_and(a, b, identity);
705 706 707
            }
        };

708
        // Check that the types which they point at are compatible.
709 710 711 712
        let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut {
            mutbl: mutbl_b,
            ty: mt_a.ty,
        });
J
Jorge Aparicio 已提交
713
        coerce_mutbls(mt_a.mutbl, mutbl_b)?;
714
        // Although references and unsafe ptrs have the same
715
        // representation, we still register an Adjust::DerefRef so that
716
        // regionck knows that the region for `a` must be valid here.
717
        if is_ref {
718 719 720 721 722 723 724 725
            self.unify_and(a_unsafe, b, |target| {
                vec![Adjustment {
                    kind: Adjust::Deref(None),
                    target: mt_a.ty
                }, Adjustment {
                    kind: Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
                    target
                }]
726
            })
727
        } else if mt_a.mutbl != mutbl_b {
728
            self.unify_and(a_unsafe, b, simple(Adjust::MutToConstPointer))
729
        } else {
730 731
            self.unify_and(a_unsafe, b, identity)
        }
732
    }
733 734
}

735
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
736 737 738 739 740 741
    /// 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,
742
                      expr_ty: Ty<'tcx>,
743
                      expr_diverges: Diverges,
744 745
                      target: Ty<'tcx>)
                      -> RelateResult<'tcx, Ty<'tcx>> {
746
        let source = self.resolve_type_vars_with_obligations(expr_ty);
747
        debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
748

749 750 751 752 753 754 755
        // 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);
        }

756
        let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
757
        let coerce = Coerce::new(self, cause);
758
        let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
759

760 761
        let (adjustments, _) = self.register_infer_ok_obligations(ok);
        self.apply_adjustments(expr, adjustments);
762
        Ok(target)
763 764
    }

765
    /// Same as `try_coerce()`, but without side-effects.
G
Guillaume Gomez 已提交
766
    pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
767 768 769 770 771
        let source = self.resolve_type_vars_with_obligations(expr_ty);
        debug!("coercion::can({:?} -> {:?})", source, target);

        let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable);
        let coerce = Coerce::new(self, cause);
772
        self.probe(|_| coerce.coerce(source, target)).is_ok()
773 774
    }

775 776 777
    /// 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").
778 779 780
    ///
    /// This is really an internal helper. From outside the coercion
    /// module, you should instantiate a `CoerceMany` instance.
781 782 783 784 785
    fn try_find_coercion_lub<E>(&self,
                                cause: &ObligationCause<'tcx>,
                                exprs: &[E],
                                prev_ty: Ty<'tcx>,
                                new: &hir::Expr,
786 787
                                new_ty: Ty<'tcx>,
                                new_diverges: Diverges)
788 789
                                -> RelateResult<'tcx, Ty<'tcx>>
        where E: AsCoercionSite
790
    {
791
        let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
792
        let new_ty = self.resolve_type_vars_with_obligations(new_ty);
N
Niko Matsakis 已提交
793
        debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
794

795 796 797 798 799 800 801
        // 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);
        }

802 803
        // Special-case that coercion alone cannot handle:
        // Two function item types of differing IDs or Substs.
804 805 806 807 808 809
        if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
            // Don't reify if the function types have a LUB, i.e. they
            // are the same function and their parameters have a LUB.
            let lub_ty = self.commit_if_ok(|_| {
                self.at(cause, self.param_env)
                    .lub(prev_ty, new_ty)
810
            }).map(|ok| self.register_infer_ok_obligations(ok));
811 812 813 814 815

            if lub_ty.is_ok() {
                // We have a LUB of prev_ty and new_ty, just return it.
                return lub_ty;
            }
816

817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
            // The signature must match.
            let a_sig = prev_ty.fn_sig(self.tcx);
            let a_sig = self.normalize_associated_types_in(new.span, &a_sig);
            let b_sig = new_ty.fn_sig(self.tcx);
            let b_sig = self.normalize_associated_types_in(new.span, &b_sig);
            let sig = self.at(cause, self.param_env)
                          .trace(prev_ty, new_ty)
                          .lub(&a_sig, &b_sig)
                          .map(|ok| self.register_infer_ok_obligations(ok))?;

            // Reify both sides and return the reified fn pointer type.
            let fn_ptr = self.tcx.mk_fn_ptr(sig);
            for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
                // The only adjustment that can produce an fn item is
                // `NeverToAny`, so this should always be valid.
                self.apply_adjustments(expr, vec![Adjustment {
                    kind: Adjust::ReifyFnPointer,
                    target: fn_ptr
                }]);
836
            }
837
            return Ok(fn_ptr);
838 839
        }

840
        let mut coerce = Coerce::new(self, cause.clone());
841 842 843 844 845
        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;
846
        if !self.tables.borrow().adjustments().contains_key(new.hir_id) {
847
            let result = self.commit_if_ok(|_| coerce.coerce(new_ty, prev_ty));
848
            match result {
849
                Ok(ok) => {
850 851
                    let (adjustments, target) = self.register_infer_ok_obligations(ok);
                    self.apply_adjustments(new, adjustments);
852
                    return Ok(target);
853
                }
854
                Err(e) => first_error = Some(e),
855
            }
856 857
        }

858 859 860
        // 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).
861 862
        for expr in exprs {
            let expr = expr.as_coercion_site();
863 864 865 866 867
            let noop = match self.tables.borrow().expr_adjustments(expr) {
                &[
                    Adjustment { kind: Adjust::Deref(_), .. },
                    Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }
                ] => {
868
                    match self.node_ty(expr.hir_id).sty {
869
                        ty::TyRef(_, mt_orig) => {
870
                            // Reborrow that we can safely ignore, because
871
                            // the next adjustment can only be a Deref
872
                            // which will be merged into it.
873 874 875
                            mutbl_adj == mt_orig.mutbl
                        }
                        _ => false,
876
                    }
877
                }
878 879
                &[Adjustment { kind: Adjust::NeverToAny, .. }] | &[] => true,
                _ => false,
880 881 882 883
            };

            if !noop {
                return self.commit_if_ok(|_| {
884 885
                    self.at(cause, self.param_env)
                        .lub(prev_ty, new_ty)
886
                }).map(|ok| self.register_infer_ok_obligations(ok));
887 888
            }
        }
889

890
        match self.commit_if_ok(|_| coerce.coerce(prev_ty, new_ty)) {
891 892 893 894 895 896
            Err(_) => {
                // Avoid giving strange errors on failed attempts.
                if let Some(e) = first_error {
                    Err(e)
                } else {
                    self.commit_if_ok(|_| {
897 898
                        self.at(cause, self.param_env)
                            .lub(prev_ty, new_ty)
899
                    }).map(|ok| self.register_infer_ok_obligations(ok))
900 901
                }
            }
902
            Ok(ok) => {
903
                let (adjustments, target) = self.register_infer_ok_obligations(ok);
904 905
                for expr in exprs {
                    let expr = expr.as_coercion_site();
906
                    self.apply_adjustments(expr, adjustments.clone());
907
                }
908
                Ok(target)
909
            }
910
        }
911 912
    }
}
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954

/// 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);
/// ```
955 956 957
pub struct CoerceMany<'gcx, 'tcx, 'exprs, E>
    where 'gcx: 'tcx, E: 'exprs + AsCoercionSite,
{
958 959
    expected_ty: Ty<'tcx>,
    final_ty: Option<Ty<'tcx>>,
960 961 962 963 964 965
    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`.
966
pub type DynamicCoerceMany<'gcx, 'tcx> = CoerceMany<'gcx, 'tcx, 'gcx, P<hir::Expr>>;
967 968 969 970 971 972

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

975 976 977 978 979 980
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.
981
    pub fn new(expected_ty: Ty<'tcx>) -> Self {
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
        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 {
997 998 999
        CoerceMany {
            expected_ty,
            final_ty: None,
1000 1001
            expressions,
            pushed: 0,
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
        }
    }

    /// 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,
1034 1035
                      expression_ty: Ty<'tcx>,
                      expression_diverges: Diverges)
1036
    {
A
alexey zabelin 已提交
1037 1038 1039 1040 1041 1042
        self.coerce_inner(fcx,
                          cause,
                          Some(expression),
                          expression_ty,
                          expression_diverges,
                          None, false)
1043 1044 1045
    }

    /// Indicates that one of the inputs is a "forced unit". This
1046
    /// occurs in a case like `if foo { ... };`, where the missing else
1047 1048 1049 1050 1051 1052
    /// 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.
1053 1054 1055 1056
    ///
    /// 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 `;`).
1057 1058
    pub fn coerce_forced_unit<'a>(&mut self,
                                  fcx: &FnCtxt<'a, 'gcx, 'tcx>,
1059
                                  cause: &ObligationCause<'tcx>,
1060 1061
                                  augment_error: &mut FnMut(&mut DiagnosticBuilder),
                                  label_unit_as_expected: bool)
1062 1063 1064 1065
    {
        self.coerce_inner(fcx,
                          cause,
                          None,
1066
                          fcx.tcx.mk_nil(),
1067
                          Diverges::Maybe,
1068 1069
                          Some(augment_error),
                          label_unit_as_expected)
1070 1071 1072 1073 1074 1075 1076 1077 1078
    }

    /// 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>,
1079
                        mut expression_ty: Ty<'tcx>,
1080
                        expression_diverges: Diverges,
1081 1082
                        augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>,
                        label_expression_as_expected: bool)
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
    {
        // 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 {
1102
            if self.pushed == 0 {
1103 1104
                // Special-case the first expression we are coercing.
                // To be honest, I'm not entirely sure why we do this.
1105
                fcx.try_coerce(expression, expression_ty, expression_diverges, self.expected_ty)
1106
            } else {
1107 1108 1109 1110 1111 1112
                match self.expressions {
                    Expressions::Dynamic(ref exprs) =>
                        fcx.try_find_coercion_lub(cause,
                                                  exprs,
                                                  self.merged_ty(),
                                                  expression,
1113 1114
                                                  expression_ty,
                                                  expression_diverges),
1115 1116 1117 1118 1119
                    Expressions::UpFront(ref coercion_sites) =>
                        fcx.try_find_coercion_lub(cause,
                                                  &coercion_sites[0..self.pushed],
                                                  self.merged_ty(),
                                                  expression,
1120 1121
                                                  expression_ty,
                                                  expression_diverges),
1122
                }
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
            }
        } 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");
1140 1141
            fcx.at(cause, fcx.param_env)
               .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
1142 1143 1144 1145 1146 1147 1148 1149 1150
               .map(|infer_ok| {
                   fcx.register_infer_ok_obligations(infer_ok);
                   expression_ty
               })
        };

        match result {
            Ok(v) => {
                self.final_ty = Some(v);
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
                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;
                }
1162 1163
            }
            Err(err) => {
1164
                let (expected, found) = if label_expression_as_expected {
A
alexey zabelin 已提交
1165 1166 1167 1168
                    // In the case where this is a "forced unit", like
                    // `break`, we want to call the `()` "expected"
                    // since it is implied by the syntax.
                    // (Note: not all force-units work this way.)"
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
                    (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)
                };

1179
                let mut db;
1180 1181
                match cause.code {
                    ObligationCauseCode::ReturnNoExpression => {
1182 1183 1184
                        db = struct_span_err!(
                            fcx.tcx.sess, cause.span, E0069,
                            "`return;` in a function whose return type is not `()`");
1185
                        db.span_label(cause.span, "return type is not ()");
1186
                    }
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
                    ObligationCauseCode::BlockTailExpression(blk_id) => {
                        db = fcx.report_mismatched_types(cause, expected, found, err);

                        let expr = expression.unwrap_or_else(|| {
                            span_bug!(cause.span,
                                      "supposed to be part of a block tail expression, but the \
                                       expression is empty");
                        });
                        fcx.suggest_mismatched_types_on_tail(&mut db, expr,
                                                             expected, found,
                                                             cause.span, blk_id);
                    }
1199
                    _ => {
1200
                        db = fcx.report_mismatched_types(cause, expected, found, err);
1201 1202 1203
                    }
                }

1204
                if let Some(augment_error) = augment_error {
1205 1206 1207 1208 1209
                    augment_error(&mut db);
                }

                db.emit();

1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
                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 `!`.
1221
            assert_eq!(self.pushed, 0);
1222 1223 1224 1225
            fcx.tcx.types.never
        }
    }
}
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263

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