Skip to content

Commit

Permalink
Auto merge of rust-lang#117590 - matthiaskrgr:rollup-9cqh1q8, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#110340 (Deref docs: expand and remove "smart pointer" qualifier)
 - rust-lang#116894 (Guarantee that `char` has the same size and alignment as `u32`)
 - rust-lang#117534 (clarify that the str invariant is a safety, not validity, invariant)
 - rust-lang#117562 (triagebot no-merges: exclude different case)
 - rust-lang#117570 (fallback for `construct_generic_bound_failure`)
 - rust-lang#117583 (Remove `'tcx` lifetime on `PlaceholderConst`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 4, 2023
2 parents a42d94e + 8912a2b commit 4b85902
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 71 deletions.
20 changes: 12 additions & 8 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2444,18 +2444,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let suggestion =
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
suggs.push((sp, suggestion))
} else {
let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap();
} else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) {
let pred = format!("{bound_kind}: {lt_name}");
let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,);
let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred);
suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
} else {
let consider = format!("{msg} `{bound_kind}: {sub}`...");
err.help(consider);
}

err.multipart_suggestion_verbose(
format!("{msg}"),
suggs,
Applicability::MaybeIncorrect, // Issue #41966
);
if !suggs.is_empty() {
err.multipart_suggestion_verbose(
format!("{msg}"),
suggs,
Applicability::MaybeIncorrect, // Issue #41966
);
}
}

err
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub enum CanonicalVarKind<'tcx> {
Effect,

/// A "placeholder" that represents "any const".
PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>),
PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>),
}

impl<'tcx> CanonicalVarKind<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn new_placeholder(
tcx: TyCtxt<'tcx>,
placeholder: ty::PlaceholderConst<'tcx>,
placeholder: ty::PlaceholderConst,
ty: Ty<'tcx>,
) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type Const = ty::Const<'tcx>;
type InferConst = ty::InferConst;
type AliasConst = ty::UnevaluatedConst<'tcx>;
type PlaceholderConst = ty::PlaceholderConst<'tcx>;
type PlaceholderConst = ty::PlaceholderConst;
type ParamConst = ty::ParamConst;
type BoundConst = ty::BoundVar;
type ValueConst = ty::ValTree<'tcx>;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,7 @@ pub struct BoundConst<'tcx> {
pub ty: Ty<'tcx>,
}

pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
pub type PlaceholderConst = Placeholder<BoundVar>;

