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.
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.
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).
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.
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
36 //! fn foo<A>(a: A, b: A) { ... }
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.
46 //! However, right now, if the user manually specifies the
47 //! values for the type variables, as so:
49 //! foo::<&int>(@1, @2)
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.
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
;
75 use std
::cell
::RefCell
;
76 use std
::collections
::VecDeque
;
79 struct Coerce
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
80 fcx
: &'a FnCtxt
<'a
, 'gcx
, 'tcx
>,
81 cause
: ObligationCause
<'tcx
>,
83 unsizing_obligations
: RefCell
<Vec
<traits
::PredicateObligation
<'tcx
>>>,
86 impl<'a
, 'gcx
, 'tcx
> Deref
for Coerce
<'a
, 'gcx
, 'tcx
> {
87 type Target
= FnCtxt
<'a
, 'gcx
, 'tcx
>;
88 fn deref(&self) -> &Self::Target
{
93 type CoerceResult
<'tcx
> = RelateResult
<'tcx
, (Ty
<'tcx
>, Adjust
<'tcx
>)>;
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
),
106 impl<'f
, 'gcx
, 'tcx
> Coerce
<'f
, 'gcx
, 'tcx
> {
107 fn new(fcx
: &'f FnCtxt
<'f
, 'gcx
, 'tcx
>, cause
: ObligationCause
<'tcx
>) -> Self {
112 unsizing_obligations
: RefCell
::new(vec
![]),
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
);
120 self.lub(false, trace
, &a
, &b
)
121 .map(|ok
| self.register_infer_ok_obligations(ok
))
123 self.sub(false, trace
, &a
, &b
)
124 .map(|InferOk { value, obligations }
| {
125 self.fcx
.register_predicates(obligations
);
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
))
137 /// Synthesize an identity adjustment.
138 fn identity(&self, ty
: Ty
<'tcx
>) -> CoerceResult
<'tcx
> {
139 Ok((ty
, Adjust
::DerefRef
{
146 fn coerce
<'a
, E
, I
>(&self, exprs
: &E
, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> CoerceResult
<'tcx
>
148 I
: IntoIterator
<Item
= &'a hir
::Expr
>
151 let a
= self.shallow_resolve(a
);
152 debug
!("Coerce.tys({:?} => {:?})", a
, b
);
154 // Just ignore error types.
155 if a
.references_error() || b
.references_error() {
156 return self.identity(b
);
160 return Ok((b
, Adjust
::NeverToAny
));
163 // Consider coercing the subtype to a DST
164 let unsize
= self.coerce_unsized(a
, b
);
169 // Examine the supertype and consider auto-borrowing.
171 // Note: does not attempt to resolve type variables we encounter.
172 // See above for details.
174 ty
::TyRawPtr(mt_b
) => {
175 return self.coerce_unsafe_ptr(a
, b
, mt_b
.mutbl
);
178 ty
::TyRef(r_b
, mt_b
) => {
179 return self.coerce_borrowed_pointer(exprs
, a
, b
, r_b
, mt_b
);
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
)
194 ty
::TyFnPtr(a_f
) => {
195 // We permit coercion of fn pointers to drop the
197 self.coerce_from_fn_pointer(a
, a_f
, b
)
200 // Otherwise, just use unification rules.
201 self.unify_and_identity(a
, b
)
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,
213 r_b
: &'tcx ty
::Region
,
214 mt_b
: TypeAndMut
<'tcx
>)
215 -> CoerceResult
<'tcx
>
217 I
: IntoIterator
<Item
= &'a hir
::Expr
>
220 debug
!("coerce_borrowed_pointer(a={:?}, b={:?})", a
, b
);
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
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
)?
;
233 _
=> return self.unify_and_identity(a
, b
),
236 let span
= self.cause
.span
;
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
;
243 for (referent_ty
, autoderefs
) in autoderef
.by_ref() {
245 // Don't let this pass, otherwise it would cause
246 // &T to autoref to &&T.
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
255 // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
256 // - `Vec<T>` -- 1 deref
257 // - `[T]` -- 2 deref
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.
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`.
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:
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
{
322 } else if autoderefs
== 1 {
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
331 r_borrow_var
.unwrap()
333 let derefd_ty_a
= self.tcx
.mk_ref(r
,
336 mutbl
: mt_b
.mutbl
, // [1] above
338 match self.unify(derefd_ty_a
, b
) {
340 success
= Some((ty
, autoderefs
));
344 if first_error
.is_none() {
345 first_error
= Some(err
);
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
356 let (ty
, autoderefs
) = match success
{
359 let err
= first_error
.expect("coerce_borrowed_pointer had no error");
360 debug
!("coerce_borrowed_pointer: failed with err = {:?}", err
);
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());
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.
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
);
386 let r_borrow
= match ty
.sty
{
387 ty
::TyRef(r_borrow
, _
) => r_borrow
,
388 _
=> span_bug
!(span
, "expected a ref type, got {:?}", ty
),
390 let autoref
= Some(AutoBorrow
::Ref(r_borrow
, mt_b
.mutbl
));
391 debug
!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
395 Ok((ty
, Adjust
::DerefRef
{
396 autoderefs
: autoderefs
,
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
);
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
{
414 debug
!("Missing Unsize or CoerceUnsized traits");
415 return Err(TypeError
::Mismatch
);
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.
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
)?
;
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
)))
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
)))
438 let source
= source
.adjust_for_autoref(self.tcx
, reborrow
);
440 let mut selcx
= traits
::SelectionContext
::new(self);
442 // Use a FIFO queue for this custom fulfillment procedure.
443 let mut queue
= VecDeque
::new();
444 let mut leftover_predicates
= vec
![];
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
]));
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(),
460 leftover_predicates
.push(obligation
);
464 match selcx
.select(&obligation
.with(trait_ref
)) {
465 // Uncertain or unimplemented.
467 Err(traits
::Unimplemented
) => {
468 debug
!("coerce_unsized: early return - can't prove obligation");
469 return Err(TypeError
::Mismatch
);
472 // Object safety violations or miscellaneous.
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.
480 Ok(Some(vtable
)) => {
481 for obligation
in vtable
.nested_obligations() {
482 queue
.push_back(obligation
);
488 *self.unsizing_obligations
.borrow_mut() = leftover_predicates
;
490 let adjustment
= Adjust
::DerefRef
{
491 autoderefs
: if reborrow
.is_some() { 1 }
else { 0 }
,
495 debug
!("Success, coerced with {:?}", adjustment
);
496 Ok((target
, adjustment
))
499 fn coerce_from_safe_fn(&self,
501 fn_ty_a
: &'tcx ty
::BareFnTy
<'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
));
514 self.unify_and_identity(a
, b
)
517 fn coerce_from_fn_pointer(&self,
519 fn_ty_a
: &'tcx ty
::BareFnTy
<'tcx
>,
521 -> CoerceResult
<'tcx
> {
522 //! Attempts to coerce from the type of a Rust function item
523 //! into a closure or a `proc`.
526 let b
= self.shallow_resolve(b
);
527 debug
!("coerce_from_fn_pointer(a={:?}, b={:?})", a
, b
);
529 self.coerce_from_safe_fn(a
, fn_ty_a
, b
)
532 fn coerce_from_fn_item(&self,
534 fn_ty_a
: &'tcx ty
::BareFnTy
<'tcx
>,
536 -> CoerceResult
<'tcx
> {
537 //! Attempts to coerce from the type of a Rust function item
538 //! into a closure or a `proc`.
541 let b
= self.shallow_resolve(b
);
542 debug
!("coerce_from_fn_item(a={:?}, b={:?})", a
, b
);
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
))
550 _
=> self.unify_and_identity(a
, b
),
554 fn coerce_unsafe_ptr(&self,
557 mutbl_b
: hir
::Mutability
)
558 -> CoerceResult
<'tcx
> {
559 debug
!("coerce_unsafe_ptr(a={:?}, b={:?})", a
, b
);
561 let (is_ref
, mt_a
) = match a
.sty
{
562 ty
::TyRef(_
, mt
) => (true, mt
),
563 ty
::TyRawPtr(mt
) => (false, mt
),
565 return self.unify_and_identity(a
, b
);
569 // Check that the types which they point at are compatible.
570 let a_unsafe
= self.tcx
.mk_ptr(ty
::TypeAndMut
{
574 let (ty
, noop
) = self.unify_and_identity(a_unsafe
, b
)?
;
575 coerce_mutbls(mt_a
.mutbl
, mutbl_b
)?
;
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.
584 autoref
: Some(AutoBorrow
::RawPtr(mutbl_b
)),
587 } else if mt_a
.mutbl
!= mutbl_b
{
588 Adjust
::MutToConstPointer
595 fn apply
<'a
, 'b
, 'gcx
, 'tcx
, E
, I
>(coerce
: &mut Coerce
<'a
, 'gcx
, 'tcx
>,
599 -> RelateResult
<'tcx
, Adjustment
<'tcx
>>
601 I
: IntoIterator
<Item
= &'b hir
::Expr
>
604 let (ty
, adjust
) = indent(|| coerce
.coerce(exprs
, a
, b
))?
;
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
);
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,
629 -> RelateResult
<'tcx
, Ty
<'tcx
>> {
630 let source
= self.resolve_type_vars_with_obligations(expr_ty
);
631 debug
!("coercion::try({:?}: {:?} -> {:?})", expr
, source
, target
);
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
) {
641 Some(&Adjustment { kind: Adjust::NeverToAny, .. }
) => (),
642 _
=> bug
!("expr already has an adjustment on it!"),
644 self.write_adjustment(expr
.id
, adjustment
);
646 Ok(adjustment
.target
)
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
>,
659 -> RelateResult
<'tcx
, Ty
<'tcx
>>
661 I
: IntoIterator
<Item
= &'b hir
::Expr
>
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
);
668 let trace
= TypeTrace
::types(cause
, true, prev_ty
, new_ty
);
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
))?
;
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
))
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
));
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
,
706 let mut coerce
= Coerce
::new(self, cause
.clone());
707 coerce
.use_lub
= true;
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
));
716 if !adjustment
.is_identity() {
717 self.write_adjustment(new
.id
, adjustment
);
719 return Ok(adjustment
.target
);
721 Err(e
) => first_error
= Some(e
),
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
{
732 autoref
: Some(AutoBorrow
::Ref(_
, mutbl_adj
)),
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
743 Some(Adjust
::NeverToAny
) => true,
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
))
756 match self.commit_if_ok(|_
| apply(&mut coerce
, &exprs
, prev_ty
, new_ty
)) {
758 // Avoid giving strange errors on failed attempts.
759 if let Some(e
) = first_error
{
762 self.commit_if_ok(|_
| {
763 self.lub(true, trace
, &prev_ty
, &new_ty
)
764 .map(|ok
| self.register_infer_ok_obligations(ok
))
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
,
775 }) = tables
.adjustments
.get_mut(&expr
.id
) {
776 *target
= adjustment
.target
;
779 tables
.adjustments
.insert(expr
.id
, adjustment
);
782 Ok(adjustment
.target
)