]> git.proxmox.com Git - rustc.git/blob - src/librustc_typeck/check/coercion.rs
New upstream version 1.15.0+dfsg1
[rustc.git] / src / librustc_typeck / check / coercion.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! # Type Coercion
12 //!
13 //! Under certain circumstances we will coerce from one type to another,
14 //! for example by auto-borrowing. This occurs in situations where the
15 //! compiler has a firm 'expected type' that was supplied from the user,
16 //! and where the actual type is similar to that expected type in purpose
17 //! but not in representation (so actual subtyping is inappropriate).
18 //!
19 //! ## Reborrowing
20 //!
21 //! Note that if we are expecting a reference, we will *reborrow*
22 //! even if the argument provided was already a reference. This is
23 //! useful for freezing mut/const things (that is, when the expected is &T
24 //! but you have &const T or &mut T) and also for avoiding the linearity
25 //! of mut things (when the expected is &mut T and you have &mut T). See
26 //! the various `src/test/run-pass/coerce-reborrow-*.rs` tests for
27 //! examples of where this is useful.
28 //!
29 //! ## Subtle note
30 //!
31 //! When deciding what type coercions to consider, we do not attempt to
32 //! resolve any type variables we may encounter. This is because `b`
33 //! represents the expected type "as the user wrote it", meaning that if
34 //! the user defined a generic function like
35 //!
36 //! fn foo<A>(a: A, b: A) { ... }
37 //!
38 //! and then we wrote `foo(&1, @2)`, we will not auto-borrow
39 //! either argument. In older code we went to some lengths to
40 //! resolve the `b` variable, which could mean that we'd
41 //! auto-borrow later arguments but not earlier ones, which
42 //! seems very confusing.
43 //!
44 //! ## Subtler note
45 //!
46 //! However, right now, if the user manually specifies the
47 //! values for the type variables, as so:
48 //!
49 //! foo::<&int>(@1, @2)
50 //!
51 //! then we *will* auto-borrow, because we can't distinguish this from a
52 //! function that declared `&int`. This is inconsistent but it's easiest
53 //! at the moment. The right thing to do, I think, is to consider the
54 //! *unsubstituted* type when deciding whether to auto-borrow, but the
55 //! *substituted* type when considering the bounds and so forth. But most
56 //! of our methods don't give access to the unsubstituted type, and
57 //! rightly so because they'd be error-prone. So maybe the thing to do is
58 //! to actually determine the kind of coercions that should occur
59 //! separately and pass them in. Or maybe it's ok as is. Anyway, it's
60 //! sort of a minor point so I've opted to leave it for later---after all
61 //! we may want to adjust precisely when coercions occur.
62
63 use check::FnCtxt;
64
65 use rustc::hir;
66 use rustc::infer::{Coercion, InferOk, TypeTrace};
67 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
68 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
69 use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
70 use rustc::ty::fold::TypeFoldable;
71 use rustc::ty::error::TypeError;
72 use rustc::ty::relate::RelateResult;
73 use util::common::indent;
74
75 use std::cell::RefCell;
76 use std::collections::VecDeque;
77 use std::ops::Deref;
78
79 struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
80 fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
81 cause: ObligationCause<'tcx>,
82 use_lub: bool,
83 unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
84 }
85
86 impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
87 type Target = FnCtxt<'a, 'gcx, 'tcx>;
88 fn deref(&self) -> &Self::Target {
89 &self.fcx
90 }
91 }
92
93 type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, Adjust<'tcx>)>;
94
95 fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
96 to_mutbl: hir::Mutability)
97 -> RelateResult<'tcx, ()> {
98 match (from_mutbl, to_mutbl) {
99 (hir::MutMutable, hir::MutMutable) |
100 (hir::MutImmutable, hir::MutImmutable) |
101 (hir::MutMutable, hir::MutImmutable) => Ok(()),
102 (hir::MutImmutable, hir::MutMutable) => Err(TypeError::Mutability),
103 }
104 }
105
106 impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
107 fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
108 Coerce {
109 fcx: fcx,
110 cause: cause,
111 use_lub: false,
112 unsizing_obligations: RefCell::new(vec![]),
113 }
114 }
115
116 fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
117 self.commit_if_ok(|_| {
118 let trace = TypeTrace::types(&self.cause, false, a, b);
119 if self.use_lub {
120 self.lub(false, trace, &a, &b)
121 .map(|ok| self.register_infer_ok_obligations(ok))
122 } else {
123 self.sub(false, trace, &a, &b)
124 .map(|InferOk { value, obligations }| {
125 self.fcx.register_predicates(obligations);
126 value
127 })
128 }
129 })
130 }
131
132 /// Unify two types (using sub or lub) and produce a noop coercion.
133 fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
134 self.unify(&a, &b).and_then(|ty| self.identity(ty))
135 }
136
137 /// Synthesize an identity adjustment.
138 fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
139 Ok((ty, Adjust::DerefRef {
140 autoderefs: 0,
141 autoref: None,
142 unsize: false,
143 }))
144 }
145
146 fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx>
147 where E: Fn() -> I,
148 I: IntoIterator<Item = &'a hir::Expr>
149 {
150
151 let a = self.shallow_resolve(a);
152 debug!("Coerce.tys({:?} => {:?})", a, b);
153
154 // Just ignore error types.
155 if a.references_error() || b.references_error() {
156 return self.identity(b);
157 }
158
159 if a.is_never() {
160 return Ok((b, Adjust::NeverToAny));
161 }
162
163 // Consider coercing the subtype to a DST
164 let unsize = self.coerce_unsized(a, b);
165 if unsize.is_ok() {
166 return unsize;
167 }
168
169 // Examine the supertype and consider auto-borrowing.
170 //
171 // Note: does not attempt to resolve type variables we encounter.
172 // See above for details.
173 match b.sty {
174 ty::TyRawPtr(mt_b) => {
175 return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
176 }
177
178 ty::TyRef(r_b, mt_b) => {
179 return self.coerce_borrowed_pointer(exprs, a, b, r_b, mt_b);
180 }
181
182 _ => {}
183 }
184
185 match a.sty {
186 ty::TyFnDef(.., a_f) => {
187 // Function items are coercible to any closure
188 // type; function pointers are not (that would
189 // require double indirection).
190 // Additionally, we permit coercion of function
191 // items to drop the unsafe qualifier.
192 self.coerce_from_fn_item(a, a_f, b)
193 }
194 ty::TyFnPtr(a_f) => {
195 // We permit coercion of fn pointers to drop the
196 // unsafe qualifier.
197 self.coerce_from_fn_pointer(a, a_f, b)
198 }
199 _ => {
200 // Otherwise, just use unification rules.
201 self.unify_and_identity(a, b)
202 }
203 }
204 }
205
206 /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
207 /// To match `A` with `B`, autoderef will be performed,
208 /// calling `deref`/`deref_mut` where necessary.
209 fn coerce_borrowed_pointer<'a, E, I>(&self,
210 exprs: &E,
211 a: Ty<'tcx>,
212 b: Ty<'tcx>,
213 r_b: &'tcx ty::Region,
214 mt_b: TypeAndMut<'tcx>)
215 -> CoerceResult<'tcx>
216 where E: Fn() -> I,
217 I: IntoIterator<Item = &'a hir::Expr>
218 {
219
220 debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
221
222 // If we have a parameter of type `&M T_a` and the value
223 // provided is `expr`, we will be adding an implicit borrow,
224 // meaning that we convert `f(expr)` to `f(&M *expr)`. Therefore,
225 // to type check, we will construct the type that `&M*expr` would
226 // yield.
227
228 let (r_a, mt_a) = match a.sty {
229 ty::TyRef(r_a, mt_a) => {
230 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
231 (r_a, mt_a)
232 }
233 _ => return self.unify_and_identity(a, b),
234 };
235
236 let span = self.cause.span;
237
238 let mut first_error = None;
239 let mut r_borrow_var = None;
240 let mut autoderef = self.autoderef(span, a);
241 let mut success = None;
242
243 for (referent_ty, autoderefs) in autoderef.by_ref() {
244 if autoderefs == 0 {
245 // Don't let this pass, otherwise it would cause
246 // &T to autoref to &&T.
247 continue;
248 }
249
250 // At this point, we have deref'd `a` to `referent_ty`. So
251 // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
252 // In the autoderef loop for `&'a mut Vec<T>`, we would get
253 // three callbacks:
254 //
255 // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
256 // - `Vec<T>` -- 1 deref
257 // - `[T]` -- 2 deref
258 //
259 // At each point after the first callback, we want to
260 // check to see whether this would match out target type
261 // (`&'b mut [T]`) if we autoref'd it. We can't just
262 // compare the referent types, though, because we still
263 // have to consider the mutability. E.g., in the case
264 // we've been considering, we have an `&mut` reference, so
265 // the `T` in `[T]` needs to be unified with equality.
266 //
267 // Therefore, we construct reference types reflecting what
268 // the types will be after we do the final auto-ref and
269 // compare those. Note that this means we use the target
270 // mutability [1], since it may be that we are coercing
271 // from `&mut T` to `&U`.
272 //
273 // One fine point concerns the region that we use. We
274 // choose the region such that the region of the final
275 // type that results from `unify` will be the region we
276 // want for the autoref:
277 //
278 // - if in sub mode, that means we want to use `'b` (the
279 // region from the target reference) for both
280 // pointers [2]. This is because sub mode (somewhat
281 // arbitrarily) returns the subtype region. In the case
282 // where we are coercing to a target type, we know we
283 // want to use that target type region (`'b`) because --
284 // for the program to type-check -- it must be the
285 // smaller of the two.
286 // - One fine point. It may be surprising that we can
287 // use `'b` without relating `'a` and `'b`. The reason
288 // that this is ok is that what we produce is
289 // effectively a `&'b *x` expression (if you could
290 // annotate the region of a borrow), and regionck has
291 // code that adds edges from the region of a borrow
292 // (`'b`, here) into the regions in the borrowed
293 // expression (`*x`, here). (Search for "link".)
294 // - if in lub mode, things can get fairly complicated. The
295 // easiest thing is just to make a fresh
296 // region variable [4], which effectively means we defer
297 // the decision to region inference (and regionck, which will add
298 // some more edges to this variable). However, this can wind up
299 // creating a crippling number of variables in some cases --
300 // e.g. #32278 -- so we optimize one particular case [3].
301 // Let me try to explain with some examples:
302 // - The "running example" above represents the simple case,
303 // where we have one `&` reference at the outer level and
304 // ownership all the rest of the way down. In this case,
305 // we want `LUB('a, 'b)` as the resulting region.
306 // - However, if there are nested borrows, that region is
307 // too strong. Consider a coercion from `&'a &'x Rc<T>` to
308 // `&'b T`. In this case, `'a` is actually irrelevant.
309 // The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
310 // we get spurious errors (`run-pass/regions-lub-ref-ref-rc.rs`).
311 // (The errors actually show up in borrowck, typically, because
312 // this extra edge causes the region `'a` to be inferred to something
313 // too big, which then results in borrowck errors.)
314 // - We could track the innermost shared reference, but there is already
315 // code in regionck that has the job of creating links between
316 // the region of a borrow and the regions in the thing being
317 // borrowed (here, `'a` and `'x`), and it knows how to handle
318 // all the various cases. So instead we just make a region variable
319 // and let regionck figure it out.
320 let r = if !self.use_lub {
321 r_b // [2] above
322 } else if autoderefs == 1 {
323 r_a // [3] above
324 } else {
325 if r_borrow_var.is_none() {
326 // create var lazilly, at most once
327 let coercion = Coercion(span);
328 let r = self.next_region_var(coercion);
329 r_borrow_var = Some(r); // [4] above
330 }
331 r_borrow_var.unwrap()
332 };
333 let derefd_ty_a = self.tcx.mk_ref(r,
334 TypeAndMut {
335 ty: referent_ty,
336 mutbl: mt_b.mutbl, // [1] above
337 });
338 match self.unify(derefd_ty_a, b) {
339 Ok(ty) => {
340 success = Some((ty, autoderefs));
341 break;
342 }
343 Err(err) => {
344 if first_error.is_none() {
345 first_error = Some(err);
346 }
347 }
348 }
349 }
350
351 // Extract type or return an error. We return the first error
352 // we got, which should be from relating the "base" type
353 // (e.g., in example above, the failure from relating `Vec<T>`
354 // to the target type), since that should be the least
355 // confusing.
356 let (ty, autoderefs) = match success {
357 Some(d) => d,
358 None => {
359 let err = first_error.expect("coerce_borrowed_pointer had no error");
360 debug!("coerce_borrowed_pointer: failed with err = {:?}", err);
361 return Err(err);
362 }
363 };
364
365 // This commits the obligations to the fulfillcx. After this succeeds,
366 // this snapshot can't be rolled back.
367 autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());
368
369 // Now apply the autoref. We have to extract the region out of
370 // the final ref type we got.
371 if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
372 // As a special case, if we would produce `&'a *x`, that's
373 // a total no-op. We end up with the type `&'a T` just as
374 // we started with. In that case, just skip it
375 // altogether. This is just an optimization.
376 //
377 // Note that for `&mut`, we DO want to reborrow --
378 // otherwise, this would be a move, which might be an
379 // error. For example `foo(self.x)` where `self` and
380 // `self.x` both have `&mut `type would be a move of
381 // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
382 // which is a borrow.
383 assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
384 return self.identity(ty);
385 }
386 let r_borrow = match ty.sty {
387 ty::TyRef(r_borrow, _) => r_borrow,
388 _ => span_bug!(span, "expected a ref type, got {:?}", ty),
389 };
390 let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl));
391 debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
392 ty,
393 autoderefs,
394 autoref);
395 Ok((ty, Adjust::DerefRef {
396 autoderefs: autoderefs,
397 autoref: autoref,
398 unsize: false,
399 }))
400 }
401
402
403 // &[T; n] or &mut [T; n] -> &[T]
404 // or &mut [T; n] -> &mut [T]
405 // or &Concrete -> &Trait, etc.
406 fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> {
407 debug!("coerce_unsized(source={:?}, target={:?})", source, target);
408
409 let traits = (self.tcx.lang_items.unsize_trait(),
410 self.tcx.lang_items.coerce_unsized_trait());
411 let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
412 (u, cu)
413 } else {
414 debug!("Missing Unsize or CoerceUnsized traits");
415 return Err(TypeError::Mismatch);
416 };
417
418 // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
419 // a DST unless we have to. This currently comes out in the wash since
420 // we can't unify [T] with U. But to properly support DST, we need to allow
421 // that, at which point we will need extra checks on the target here.
422
423 // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
424 let (source, reborrow) = match (&source.sty, &target.sty) {
425 (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => {
426 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
427
428 let coercion = Coercion(self.cause.span);
429 let r_borrow = self.next_region_var(coercion);
430 (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl)))
431 }
432 (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
433 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
434 (mt_a.ty, Some(AutoBorrow::RawPtr(mt_b.mutbl)))
435 }
436 _ => (source, None),
437 };
438 let source = source.adjust_for_autoref(self.tcx, reborrow);
439
440 let mut selcx = traits::SelectionContext::new(self);
441
442 // Use a FIFO queue for this custom fulfillment procedure.
443 let mut queue = VecDeque::new();
444 let mut leftover_predicates = vec![];
445
446 // Create an obligation for `Source: CoerceUnsized<Target>`.
447 let cause = ObligationCause::misc(self.cause.span, self.body_id);
448 queue.push_back(self.tcx
449 .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target]));
450
451 // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
452 // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
453 // inference might unify those two inner type variables later.
454 let traits = [coerce_unsized_did, unsize_did];
455 while let Some(obligation) = queue.pop_front() {
456 debug!("coerce_unsized resolve step: {:?}", obligation);
457 let trait_ref = match obligation.predicate {
458 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
459 _ => {
460 leftover_predicates.push(obligation);
461 continue;
462 }
463 };
464 match selcx.select(&obligation.with(trait_ref)) {
465 // Uncertain or unimplemented.
466 Ok(None) |
467 Err(traits::Unimplemented) => {
468 debug!("coerce_unsized: early return - can't prove obligation");
469 return Err(TypeError::Mismatch);
470 }
471
472 // Object safety violations or miscellaneous.
473 Err(err) => {
474 self.report_selection_error(&obligation, &err);
475 // Treat this like an obligation and follow through
476 // with the unsizing - the lack of a coercion should
477 // be silent, as it causes a type mismatch later.
478 }
479
480 Ok(Some(vtable)) => {
481 for obligation in vtable.nested_obligations() {
482 queue.push_back(obligation);
483 }
484 }
485 }
486 }
487
488 *self.unsizing_obligations.borrow_mut() = leftover_predicates;
489
490 let adjustment = Adjust::DerefRef {
491 autoderefs: if reborrow.is_some() { 1 } else { 0 },
492 autoref: reborrow,
493 unsize: true,
494 };
495 debug!("Success, coerced with {:?}", adjustment);
496 Ok((target, adjustment))
497 }
498
499 fn coerce_from_safe_fn(&self,
500 a: Ty<'tcx>,
501 fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
502 b: Ty<'tcx>)
503 -> CoerceResult<'tcx> {
504 if let ty::TyFnPtr(fn_ty_b) = b.sty {
505 match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
506 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
507 let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
508 return self.unify_and_identity(unsafe_a, b)
509 .map(|(ty, _)| (ty, Adjust::UnsafeFnPointer));
510 }
511 _ => {}
512 }
513 }
514 self.unify_and_identity(a, b)
515 }
516
517 fn coerce_from_fn_pointer(&self,
518 a: Ty<'tcx>,
519 fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
520 b: Ty<'tcx>)
521 -> CoerceResult<'tcx> {
522 //! Attempts to coerce from the type of a Rust function item
523 //! into a closure or a `proc`.
524 //!
525
526 let b = self.shallow_resolve(b);
527 debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
528
529 self.coerce_from_safe_fn(a, fn_ty_a, b)
530 }
531
532 fn coerce_from_fn_item(&self,
533 a: Ty<'tcx>,
534 fn_ty_a: &'tcx ty::BareFnTy<'tcx>,
535 b: Ty<'tcx>)
536 -> CoerceResult<'tcx> {
537 //! Attempts to coerce from the type of a Rust function item
538 //! into a closure or a `proc`.
539 //!
540
541 let b = self.shallow_resolve(b);
542 debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
543
544 match b.sty {
545 ty::TyFnPtr(_) => {
546 let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
547 self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
548 .map(|(ty, _)| (ty, Adjust::ReifyFnPointer))
549 }
550 _ => self.unify_and_identity(a, b),
551 }
552 }
553
554 fn coerce_unsafe_ptr(&self,
555 a: Ty<'tcx>,
556 b: Ty<'tcx>,
557 mutbl_b: hir::Mutability)
558 -> CoerceResult<'tcx> {
559 debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b);
560
561 let (is_ref, mt_a) = match a.sty {
562 ty::TyRef(_, mt) => (true, mt),
563 ty::TyRawPtr(mt) => (false, mt),
564 _ => {
565 return self.unify_and_identity(a, b);
566 }
567 };
568
569 // Check that the types which they point at are compatible.
570 let a_unsafe = self.tcx.mk_ptr(ty::TypeAndMut {
571 mutbl: mutbl_b,
572 ty: mt_a.ty,
573 });
574 let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
575 coerce_mutbls(mt_a.mutbl, mutbl_b)?;
576
577 // Although references and unsafe ptrs have the same
578 // representation, we still register an Adjust::DerefRef so that
579 // regionck knows that the region for `a` must be valid here.
580 Ok((ty,
581 if is_ref {
582 Adjust::DerefRef {
583 autoderefs: 1,
584 autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
585 unsize: false,
586 }
587 } else if mt_a.mutbl != mutbl_b {
588 Adjust::MutToConstPointer
589 } else {
590 noop
591 }))
592 }
593 }
594
595 fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
596 exprs: &E,
597 a: Ty<'tcx>,
598 b: Ty<'tcx>)
599 -> RelateResult<'tcx, Adjustment<'tcx>>
600 where E: Fn() -> I,
601 I: IntoIterator<Item = &'b hir::Expr>
602 {
603
604 let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?;
605
606 let fcx = coerce.fcx;
607 if let Adjust::DerefRef { unsize: true, .. } = adjust {
608 let mut obligations = coerce.unsizing_obligations.borrow_mut();
609 for obligation in obligations.drain(..) {
610 fcx.register_predicate(obligation);
611 }
612 }
613
614 Ok(Adjustment {
615 kind: adjust,
616 target: ty
617 })
618 }
619
620 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
621 /// Attempt to coerce an expression to a type, and return the
622 /// adjusted type of the expression, if successful.
623 /// Adjustments are only recorded if the coercion succeeded.
624 /// The expressions *must not* have any pre-existing adjustments.
625 pub fn try_coerce(&self,
626 expr: &hir::Expr,
627 expr_ty: Ty<'tcx>,
628 target: Ty<'tcx>)
629 -> RelateResult<'tcx, Ty<'tcx>> {
630 let source = self.resolve_type_vars_with_obligations(expr_ty);
631 debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
632
633 let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
634 let mut coerce = Coerce::new(self, cause);
635 self.commit_if_ok(|_| {
636 let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?;
637 if !adjustment.is_identity() {
638 debug!("Success, coerced with {:?}", adjustment);
639 match self.tables.borrow().adjustments.get(&expr.id) {
640 None |
641 Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => (),
642 _ => bug!("expr already has an adjustment on it!"),
643 };
644 self.write_adjustment(expr.id, adjustment);
645 }
646 Ok(adjustment.target)
647 })
648 }
649
650 /// Given some expressions, their known unified type and another expression,
651 /// tries to unify the types, potentially inserting coercions on any of the
652 /// provided expressions and returns their LUB (aka "common supertype").
653 pub fn try_find_coercion_lub<'b, E, I>(&self,
654 cause: &ObligationCause<'tcx>,
655 exprs: E,
656 prev_ty: Ty<'tcx>,
657 new: &'b hir::Expr,
658 new_ty: Ty<'tcx>)
659 -> RelateResult<'tcx, Ty<'tcx>>
660 where E: Fn() -> I,
661 I: IntoIterator<Item = &'b hir::Expr>
662 {
663
664 let prev_ty = self.resolve_type_vars_with_obligations(prev_ty);
665 let new_ty = self.resolve_type_vars_with_obligations(new_ty);
666 debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty);
667
668 let trace = TypeTrace::types(cause, true, prev_ty, new_ty);
669
670 // Special-case that coercion alone cannot handle:
671 // Two function item types of differing IDs or Substs.
672 match (&prev_ty.sty, &new_ty.sty) {
673 (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
674 // The signature must always match.
675 let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
676 .map(|ok| self.register_infer_ok_obligations(ok))?;
677
678 if a_def_id == b_def_id {
679 // Same function, maybe the parameters match.
680 let substs = self.commit_if_ok(|_| {
681 self.lub(true, trace.clone(), &a_substs, &b_substs)
682 .map(|ok| self.register_infer_ok_obligations(ok))
683 });
684
685 if let Ok(substs) = substs {
686 // We have a LUB of prev_ty and new_ty, just return it.
687 return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
688 }
689 }
690
691 // Reify both sides and return the reified fn pointer type.
692 let fn_ptr = self.tcx.mk_fn_ptr(fty);
693 for expr in exprs().into_iter().chain(Some(new)) {
694 // No adjustments can produce a fn item, so this should never trip.
695 assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
696 self.write_adjustment(expr.id, Adjustment {
697 kind: Adjust::ReifyFnPointer,
698 target: fn_ptr
699 });
700 }
701 return Ok(fn_ptr);
702 }
703 _ => {}
704 }
705
706 let mut coerce = Coerce::new(self, cause.clone());
707 coerce.use_lub = true;
708
709 // First try to coerce the new expression to the type of the previous ones,
710 // but only if the new expression has no coercion already applied to it.
711 let mut first_error = None;
712 if !self.tables.borrow().adjustments.contains_key(&new.id) {
713 let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty));
714 match result {
715 Ok(adjustment) => {
716 if !adjustment.is_identity() {
717 self.write_adjustment(new.id, adjustment);
718 }
719 return Ok(adjustment.target);
720 }
721 Err(e) => first_error = Some(e),
722 }
723 }
724
725 // Then try to coerce the previous expressions to the type of the new one.
726 // This requires ensuring there are no coercions applied to *any* of the
727 // previous expressions, other than noop reborrows (ignoring lifetimes).
728 for expr in exprs() {
729 let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) {
730 Some(Adjust::DerefRef {
731 autoderefs: 1,
732 autoref: Some(AutoBorrow::Ref(_, mutbl_adj)),
733 unsize: false
734 }) => {
735 match self.node_ty(expr.id).sty {
736 ty::TyRef(_, mt_orig) => {
737 // Reborrow that we can safely ignore.
738 mutbl_adj == mt_orig.mutbl
739 }
740 _ => false,
741 }
742 }
743 Some(Adjust::NeverToAny) => true,
744 Some(_) => false,
745 None => true,
746 };
747
748 if !noop {
749 return self.commit_if_ok(|_| {
750 self.lub(true, trace.clone(), &prev_ty, &new_ty)
751 .map(|ok| self.register_infer_ok_obligations(ok))
752 });
753 }
754 }
755
756 match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
757 Err(_) => {
758 // Avoid giving strange errors on failed attempts.
759 if let Some(e) = first_error {
760 Err(e)
761 } else {
762 self.commit_if_ok(|_| {
763 self.lub(true, trace, &prev_ty, &new_ty)
764 .map(|ok| self.register_infer_ok_obligations(ok))
765 })
766 }
767 }
768 Ok(adjustment) => {
769 if !adjustment.is_identity() {
770 let mut tables = self.tables.borrow_mut();
771 for expr in exprs() {
772 if let Some(&mut Adjustment {
773 kind: Adjust::NeverToAny,
774 ref mut target
775 }) = tables.adjustments.get_mut(&expr.id) {
776 *target = adjustment.target;
777 continue;
778 }
779 tables.adjustments.insert(expr.id, adjustment);
780 }
781 }
782 Ok(adjustment.target)
783 }
784 }
785 }
786 }