/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ pub struct BoundVarReplacer<'me, 'tcx> {
// the `var` (but we *could* bring that into scope if we were to track them as we pass them).
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
// The current depth relative to *this* folding, *not* the entire normalization. In other words,
// the depth of binders we've passed here.
current_index: ty::DebruijnIndex,
Expand Down Expand Up @@ -843,11 +843,11 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
T,
BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
BTreeMap<ty::PlaceholderType, ty::BoundTy>,
BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
) {
let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new();
let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new();
let mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar> = BTreeMap::new();
let mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar> = BTreeMap::new();

let mut replacer = BoundVarReplacer {
infcx,
Expand Down Expand Up @@ -966,7 +966,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
universe_indices: &'me [Option<ty::UniverseIndex>],
current_index: ty::DebruijnIndex,
}
Expand All @@ -976,7 +976,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>,
universe_indices: &'me [Option<ty::UniverseIndex>],
value: T,
) -> T {
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub const fn identity<T>(x: T) -> T {
///
/// [dereferenceable types]: core::ops::Deref
/// [pointed-to value]: core::ops::Deref::Target
/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion
/// ['`Deref` coercion']: core::ops::Deref#deref-coercion
///
/// ```
/// let x = Box::new(5i32);
Expand Down Expand Up @@ -244,7 +244,7 @@ pub trait AsRef<T: ?Sized> {
///
/// [mutably dereferenceable types]: core::ops::DerefMut
/// [pointed-to value]: core::ops::Deref::Target
/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion
/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion
///
/// ```
/// let mut x = Box::new(5i32);
Expand Down
162 changes: 123 additions & 39 deletions library/core/src/ops/deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,107 @@
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and
/// mutable deref coercion similarly occurs.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accommodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
/// **Warning:** Deref coercion is a powerful language feature which has
/// far-reaching implications for every type that implements `Deref`. The
/// compiler will silently insert calls to `Deref::deref`. For this reason, one
/// should be careful about implementing `Deref` and only do so when deref
/// coercion is desirable. See [below][implementing] for advice on when this is
/// typically desirable or undesirable.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
/// Types that implement `Deref` or `DerefMut` are often called "smart
/// pointers" and the mechanism of deref coercion has been specifically designed
/// to facilitate the pointer-like behaviour that name suggests. Often, the
/// purpose of a "smart pointer" type is to change the ownership semantics
/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
/// storage semantics of a contained value (for example, [`Box`][box]).
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
/// method.
/// # Deref coercion
///
/// # More on `Deref` coercion
/// If `T` implements `Deref<Target = U>`, and `v` is a value of type `T`, then:
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
/// is equivalent to `*Deref::deref(&x)`.
/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw
/// pointer) is equivalent to `*Deref::deref(&v)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
/// * `T` implicitly implements all the methods of the type `U` which take the
/// `&self` receiver.
///
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
/// as well as the reference sections on [the dereference operator][ref-deref-op],
/// [method resolution] and [type coercions].
/// [method resolution], and [type coercions].
///
/// # When to implement `Deref` or `DerefMut`
///
/// The same advice applies to both deref traits. In general, deref traits
/// **should** be implemented if:
///
/// 1. a value of the type transparently behaves like a value of the target
/// type;
/// 1. the implementation of the deref function is cheap; and
/// 1. users of the type will not be surprised by any deref coercion behaviour.
///
/// In general, deref traits **should not** be implemented if:
///
/// 1. the deref implementations could fail unexpectedly; or
/// 1. the type has methods that are likely to collide with methods on the
/// target type; or
/// 1. committing to deref coercion as part of the public API is not desirable.
///
/// Note that there's a large difference between implementing deref traits
/// generically over many target types, and doing so only for specific target
/// types.
///
/// Generic implementations, such as for [`Box<T>`][box] (which is generic over
/// every type and dereferences to `T`) should be careful to provide few or no
/// methods, since the target type is unknown and therefore every method could
/// collide with one on the target type, causing confusion for users.
/// `impl<T> Box<T>` has no methods (though several associated functions),
/// partly for this reason.
///
/// Specific implementations, such as for [`String`][string] (whose `Deref`
/// implementation has `Target = str`) can have many methods, since avoiding
/// collision is much easier. `String` and `str` both have many methods, and
/// `String` additionally behaves as if it has every method of `str` because of
/// deref coercion. The implementing type may also be generic while the
/// implementation is still specific in this sense; for example, [`Vec<T>`][vec]
/// dereferences to `[T]`, so methods of `T` are not applicable.
///
/// Consider also that deref coericion means that deref traits are a much larger
/// part of a type's public API than any other trait as it is implicitly called
/// by the compiler. Therefore, it is advisable to consider whether this is
/// something you are comfortable supporting as a public API.
///
/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar
/// signatures to `Deref`. It may be desirable to implement either or both of
/// these, whether in addition to or rather than deref traits. See their
/// documentation for details.
///
/// # Fallibility
///
/// **This trait's method should never unexpectedly fail**. Deref coercion means
/// the compiler will often insert calls to `Deref::deref` implicitly. Failure
/// during dereferencing can be extremely confusing when `Deref` is invoked
/// implicitly. In the majority of uses it should be infallible, though it may
/// be acceptable to panic if the type is misused through programmer error, for
/// example.
///
/// However, infallibility is not enforced and therefore not guaranteed.
/// As such, `unsafe` code should not rely on infallibility in general for
/// soundness.
///
/// [book]: ../../book/ch15-02-deref.html
/// [more]: #more-on-deref-coercion
/// [coercion]: #deref-coercion
/// [implementing]: #when-to-implement-deref-or-derefmut
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
/// [box]: ../../alloc/boxed/struct.Box.html
/// [string]: ../../alloc/string/struct.String.html
/// [vec]: ../../alloc/vec/struct.Vec.html
/// [rc]: ../../alloc/rc/struct.Rc.html
/// [cow]: ../../alloc/borrow/enum.Cow.html
///
/// # Examples
///
Expand Down Expand Up @@ -107,42 +174,59 @@ impl<T: ?Sized> Deref for &mut T {
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
/// **Warning:** Deref coercion is a powerful language feature which has
/// far-reaching implications for every type that implements `DerefMut`. The
/// compiler will silently insert calls to `DerefMut::deref_mut`. For this
/// reason, one should be careful about implementing `DerefMut` and only do so
/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing]
/// for advice on when this is typically desirable or undesirable.
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
/// method.
/// Types that implement `DerefMut` or `Deref` are often called "smart
/// pointers" and the mechanism of deref coercion has been specifically designed
/// to facilitate the pointer-like behaviour that name suggests. Often, the
/// purpose of a "smart pointer" type is to change the ownership semantics
/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
/// storage semantics of a contained value (for example, [`Box`][box]).
///
/// # More on `Deref` coercion
/// # Mutable deref coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// If `T` implements `DerefMut<Target = U>`, and `v` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
/// is equivalent to `*DerefMut::deref_mut(&mut x)`.
/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer)
/// is equivalent to `*DerefMut::deref_mut(&mut v)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
/// as well as the reference sections on [the dereference operator][ref-deref-op],
/// [method resolution] and [type coercions].
///
/// # Fallibility
///
/// **This trait's method should never unexpectedly fail**. Deref coercion means
/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly.
/// Failure during dereferencing can be extremely confusing when `DerefMut` is
/// invoked implicitly. In the majority of uses it should be infallible, though
/// it may be acceptable to panic if the type is misused through programmer
/// error, for example.
///
/// However, infallibility is not enforced and therefore not guaranteed.
/// As such, `unsafe` code should not rely on infallibility in general for
/// soundness.
///
/// [book]: ../../book/ch15-02-deref.html
/// [more]: #more-on-deref-coercion
/// [coercion]: #mutable-deref-coercion
/// [implementing]: Deref#when-to-implement-deref-or-derefmut
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
/// [box]: ../../alloc/boxed/struct.Box.html
/// [string]: ../../alloc/string/struct.String.html
/// [rc]: ../../alloc/rc/struct.Rc.html
/// [cow]: ../../alloc/borrow/enum.Cow.html
///
/// # Examples
///
Expand Down
Loading

0 comments on commit 4b85902

Please sign in to comment.