Auto merge of #117590 - matthiaskrgr:rollup-9cqh1q8, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #110340 (Deref docs: expand and remove "smart pointer" qualifier) - #116894 (Guarantee that `char` has the same size and alignment as `u32`) - #117534 (clarify that the str invariant is a safety, not validity, invariant) - #117562 (triagebot no-merges: exclude different case) - #117570 (fallback for `construct_generic_bound_failure`) - #117583 (Remove `'tcx` lifetime on `PlaceholderConst`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4b85902b43
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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)
|
||||
|
@ -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>;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
@ -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,
|
||||
@ -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,
|
||||
}
|
||||
@ -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 {
|
||||
|
@ -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);
|
||||
@ -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);
|
||||
|
@ -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
|
||||
///
|
||||
@ -107,30 +174,29 @@ 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.
|
||||
/// ["mutable deref coercion"][coercion]. 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.
|
||||
/// **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.
|
||||
///
|
||||
/// For similar reasons, **this trait should never fail**. Failure during
|
||||
/// dereferencing can be extremely confusing when `DerefMut` is invoked
|
||||
/// implicitly.
|
||||
/// 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]).
|
||||
///
|
||||
/// 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.
|
||||
/// # Mutable deref coercion
|
||||
///
|
||||
/// # More on `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`.
|
||||
///
|
||||
@ -138,11 +204,29 @@ impl<T: ?Sized> Deref for &mut T {
|
||||
/// 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
|
||||
///
|
||||
|
@ -283,7 +283,7 @@ mod prim_never {}
|
||||
/// `char` type. For technical reasons, there is additional, separate
|
||||
/// documentation in [the `std::char` module](char/index.html) as well.
|
||||
///
|
||||
/// # Validity
|
||||
/// # Validity and Layout
|
||||
///
|
||||
/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]'
|
||||
/// other than a [surrogate code point]. This has a fixed numerical definition:
|
||||
@ -291,7 +291,7 @@ mod prim_never {}
|
||||
/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF.
|
||||
///
|
||||
/// No `char` may be constructed, whether as a literal or at runtime, that is not a
|
||||
/// Unicode scalar value:
|
||||
/// Unicode scalar value. Violating this rule causes undefined behavior.
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// // Each of these is a compiler error
|
||||
@ -308,9 +308,10 @@ mod prim_never {}
|
||||
/// let _ = unsafe { char::from_u32_unchecked(0x110000) };
|
||||
/// ```
|
||||
///
|
||||
/// USVs are also the exact set of values that may be encoded in UTF-8. Because
|
||||
/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store
|
||||
/// any `char` in a `str` or read any character from a `str` as a `char`.
|
||||
/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because
|
||||
/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are
|
||||
/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read
|
||||
/// any character from a `str` as a `char`.
|
||||
///
|
||||
/// The gap in valid `char` values is understood by the compiler, so in the
|
||||
/// below example the two ranges are understood to cover the whole range of
|
||||
@ -324,11 +325,17 @@ mod prim_never {}
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// All USVs are valid `char` values, but not all of them represent a real
|
||||
/// character. Many USVs are not currently assigned to a character, but may be
|
||||
/// in the future ("reserved"); some will never be a character
|
||||
/// ("noncharacters"); and some may be given different meanings by different
|
||||
/// users ("private use").
|
||||
/// All Unicode scalar values are valid `char` values, but not all of them represent a real
|
||||
/// character. Many Unicode scalar values are not currently assigned to a character, but may be in
|
||||
/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given
|
||||
/// different meanings by different users ("private use").
|
||||
///
|
||||
/// `char` is guaranteed to have the same size and alignment as `u32` on all
|
||||
/// platforms.
|
||||
/// ```
|
||||
/// use std::alloc::Layout;
|
||||
/// assert_eq!(Layout::new::<char>(), Layout::new::<u32>());
|
||||
/// ```
|
||||
///
|
||||
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
|
||||
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
|
||||
@ -887,8 +894,6 @@ mod prim_slice {}
|
||||
/// type. It is usually seen in its borrowed form, `&str`. It is also the type
|
||||
/// of string literals, `&'static str`.
|
||||
///
|
||||
/// String slices are always valid UTF-8.
|
||||
///
|
||||
/// # Basic Usage
|
||||
///
|
||||
/// String literals are string slices:
|
||||
@ -942,6 +947,14 @@ mod prim_slice {}
|
||||
/// Note: This example shows the internals of `&str`. `unsafe` should not be
|
||||
/// used to get a string slice under normal circumstances. Use `as_str`
|
||||
/// instead.
|
||||
///
|
||||
/// # Invariant
|
||||
///
|
||||
/// Rust libraries may assume that string slices are always valid UTF-8.
|
||||
///
|
||||
/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function
|
||||
/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string
|
||||
/// slice can lead to undefined behavior down the road.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
mod prim_str {}
|
||||
|
||||
|
11
tests/ui/impl-trait/in-trait/async-and-ret-ref.rs
Normal file
11
tests/ui/impl-trait/in-trait/async-and-ret-ref.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// edition:2021
|
||||
// https://github.com/rust-lang/rust/issues/117547
|
||||
|
||||
trait T {}
|
||||
|
||||
trait MyTrait {
|
||||
async fn foo() -> &'static impl T;
|
||||
//~^ ERROR the associated type `<Self as MyTrait>::{opaque#0}` may not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr
Normal file
14
tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0310]: the associated type `<Self as MyTrait>::{opaque#0}` may not live long enough
|
||||
--> $DIR/async-and-ret-ref.rs:7:5
|
||||
|
|
||||
LL | async fn foo() -> &'static impl T;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the associated type `<Self as MyTrait>::{opaque#0}` must be valid for the static lifetime...
|
||||
| ...so that the reference type `&'static impl T` does not outlive the data it points at
|
||||
|
|
||||
= help: consider adding an explicit lifetime bound `<Self as MyTrait>::{opaque#0}: 'static`...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
@ -415,7 +415,7 @@ Issue #{number} "{title}" has been added.
|
||||
"""
|
||||
|
||||
[no-merges]
|
||||
exclude_titles = ["Rollup of", "subtree update"]
|
||||
exclude_titles = ["Rollup of", "subtree update", "Subtree update"]
|
||||
labels = ["has-merge-commits", "S-waiting-on-author"]
|
||||
|
||||
[github-releases]
|
||||
|
Loading…
x
Reference in New Issue
Block a user