about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-05-30 19:43:04 +0200
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-06-19 11:06:21 +0200
commit9b47586a47888f24f8f5565731db44480cce7e28 (patch)
treeb5980e6fcd60a107e060426f3f7e963880fff418
parent0b5007e4b7c4ee9a3d0356e54f91ef3def094a0a (diff)
downloadrust-9b47586a47888f24f8f5565731db44480cce7e28.tar.gz
rust-9b47586a47888f24f8f5565731db44480cce7e28.zip
update coercion docs
-rw-r--r--src/librustc_typeck/check/coercion.rs49
1 files changed, 18 insertions, 31 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index dd3f292fb56..aac4466b6ab 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -10,45 +10,30 @@
 //!
 //! 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
+//! useful for freezing mut things (that is, when the expected type is &T
+//! but you have &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/ui/coerce-reborrow-*.rs` tests for
+//! the various `src/test/ui/coerce/*.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
+//! When infering the generic arguments of functions, the argument
+//! order is relevant, which can lead to the following edge case:
 //!
-//!    fn foo<A>(a: A, b: A) { ... }
+//! ```rust
+//! fn foo<T>(a: T, b: T) {
+//!     // ...
+//! }
 //!
-//! 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.
+//! foo(&7i32, &mut 7i32);
+//! // This compiles, as we first infer `T` to be `&i32`,
+//! // and then coerce `&mut 7i32` to `&7i32`.
 //!
-//! ## 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.
+//! foo(&mut 7i32, &7i32);
+//! // This does not compile, as we first infer `T` to be `&mut i32`
+//! // and are then unable to coerce `&7i32` to `&mut i32`.
+//! ```
 
 use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
@@ -96,6 +81,8 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
 
 type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
 
+/// Coercing a mutable reference to an immutable works, while
+/// coercing `&T` to `&mut T` should be forbidden.
 fn coerce_mutbls<'tcx>(
     from_mutbl: hir::Mutability,
     to_mutbl: hir::Mutability,