|
10 | 10 | //!
|
11 | 11 | //! Note that if we are expecting a reference, we will *reborrow*
|
12 | 12 | //! even if the argument provided was already a reference. This is
|
13 |
| -//! useful for freezing mut/const things (that is, when the expected is &T |
14 |
| -//! but you have &const T or &mut T) and also for avoiding the linearity |
| 13 | +//! useful for freezing mut things (that is, when the expected type is &T |
| 14 | +//! but you have &mut T) and also for avoiding the linearity |
15 | 15 | //! of mut things (when the expected is &mut T and you have &mut T). See
|
16 |
| -//! the various `src/test/ui/coerce-reborrow-*.rs` tests for |
| 16 | +//! the various `src/test/ui/coerce/*.rs` tests for |
17 | 17 | //! examples of where this is useful.
|
18 | 18 | //!
|
19 | 19 | //! ## Subtle note
|
20 | 20 | //!
|
21 |
| -//! When deciding what type coercions to consider, we do not attempt to |
22 |
| -//! resolve any type variables we may encounter. This is because `b` |
23 |
| -//! represents the expected type "as the user wrote it", meaning that if |
24 |
| -//! the user defined a generic function like |
| 21 | +//! When infering the generic arguments of functions, the argument |
| 22 | +//! order is relevant, which can lead to the following edge case: |
25 | 23 | //!
|
26 |
| -//! fn foo<A>(a: A, b: A) { ... } |
| 24 | +//! ```rust |
| 25 | +//! fn foo<T>(a: T, b: T) { |
| 26 | +//! // ... |
| 27 | +//! } |
27 | 28 | //!
|
28 |
| -//! and then we wrote `foo(&1, @2)`, we will not auto-borrow |
29 |
| -//! either argument. In older code we went to some lengths to |
30 |
| -//! resolve the `b` variable, which could mean that we'd |
31 |
| -//! auto-borrow later arguments but not earlier ones, which |
32 |
| -//! seems very confusing. |
| 29 | +//! foo(&7i32, &mut 7i32); |
| 30 | +//! // This compiles, as we first infer `T` to be `&i32`, |
| 31 | +//! // and then coerce `&mut 7i32` to `&7i32`. |
33 | 32 | //!
|
34 |
| -//! ## Subtler note |
35 |
| -//! |
36 |
| -//! However, right now, if the user manually specifies the |
37 |
| -//! values for the type variables, as so: |
38 |
| -//! |
39 |
| -//! foo::<&int>(@1, @2) |
40 |
| -//! |
41 |
| -//! then we *will* auto-borrow, because we can't distinguish this from a |
42 |
| -//! function that declared `&int`. This is inconsistent but it's easiest |
43 |
| -//! at the moment. The right thing to do, I think, is to consider the |
44 |
| -//! *unsubstituted* type when deciding whether to auto-borrow, but the |
45 |
| -//! *substituted* type when considering the bounds and so forth. But most |
46 |
| -//! of our methods don't give access to the unsubstituted type, and |
47 |
| -//! rightly so because they'd be error-prone. So maybe the thing to do is |
48 |
| -//! to actually determine the kind of coercions that should occur |
49 |
| -//! separately and pass them in. Or maybe it's ok as is. Anyway, it's |
50 |
| -//! sort of a minor point so I've opted to leave it for later -- after all, |
51 |
| -//! we may want to adjust precisely when coercions occur. |
| 33 | +//! foo(&mut 7i32, &7i32); |
| 34 | +//! // This does not compile, as we first infer `T` to be `&mut i32` |
| 35 | +//! // and are then unable to coerce `&7i32` to `&mut i32`. |
| 36 | +//! ``` |
52 | 37 |
|
53 | 38 | use crate::astconv::AstConv;
|
54 | 39 | use crate::check::{FnCtxt, Needs};
|
@@ -96,6 +81,8 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
|
96 | 81 |
|
97 | 82 | type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
|
98 | 83 |
|
| 84 | +/// Coercing a mutable reference to an immutable works, while |
| 85 | +/// coercing `&T` to `&mut T` should be forbidden. |
99 | 86 | fn coerce_mutbls<'tcx>(
|
100 | 87 | from_mutbl: hir::Mutability,
|
101 | 88 | to_mutbl: hir::Mutability,
|
|
0 commit comments