mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #149510 - matthiaskrgr:rollup-5rt6o7z, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang/rust#148690 (Implement `clamp_magnitude` method for primitive floats & signed integers) - rust-lang/rust#149102 (stabilize maybe_uninit_slice) - rust-lang/rust#149269 (cmse: do not calculate the layout of a type with infer types) - rust-lang/rust#149299 (Fudge infer vars in the cause code of `Obligation` intentionally) - rust-lang/rust#149344 (Don't suggest unwrap for Result in const) - rust-lang/rust#149358 (fix(parse): Limit frontmatter fences to 255 dashes ) - rust-lang/rust#149445 (make assoc fn inherit const stability from inherent `const impl` blocks) - rust-lang/rust#149479 (Fix indent in E0591.md) - rust-lang/rust#149496 (Fix rust-lang/rust#148889: Add label rib when visiting delegation body) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -10,13 +10,13 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine.
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(maybe_uninit_slice))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![doc(test(no_crate_inject, attr(deny(warnings), allow(internal_features))))]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(unwrap_infallible)]
|
||||
|
||||
@@ -62,14 +62,14 @@ This pattern should be rewritten. There are a few possible ways to do this:
|
||||
and do the cast in the fn body (the preferred option)
|
||||
- cast the fn item of a fn pointer before calling transmute, as shown here:
|
||||
|
||||
```
|
||||
# extern "C" fn foo(_: Box<i32>) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
# }
|
||||
```
|
||||
```
|
||||
# extern "C" fn foo(_: Box<i32>) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
# }
|
||||
```
|
||||
|
||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||
Note though that use of this type is generally incorrect.
|
||||
|
||||
@@ -86,6 +86,11 @@ fn is_valid_cmse_inputs<'tcx>(
|
||||
let fn_sig = tcx.erase_and_anonymize_regions(fn_sig);
|
||||
|
||||
for (ty, hir_ty) in fn_sig.inputs().iter().zip(fn_decl.inputs) {
|
||||
if ty.has_infer_types() {
|
||||
let err = LayoutError::Unknown(*ty);
|
||||
return Err((hir_ty.span, tcx.arena.alloc(err)));
|
||||
}
|
||||
|
||||
let layout = tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))
|
||||
.map_err(|e| (hir_ty.span, e))?;
|
||||
@@ -138,6 +143,11 @@ fn is_valid_cmse_output<'tcx>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if return_type.has_infer_types() {
|
||||
let err = LayoutError::Unknown(return_type);
|
||||
return Err(tcx.arena.alloc(err));
|
||||
}
|
||||
|
||||
let typing_env = ty::TypingEnv::fully_monomorphized();
|
||||
let layout = tcx.layout_of(typing_env.as_query_input(return_type))?;
|
||||
|
||||
|
||||
@@ -2106,14 +2106,16 @@ pub(crate) fn suggest_missing_unwrap_expect(
|
||||
)),
|
||||
);
|
||||
|
||||
let (article, kind, variant, sugg_operator) =
|
||||
if self.tcx.is_diagnostic_item(sym::Result, adt.did()) {
|
||||
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
||||
} else if self.tcx.is_diagnostic_item(sym::Option, adt.did()) {
|
||||
("an", "Option", "None", ret_ty_matches(sym::Option))
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
let (article, kind, variant, sugg_operator) = if self.tcx.is_diagnostic_item(sym::Result, adt.did())
|
||||
// Do not suggest `.expect()` in const context where it's not available. rust-lang/rust#149316
|
||||
&& !self.tcx.hir_is_inside_const_context(expr.hir_id)
|
||||
{
|
||||
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
||||
} else if self.tcx.is_diagnostic_item(sym::Option, adt.did()) {
|
||||
("an", "Option", "None", ret_ty_matches(sym::Option))
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
if is_ctor || !self.may_coerce(args.type_at(0), expected) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3041,14 +3041,16 @@ fn suggest_unwrapping_inner_self(
|
||||
tcx.def_span(pick.item.def_id),
|
||||
format!("the method `{item_name}` exists on the type `{self_ty}`"),
|
||||
);
|
||||
let (article, kind, variant, question) =
|
||||
if tcx.is_diagnostic_item(sym::Result, kind.did()) {
|
||||
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
||||
} else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
|
||||
("an", "Option", "None", ret_ty_matches(sym::Option))
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let (article, kind, variant, question) = if tcx.is_diagnostic_item(sym::Result, kind.did())
|
||||
// Do not suggest `.expect()` in const context where it's not available. rust-lang/rust#149316
|
||||
&& !tcx.hir_is_inside_const_context(expr.hir_id)
|
||||
{
|
||||
("a", "Result", "Err", ret_ty_matches(sym::Result))
|
||||
} else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
|
||||
("an", "Option", "None", ret_ty_matches(sym::Option))
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
if question {
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#[derive(Clone, TypeFoldable, TypeVisitable)]
|
||||
pub struct Obligation<'tcx, T> {
|
||||
/// The reason we have to prove this thing.
|
||||
/// FIXME: we shouldn't ignore the cause but instead change the affected visitors
|
||||
/// to only visit predicates manually.
|
||||
#[type_foldable(identity)]
|
||||
#[type_visitable(ignore)]
|
||||
pub cause: ObligationCause<'tcx>,
|
||||
|
||||
@@ -347,6 +347,7 @@ parse_frontmatter_invalid_opening_preceding_whitespace = invalid preceding white
|
||||
parse_frontmatter_length_mismatch = frontmatter close does not match the opening
|
||||
.label_opening = the opening here has {$len_opening} dashes...
|
||||
.label_close = ...while the close has {$len_close} dashes
|
||||
parse_frontmatter_too_many_dashes = too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening}
|
||||
parse_frontmatter_unclosed = unclosed frontmatter
|
||||
.note = frontmatter opening here was not closed
|
||||
|
||||
|
||||
@@ -822,6 +822,12 @@ pub(crate) struct FrontmatterLengthMismatch {
|
||||
pub len_close: usize,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_frontmatter_too_many_dashes)]
|
||||
pub(crate) struct FrontmatterTooManyDashes {
|
||||
pub len_opening: usize,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_leading_plus_not_supported)]
|
||||
pub(crate) struct LeadingPlusNotSupported {
|
||||
|
||||
@@ -665,6 +665,11 @@ fn validate_frontmatter(
|
||||
});
|
||||
}
|
||||
|
||||
// Only up to 255 `-`s are allowed in code fences
|
||||
if u8::try_from(len_opening).is_err() {
|
||||
self.dcx().emit_err(errors::FrontmatterTooManyDashes { len_opening });
|
||||
}
|
||||
|
||||
if !rest.trim_matches(is_horizontal_whitespace).is_empty() {
|
||||
let span = self.mk_sp(last_line_start_pos, self.pos);
|
||||
self.dcx().emit_err(errors::FrontmatterExtraCharactersAfterClose { span });
|
||||
|
||||
@@ -54,7 +54,7 @@ fn inherit_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
match def_kind {
|
||||
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||
match tcx.def_kind(tcx.local_parent(def_id)) {
|
||||
DefKind::Impl { of_trait: true } => true,
|
||||
DefKind::Impl { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3689,7 +3689,11 @@ fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
|
||||
let ident = Ident::new(kw::SelfLower, span.normalize_to_macro_rules());
|
||||
let res = Res::Local(delegation.id);
|
||||
this.innermost_rib_bindings(ValueNS).insert(ident, res);
|
||||
this.visit_block(body);
|
||||
|
||||
//As we lower target_expr_template body to a body of a function we need a label rib (#148889)
|
||||
this.with_label_rib(RibKind::FnOrCoroutine, |this| {
|
||||
this.visit_block(body);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,11 @@ fn find_best_leaf_obligation<'tcx>(
|
||||
)
|
||||
.break_value()
|
||||
.ok_or(())
|
||||
// walk around the fact that the cause in `Obligation` is ignored by folders so that
|
||||
// we can properly fudge the infer vars in cause code.
|
||||
.map(|o| (o.cause.clone(), o))
|
||||
})
|
||||
.map(|(cause, o)| PredicateObligation { cause, ..o })
|
||||
.unwrap_or(obligation);
|
||||
deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
|
||||
}
|
||||
|
||||
@@ -127,7 +127,6 @@
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(legacy_receiver_trait)]
|
||||
#![feature(local_waker)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pattern)]
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#![feature(inplace_iteration)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_next_chunk)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||
#![feature(ptr_alignment_type)]
|
||||
#![feature(ptr_internals)]
|
||||
|
||||
@@ -114,16 +114,10 @@ fn push(&mut self, value: T) {
|
||||
impl<'a, T> Drop for InitializingSlice<'a, T> {
|
||||
#[cold] // will only be invoked on unwind
|
||||
fn drop(&mut self) {
|
||||
let initialized_slice = ptr::slice_from_raw_parts_mut(
|
||||
MaybeUninit::slice_as_mut_ptr(self.data),
|
||||
self.initialized_len,
|
||||
);
|
||||
// SAFETY:
|
||||
// * the pointer is valid because it was made from a mutable reference
|
||||
// * `initialized_len` counts the initialized elements as an invariant of this type,
|
||||
// so each of the pointed-to elements is initialized and may be dropped.
|
||||
unsafe {
|
||||
ptr::drop_in_place::<[T]>(initialized_slice);
|
||||
}
|
||||
unsafe { self.data[..self.initialized_len].assume_init_drop() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1047,7 +1047,7 @@ pub const fn as_mut_ptr(&mut self) -> *mut T {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
|
||||
/// #![feature(maybe_uninit_as_bytes)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let val = 0x12345678_i32;
|
||||
@@ -1097,20 +1097,6 @@ pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
this.as_ptr() as *const T
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
|
||||
this.as_mut_ptr() as *mut T
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> [MaybeUninit<T>] {
|
||||
@@ -1410,7 +1396,7 @@ pub fn write_iter<I>(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit<T>])
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
|
||||
/// #![feature(maybe_uninit_as_bytes)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let uninit = [MaybeUninit::new(0x1234u16), MaybeUninit::new(0x5678u16)];
|
||||
@@ -1437,7 +1423,7 @@ pub const fn as_bytes(&self) -> &[MaybeUninit<u8>] {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
|
||||
/// #![feature(maybe_uninit_as_bytes)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
|
||||
@@ -1477,7 +1463,7 @@ pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
/// requirement the compiler knows about it is that the data pointer must be
|
||||
/// non-null. Dropping such a `Vec<T>` however will cause undefined
|
||||
/// behaviour.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[stable(feature = "maybe_uninit_slice", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline(always)]
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn assume_init_drop(&mut self)
|
||||
@@ -1499,7 +1485,8 @@ pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
/// Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in
|
||||
/// the slice really is in an initialized state.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[stable(feature = "maybe_uninit_slice", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "maybe_uninit_slice", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn assume_init_ref(&self) -> &[T] {
|
||||
// SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that
|
||||
@@ -1517,7 +1504,8 @@ pub const fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
|
||||
/// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
|
||||
/// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
|
||||
/// be used to initialize a `MaybeUninit` slice.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[stable(feature = "maybe_uninit_slice", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "maybe_uninit_slice", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline(always)]
|
||||
pub const unsafe fn assume_init_mut(&mut self) -> &mut [T] {
|
||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||
|
||||
@@ -1291,6 +1291,38 @@ pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
|
||||
self
|
||||
}
|
||||
|
||||
/// Clamps this number to a symmetric range centered around zero.
|
||||
///
|
||||
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
|
||||
///
|
||||
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
|
||||
/// explicit about the intent.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(clamp_magnitude)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// assert_eq!(5.0f128.clamp_magnitude(3.0), 3.0);
|
||||
/// assert_eq!((-5.0f128).clamp_magnitude(3.0), -3.0);
|
||||
/// assert_eq!(2.0f128.clamp_magnitude(3.0), 2.0);
|
||||
/// assert_eq!((-2.0f128).clamp_magnitude(3.0), -2.0);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "clamp_magnitude", issue = "148519")]
|
||||
#[must_use = "this returns the clamped value and does not modify the original"]
|
||||
pub fn clamp_magnitude(self, limit: f128) -> f128 {
|
||||
assert!(limit >= 0.0, "limit must be non-negative");
|
||||
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
|
||||
self.clamp(-limit, limit)
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
|
||||
@@ -1269,6 +1269,38 @@ pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
|
||||
self
|
||||
}
|
||||
|
||||
/// Clamps this number to a symmetric range centered around zero.
|
||||
///
|
||||
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
|
||||
///
|
||||
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
|
||||
/// explicit about the intent.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// #![feature(clamp_magnitude)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
/// assert_eq!(5.0f16.clamp_magnitude(3.0), 3.0);
|
||||
/// assert_eq!((-5.0f16).clamp_magnitude(3.0), -3.0);
|
||||
/// assert_eq!(2.0f16.clamp_magnitude(3.0), 2.0);
|
||||
/// assert_eq!((-2.0f16).clamp_magnitude(3.0), -2.0);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "clamp_magnitude", issue = "148519")]
|
||||
#[must_use = "this returns the clamped value and does not modify the original"]
|
||||
pub fn clamp_magnitude(self, limit: f16) -> f16 {
|
||||
assert!(limit >= 0.0, "limit must be non-negative");
|
||||
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
|
||||
self.clamp(-limit, limit)
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
|
||||
@@ -1446,6 +1446,35 @@ pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
|
||||
self
|
||||
}
|
||||
|
||||
/// Clamps this number to a symmetric range centered around zero.
|
||||
///
|
||||
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
|
||||
///
|
||||
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
|
||||
/// explicit about the intent.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(clamp_magnitude)]
|
||||
/// assert_eq!(5.0f32.clamp_magnitude(3.0), 3.0);
|
||||
/// assert_eq!((-5.0f32).clamp_magnitude(3.0), -3.0);
|
||||
/// assert_eq!(2.0f32.clamp_magnitude(3.0), 2.0);
|
||||
/// assert_eq!((-2.0f32).clamp_magnitude(3.0), -2.0);
|
||||
/// ```
|
||||
#[must_use = "this returns the clamped value and does not modify the original"]
|
||||
#[unstable(feature = "clamp_magnitude", issue = "148519")]
|
||||
#[inline]
|
||||
pub fn clamp_magnitude(self, limit: f32) -> f32 {
|
||||
assert!(limit >= 0.0, "limit must be non-negative");
|
||||
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
|
||||
self.clamp(-limit, limit)
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
|
||||
@@ -1444,6 +1444,35 @@ pub const fn clamp(mut self, min: f64, max: f64) -> f64 {
|
||||
self
|
||||
}
|
||||
|
||||
/// Clamps this number to a symmetric range centered around zero.
|
||||
///
|
||||
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
|
||||
///
|
||||
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
|
||||
/// explicit about the intent.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `limit` is negative or NaN, as this indicates a logic error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(clamp_magnitude)]
|
||||
/// assert_eq!(5.0f64.clamp_magnitude(3.0), 3.0);
|
||||
/// assert_eq!((-5.0f64).clamp_magnitude(3.0), -3.0);
|
||||
/// assert_eq!(2.0f64.clamp_magnitude(3.0), 2.0);
|
||||
/// assert_eq!((-2.0f64).clamp_magnitude(3.0), -2.0);
|
||||
/// ```
|
||||
#[must_use = "this returns the clamped value and does not modify the original"]
|
||||
#[unstable(feature = "clamp_magnitude", issue = "148519")]
|
||||
#[inline]
|
||||
pub fn clamp_magnitude(self, limit: f64) -> f64 {
|
||||
assert!(limit >= 0.0, "limit must be non-negative");
|
||||
let limit = limit.abs(); // Canonicalises -0.0 to 0.0
|
||||
self.clamp(-limit, limit)
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
|
||||
@@ -3878,5 +3878,32 @@ pub const fn min_value() -> Self {
|
||||
pub const fn max_value() -> Self {
|
||||
Self::MAX
|
||||
}
|
||||
|
||||
/// Clamps this number to a symmetric range centred around zero.
|
||||
///
|
||||
/// The method clamps the number's magnitude (absolute value) to be at most `limit`.
|
||||
///
|
||||
/// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more
|
||||
/// explicit about the intent.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(clamp_magnitude)]
|
||||
#[doc = concat!("assert_eq!(120", stringify!($SelfT), ".clamp_magnitude(100), 100);")]
|
||||
#[doc = concat!("assert_eq!(-120", stringify!($SelfT), ".clamp_magnitude(100), -100);")]
|
||||
#[doc = concat!("assert_eq!(80", stringify!($SelfT), ".clamp_magnitude(100), 80);")]
|
||||
#[doc = concat!("assert_eq!(-80", stringify!($SelfT), ".clamp_magnitude(100), -80);")]
|
||||
/// ```
|
||||
#[must_use = "this returns the clamped value and does not modify the original"]
|
||||
#[unstable(feature = "clamp_magnitude", issue = "148519")]
|
||||
#[inline]
|
||||
pub fn clamp_magnitude(self, limit: $UnsignedT) -> Self {
|
||||
if let Ok(limit) = core::convert::TryInto::<$SelfT>::try_into(limit) {
|
||||
self.clamp(-limit, limit)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ pub fn merge<T, F: FnMut(&T, &T) -> bool>(
|
||||
// 1. Protects integrity of `v` from panics in `is_less`.
|
||||
// 2. Fills the remaining gap in `v` if the longer run gets consumed first.
|
||||
|
||||
let buf = MaybeUninit::slice_as_mut_ptr(scratch);
|
||||
let buf = scratch.as_mut_ptr().cast_init();
|
||||
|
||||
let v_base = v.as_mut_ptr();
|
||||
let v_mid = v_base.add(mid);
|
||||
|
||||
@@ -97,7 +97,7 @@ fn stable_partition<T, F: FnMut(&T, &T) -> bool>(
|
||||
}
|
||||
|
||||
let v_base = v.as_ptr();
|
||||
let scratch_base = MaybeUninit::slice_as_mut_ptr(scratch);
|
||||
let scratch_base = scratch.as_mut_ptr().cast_init();
|
||||
|
||||
// The core idea is to write the values that compare as less-than to the left
|
||||
// side of `scratch`, while the values that compared as greater or equal than
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#![feature(cfg_target_has_reliable_f16_f128)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(char_max_len)]
|
||||
#![feature(clamp_magnitude)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(const_array)]
|
||||
#![feature(const_cell_traits)]
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
macro_rules! check_int_clamp {
|
||||
($t:ty, $ut:ty) => {
|
||||
let min = <$t>::MIN;
|
||||
let max = <$t>::MAX;
|
||||
let max_u = <$ut>::MAX;
|
||||
|
||||
// Basic clamping
|
||||
assert_eq!((100 as $t).clamp_magnitude(50), 50);
|
||||
assert_eq!((-100 as $t).clamp_magnitude(50), -50);
|
||||
assert_eq!((30 as $t).clamp_magnitude(50), 30);
|
||||
assert_eq!((-30 as $t).clamp_magnitude(50), -30);
|
||||
|
||||
// Exact boundary
|
||||
assert_eq!((50 as $t).clamp_magnitude(50), 50);
|
||||
assert_eq!((-50 as $t).clamp_magnitude(50), -50);
|
||||
|
||||
// Zero cases
|
||||
assert_eq!((0 as $t).clamp_magnitude(100), 0);
|
||||
assert_eq!((0 as $t).clamp_magnitude(0), 0);
|
||||
assert_eq!((100 as $t).clamp_magnitude(0), 0);
|
||||
assert_eq!((-100 as $t).clamp_magnitude(0), 0);
|
||||
|
||||
// MIN/MAX values
|
||||
// Symmetric range [-MAX, MAX]
|
||||
assert_eq!(max.clamp_magnitude(max as $ut), max);
|
||||
assert_eq!(min.clamp_magnitude(max as $ut), -max);
|
||||
|
||||
// Full range (limit covers MIN)
|
||||
let min_abs = min.unsigned_abs();
|
||||
assert_eq!(min.clamp_magnitude(min_abs), min);
|
||||
|
||||
// Limit larger than type max (uN > iN::MAX)
|
||||
assert_eq!(max.clamp_magnitude(max_u), max);
|
||||
assert_eq!(min.clamp_magnitude(max_u), min);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_i8() {
|
||||
check_int_clamp!(i8, u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_i16() {
|
||||
check_int_clamp!(i16, u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_i32() {
|
||||
check_int_clamp!(i32, u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_i64() {
|
||||
check_int_clamp!(i64, u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_i128() {
|
||||
check_int_clamp!(i128, u128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_isize() {
|
||||
check_int_clamp!(isize, usize);
|
||||
}
|
||||
|
||||
macro_rules! check_float_clamp {
|
||||
($t:ty) => {
|
||||
// Basic clamping
|
||||
assert_eq!((5.0 as $t).clamp_magnitude(3.0), 3.0);
|
||||
assert_eq!((-5.0 as $t).clamp_magnitude(3.0), -3.0);
|
||||
assert_eq!((2.0 as $t).clamp_magnitude(3.0), 2.0);
|
||||
assert_eq!((-2.0 as $t).clamp_magnitude(3.0), -2.0);
|
||||
|
||||
// Exact boundary
|
||||
assert_eq!((3.0 as $t).clamp_magnitude(3.0), 3.0);
|
||||
assert_eq!((-3.0 as $t).clamp_magnitude(3.0), -3.0);
|
||||
|
||||
// Zero cases
|
||||
assert_eq!((0.0 as $t).clamp_magnitude(1.0), 0.0);
|
||||
assert_eq!((-0.0 as $t).clamp_magnitude(1.0), 0.0);
|
||||
assert_eq!((5.0 as $t).clamp_magnitude(0.0), 0.0);
|
||||
assert_eq!((-5.0 as $t).clamp_magnitude(0.0), 0.0);
|
||||
|
||||
// Special values - Infinity
|
||||
let inf = <$t>::INFINITY;
|
||||
let neg_inf = <$t>::NEG_INFINITY;
|
||||
assert_eq!(inf.clamp_magnitude(100.0), 100.0);
|
||||
assert_eq!(neg_inf.clamp_magnitude(100.0), -100.0);
|
||||
assert_eq!(inf.clamp_magnitude(inf), inf);
|
||||
|
||||
// Value with infinite limit
|
||||
assert_eq!((1.0 as $t).clamp_magnitude(inf), 1.0);
|
||||
assert_eq!((-1.0 as $t).clamp_magnitude(inf), -1.0);
|
||||
|
||||
// MIN and MAX
|
||||
let max = <$t>::MAX;
|
||||
let min = <$t>::MIN;
|
||||
// Large limit
|
||||
let huge = 1e30;
|
||||
assert_eq!(max.clamp_magnitude(huge), huge);
|
||||
assert_eq!(min.clamp_magnitude(huge), -huge);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_f32() {
|
||||
check_float_clamp!(f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp_magnitude_f64() {
|
||||
check_float_clamp!(f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "limit must be non-negative")]
|
||||
fn test_clamp_magnitude_f32_panic_negative_limit() {
|
||||
let _ = 1.0f32.clamp_magnitude(-1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "limit must be non-negative")]
|
||||
fn test_clamp_magnitude_f64_panic_negative_limit() {
|
||||
let _ = 1.0f64.clamp_magnitude(-1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_clamp_magnitude_f32_panic_nan_limit() {
|
||||
let _ = 1.0f32.clamp_magnitude(f32::NAN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_clamp_magnitude_f64_panic_nan_limit() {
|
||||
let _ = 1.0f64.clamp_magnitude(f64::NAN);
|
||||
}
|
||||
@@ -346,7 +346,6 @@
|
||||
#![feature(ip)]
|
||||
#![feature(lazy_get)]
|
||||
#![feature(maybe_uninit_array_assume_init)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(normalize_lexically)]
|
||||
#![feature(path_trailing_sep)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
//@ known-bug: rust-lang/rust#130104
|
||||
|
||||
fn main() {
|
||||
let non_secure_function =
|
||||
core::mem::transmute::<fn() -> _, extern "cmse-nonsecure-call" fn() -> _>;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//@ add-minicore
|
||||
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
|
||||
//@ needs-llvm-components: arm
|
||||
#![feature(abi_cmse_nonsecure_call, no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
// Infer variables cause panics in layout generation, so the argument/return type is checked for
|
||||
// whether it contains an infer var, and `LayoutError::Unknown` is emitted if so.
|
||||
//
|
||||
// See https://github.com/rust-lang/rust/issues/130104.
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
fn infer_1() {
|
||||
let _ = mem::transmute::<fn() -> _, extern "cmse-nonsecure-call" fn() -> _>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_2() {
|
||||
let _ = mem::transmute::<fn() -> (i32, _), extern "cmse-nonsecure-call" fn() -> (i32, _)>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_3() {
|
||||
let _ = mem::transmute::<fn(_: _) -> (), extern "cmse-nonsecure-call" fn(_: _) -> ()>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_4() {
|
||||
let _ =
|
||||
mem::transmute::<fn(_: (i32, _)) -> (), extern "cmse-nonsecure-call" fn(_: (i32, _)) -> ()>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:16:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn() -> _, extern "cmse-nonsecure-call" fn() -> _>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:21:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn() -> (i32, _), extern "cmse-nonsecure-call" fn() -> (i32, _)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:26:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn(_: _) -> (), extern "cmse-nonsecure-call" fn(_: _) -> ()>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:32:9
|
||||
|
|
||||
LL | mem::transmute::<fn(_: (i32, _)) -> (), extern "cmse-nonsecure-call" fn(_: (i32, _)) -> ()>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
@@ -0,0 +1,36 @@
|
||||
//@ add-minicore
|
||||
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
|
||||
//@ needs-llvm-components: arm
|
||||
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
// Infer variables cause panics in layout generation, so the argument/return type is checked for
|
||||
// whether it contains an infer var, and `LayoutError::Unknown` is emitted if so.
|
||||
//
|
||||
// See https://github.com/rust-lang/rust/issues/130104.
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
fn infer_1() {
|
||||
let _ = mem::transmute::<fn() -> _, extern "cmse-nonsecure-entry" fn() -> _>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_2() {
|
||||
let _ = mem::transmute::<fn() -> (i32, _), extern "cmse-nonsecure-entry" fn() -> (i32, _)>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_3() {
|
||||
let _ = mem::transmute::<fn(_: _) -> (), extern "cmse-nonsecure-entry" fn(_: _) -> ()>;
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn infer_4() {
|
||||
let _ = mem::transmute::<
|
||||
//~^ ERROR type annotations needed
|
||||
fn(_: (i32, _)) -> (),
|
||||
extern "cmse-nonsecure-entry" fn(_: (i32, _)) -> (),
|
||||
>;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:16:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn() -> _, extern "cmse-nonsecure-entry" fn() -> _>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:21:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn() -> (i32, _), extern "cmse-nonsecure-entry" fn() -> (i32, _)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:26:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<fn(_: _) -> (), extern "cmse-nonsecure-entry" fn(_: _) -> ()>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/infer.rs:31:13
|
||||
|
|
||||
LL | let _ = mem::transmute::<
|
||||
| _____________^
|
||||
LL | |
|
||||
LL | | fn(_: (i32, _)) -> (),
|
||||
LL | | extern "cmse-nonsecure-entry" fn(_: (i32, _)) -> (),
|
||||
LL | | >;
|
||||
| |_____^ cannot infer type of the type parameter `Src` declared on the function `transmute`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
@@ -0,0 +1,15 @@
|
||||
const fn f(value: u32) -> Result<u32, ()> {
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
const TEST: u32 = f(2);
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
const fn g() -> Result<String, ()> {
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
const TEST2: usize = g().len();
|
||||
//~^ ERROR: no method named `len` found for enum `Result<T, E>`
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,24 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-result-no-expect-suggestion.rs:5:19
|
||||
|
|
||||
LL | const TEST: u32 = f(2);
|
||||
| ^^^^ expected `u32`, found `Result<u32, ()>`
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found enum `Result<u32, ()>`
|
||||
|
||||
error[E0599]: no method named `len` found for enum `Result<T, E>` in the current scope
|
||||
--> $DIR/const-result-no-expect-suggestion.rs:12:26
|
||||
|
|
||||
LL | const TEST2: usize = g().len();
|
||||
| ^^^
|
||||
|
|
||||
note: the method `len` exists on the type `String`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
help: there is a method `le` with a similar name, but with different arguments
|
||||
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0599.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
@@ -0,0 +1,18 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(fn_delegation)]
|
||||
|
||||
trait Trait {
|
||||
fn static_method2(x: i32, y: i32) -> i32 {
|
||||
x + y
|
||||
}
|
||||
}
|
||||
|
||||
struct S;
|
||||
impl Trait for S {}
|
||||
|
||||
pub fn main() {
|
||||
'foo: loop {
|
||||
reuse <S as Trait>::static_method2 { loop { break 'foo; } }
|
||||
//~^ ERROR use of unreachable label `'foo`
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
error[E0767]: use of unreachable label `'foo`
|
||||
--> $DIR/unreachable-label-ice-148889.rs:15:59
|
||||
|
|
||||
LL | 'foo: loop {
|
||||
| ---- unreachable label defined here
|
||||
LL | reuse <S as Trait>::static_method2 { loop { break 'foo; } }
|
||||
| ^^^^ unreachable label `'foo`
|
||||
|
|
||||
= note: labels are unreachable through functions, closures, async blocks and modules
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0767`.
|
||||
@@ -56,10 +56,10 @@ This pattern should be rewritten. There are a few possible ways to do this:
|
||||
and do the cast in the fn body (the preferred option)
|
||||
- cast the fn item of a fn pointer before calling transmute, as shown here:
|
||||
|
||||
```
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
```
|
||||
```
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
```
|
||||
|
||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||
Note though that use of this type is generally incorrect.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//~? ERROR: too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols
|
||||
// ignore-tidy-linelength
|
||||
[dependencies]
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#![feature(frontmatter)]
|
||||
|
||||
// check that we limit fence lengths
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,4 @@
|
||||
error: too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found 256
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(staged_api)]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
@@ -19,6 +18,14 @@ impl const MyTrait for Unstable {
|
||||
fn func() {}
|
||||
}
|
||||
|
||||
// tested in inherent-impl-stability.rs instead to avoid clutter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "unstable", issue = "none")]
|
||||
const impl Unstable {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn inherent_func() {}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Unstable2;
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//@ aux-build: staged-api.rs
|
||||
extern crate staged_api;
|
||||
|
||||
use staged_api::*;
|
||||
|
||||
// Const stability has no impact on usage in non-const contexts.
|
||||
fn non_const_context() {
|
||||
Unstable::inherent_func();
|
||||
}
|
||||
|
||||
const fn stable_const_context() {
|
||||
Unstable::inherent_func();
|
||||
//~^ ERROR: `staged_api::Unstable::inherent_func` is not yet stable as a const fn
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,13 @@
|
||||
error: `staged_api::Unstable::inherent_func` is not yet stable as a const fn
|
||||
--> $DIR/inherent-impl-stability.rs:12:5
|
||||
|
|
||||
LL | Unstable::inherent_func();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
|
|
||||
LL + #![feature(unstable)]
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
//@ edition: 2024
|
||||
//
|
||||
// A regression test for the ICE variant in trait-system-refactor-initiative#245.
|
||||
// We'll meet regions that're already popped off when using parent predicate in cause code.
|
||||
// `cause` in `Obligation` is ignored by folders/visitors.
|
||||
// In this case, `fudge_inference_if_ok` doesn't fudge a region var in cause code.
|
||||
//
|
||||
// The old solver doesn't trigger ICE because regions in the predicate are replaced with
|
||||
// placeholders when checking generator witness. Besides, the old solver doesn't eagerly
|
||||
// resolves vars before canonicalizing the predicate in `predicate_must_hold_modulo_regions`.
|
||||
|
||||
trait AsyncFn: Send + 'static {
|
||||
type Fut: Future<Output = ()> + Send;
|
||||
|
||||
fn call(&self) -> Self::Fut;
|
||||
}
|
||||
|
||||
async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
|
||||
filter.call().await;
|
||||
}
|
||||
|
||||
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn cursed_fut() {
|
||||
wrap_call(get_boxed_fn().as_ref()).await;
|
||||
}
|
||||
|
||||
fn observe_fut_not_send() {
|
||||
assert_send(cursed_fut());
|
||||
//~^ ERROR: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely [E0277]
|
||||
}
|
||||
|
||||
fn assert_send<T: Send>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
|
||||
pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0277]: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:32:17
|
||||
|
|
||||
LL | assert_send(cursed_fut());
|
||||
| ----------- ^^^^^^^^^^^^ `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>`
|
||||
= note: required for `&dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` to implement `Send`
|
||||
note: required because it's used within this `async` fn body
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:19:53
|
||||
|
|
||||
LL | async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
|
||||
| _____________________________________________________^
|
||||
LL | | filter.call().await;
|
||||
LL | | }
|
||||
| |_^
|
||||
note: required because it's used within this `async` fn body
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:27:23
|
||||
|
|
||||
LL | async fn cursed_fut() {
|
||||
| _______________________^
|
||||
LL | | wrap_call(get_boxed_fn().as_ref()).await;
|
||||
LL | | }
|
||||
| |_^
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:36:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>(t: T) -> T {
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -0,0 +1,31 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// The `cause` in `Obligation` is ignored by type folders. So infer vars in cause code is not
|
||||
// fudged.
|
||||
// Check the comments of
|
||||
// `leaking-vars-in-cause-code-1.rs` for more details.
|
||||
trait Trait<T> {}
|
||||
struct A<T>(T);
|
||||
struct B<T>(T);
|
||||
|
||||
trait IncompleteGuidance {}
|
||||
|
||||
impl<T> Trait<()> for A<T>
|
||||
where
|
||||
T: IncompleteGuidance,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Trait<()> for B<T>
|
||||
//~^ ERROR: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
where
|
||||
A<T>: Trait<U>,
|
||||
{
|
||||
}
|
||||
|
||||
fn impls_trait<T: Trait<()>>() {}
|
||||
|
||||
fn main() {
|
||||
impls_trait::<B<()>>();
|
||||
//~^ ERROR: the trait bound `(): IncompleteGuidance` is not satisfied
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:19:9
|
||||
|
|
||||
LL | impl<T, U> Trait<()> for B<T>
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0277]: the trait bound `(): IncompleteGuidance` is not satisfied
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:29:19
|
||||
|
|
||||
LL | impls_trait::<B<()>>();
|
||||
| ^^^^^ the trait `IncompleteGuidance` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:11:1
|
||||
|
|
||||
LL | trait IncompleteGuidance {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required for `A<()>` to implement `Trait<()>`
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:13:9
|
||||
|
|
||||
LL | impl<T> Trait<()> for A<T>
|
||||
| ^^^^^^^^^ ^^^^
|
||||
LL | where
|
||||
LL | T: IncompleteGuidance,
|
||||
| ------------------ unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `B<()>` to implement `Trait<()>`
|
||||
note: required by a bound in `impls_trait`
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:26:19
|
||||
|
|
||||
LL | fn impls_trait<T: Trait<()>>() {}
|
||||
| ^^^^^^^^^ required by this bound in `impls_trait`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0207, E0277.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
||||
Reference in New Issue
Block a user