Auto merge of #145475 - jhpratt:rollup-jr0wado, r=jhpratt
Rollup of 11 pull requests Successful merges: - rust-lang/rust#143717 (Add `Default` impls for `Pin`ned `Box`, `Rc`, `Arc`) - rust-lang/rust#144054 (Stabilize as_array_of_cells) - rust-lang/rust#144907 (fix: Reject async assoc fns of const traits/impls in ast_passes) - rust-lang/rust#144922 (Implement `#[derive(From)]`) - rust-lang/rust#144963 (Stabilize `core::iter::chain`) - rust-lang/rust#145436 (fix(tests/rmake/wasm-unexpected-features): change features from `WASM1` to `MVP`) - rust-lang/rust#145453 (Remove duplicated tracing span in bootstrap) - rust-lang/rust#145454 (Fix tracing debug representation of steps without arguments in bootstrap) - rust-lang/rust#145455 (Do not copy files in `copy_src_dirs` in dry run) - rust-lang/rust#145462 (Stabilize `const_exposed_provenance` feature) - rust-lang/rust#145466 (Enable new `[range-diff]` feature in triagebot) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1ae7c49072
38 changed files with 722 additions and 36 deletions
|
|
@ -32,6 +32,13 @@ ast_passes_assoc_type_without_body =
|
|||
associated type in `impl` without body
|
||||
.suggestion = provide a definition for the type
|
||||
|
||||
ast_passes_async_fn_in_const_trait_or_trait_impl =
|
||||
async functions are not allowed in `const` {$in_impl ->
|
||||
[true] trait impls
|
||||
*[false] traits
|
||||
}
|
||||
.label = associated functions of `const` cannot be declared `async`
|
||||
|
||||
ast_passes_at_least_one_trait = at least one trait must be specified
|
||||
|
||||
ast_passes_auto_generic = auto traits cannot have generic parameters
|
||||
|
|
|
|||
|
|
@ -293,6 +293,21 @@ impl<'a> AstValidator<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
fn check_async_fn_in_const_trait_or_impl(&self, sig: &FnSig, parent: &TraitOrTraitImpl) {
|
||||
let Some(const_keyword) = parent.constness() else { return };
|
||||
|
||||
let Some(CoroutineKind::Async { span: async_keyword, .. }) = sig.header.coroutine_kind
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.dcx().emit_err(errors::AsyncFnInConstTraitOrTraitImpl {
|
||||
async_keyword,
|
||||
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
|
||||
const_keyword,
|
||||
});
|
||||
}
|
||||
|
||||
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
|
||||
self.check_decl_num_args(fn_decl);
|
||||
self.check_decl_cvariadic_pos(fn_decl);
|
||||
|
|
@ -1578,6 +1593,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
|
||||
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
||||
self.check_trait_fn_not_const(sig.header.constness, parent);
|
||||
self.check_async_fn_in_const_trait_or_impl(sig, parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,16 @@ pub(crate) struct TraitFnConst {
|
|||
pub make_trait_const_sugg: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_async_fn_in_const_trait_or_trait_impl)]
|
||||
pub(crate) struct AsyncFnInConstTraitOrTraitImpl {
|
||||
#[primary_span]
|
||||
pub async_keyword: Span,
|
||||
pub in_impl: bool,
|
||||
#[label]
|
||||
pub const_keyword: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_forbidden_bound)]
|
||||
pub(crate) struct ForbiddenBound {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,15 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
|
|||
|
||||
builtin_macros_format_use_positional = consider using a positional formatting argument instead
|
||||
|
||||
builtin_macros_derive_from_wrong_target = `#[derive(From)]` used on {$kind}
|
||||
|
||||
builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struct with {$multiple_fields ->
|
||||
[true] multiple fields
|
||||
*[false] no fields
|
||||
}
|
||||
|
||||
builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
|
||||
.note = only one `#[default]` attribute is needed
|
||||
.label = `#[default]` used here
|
||||
|
|
|
|||
132
compiler/rustc_builtin_macros/src/deriving/from.rs
Normal file
132
compiler/rustc_builtin_macros/src/deriving/from.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::{ItemKind, VariantData};
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
|
||||
use rustc_span::{Ident, Span, kw, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::deriving::generic::ty::{Bounds, Path, PathKind, Ty};
|
||||
use crate::deriving::generic::{
|
||||
BlockOrExpr, FieldlessVariantsStrategy, MethodDef, SubstructureFields, TraitDef,
|
||||
combine_substructure,
|
||||
};
|
||||
use crate::deriving::pathvec_std;
|
||||
use crate::errors;
|
||||
|
||||
/// Generate an implementation of the `From` trait, provided that `item`
|
||||
/// is a struct or a tuple struct with exactly one field.
|
||||
pub(crate) fn expand_deriving_from(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &ast::MetaItem,
|
||||
annotatable: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let Annotatable::Item(item) = &annotatable else {
|
||||
cx.dcx().bug("derive(From) used on something else than an item");
|
||||
};
|
||||
|
||||
// #[derive(From)] is currently usable only on structs with exactly one field.
|
||||
let field = if let ItemKind::Struct(_, _, data) = &item.kind
|
||||
&& let [field] = data.fields()
|
||||
{
|
||||
Some(field.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let from_type = match &field {
|
||||
Some(field) => Ty::AstTy(field.ty.clone()),
|
||||
// We don't have a type to put into From<...> if we don't have a single field, so just put
|
||||
// unit there.
|
||||
None => Ty::Unit,
|
||||
};
|
||||
let path =
|
||||
Path::new_(pathvec_std!(convert::From), vec![Box::new(from_type.clone())], PathKind::Std);
|
||||
|
||||
// Generate code like this:
|
||||
//
|
||||
// struct S(u32);
|
||||
// #[automatically_derived]
|
||||
// impl ::core::convert::From<u32> for S {
|
||||
// #[inline]
|
||||
// fn from(value: u32) -> S {
|
||||
// Self(value)
|
||||
// }
|
||||
// }
|
||||
let from_trait_def = TraitDef {
|
||||
span,
|
||||
path,
|
||||
skip_path_as_bound: true,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: Vec::new(),
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::from,
|
||||
generics: Bounds { bounds: vec![] },
|
||||
explicit_self: false,
|
||||
nonself_args: vec![(from_type, sym::value)],
|
||||
ret_ty: Ty::Self_,
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, span, substructure| {
|
||||
let Some(field) = &field else {
|
||||
let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span);
|
||||
let err_span = MultiSpan::from_spans(vec![span, item_span]);
|
||||
let error = match &item.kind {
|
||||
ItemKind::Struct(_, _, data) => {
|
||||
cx.dcx().emit_err(errors::DeriveFromWrongFieldCount {
|
||||
span: err_span,
|
||||
multiple_fields: data.fields().len() > 1,
|
||||
})
|
||||
}
|
||||
ItemKind::Enum(_, _, _) | ItemKind::Union(_, _, _) => {
|
||||
cx.dcx().emit_err(errors::DeriveFromWrongTarget {
|
||||
span: err_span,
|
||||
kind: &format!("{} {}", item.kind.article(), item.kind.descr()),
|
||||
})
|
||||
}
|
||||
_ => cx.dcx().bug("Invalid derive(From) ADT input"),
|
||||
};
|
||||
|
||||
return BlockOrExpr::new_expr(DummyResult::raw_expr(span, Some(error)));
|
||||
};
|
||||
|
||||
let self_kw = Ident::new(kw::SelfUpper, span);
|
||||
let expr: Box<ast::Expr> = match substructure.fields {
|
||||
SubstructureFields::StaticStruct(variant, _) => match variant {
|
||||
// Self {
|
||||
// field: value
|
||||
// }
|
||||
VariantData::Struct { .. } => cx.expr_struct_ident(
|
||||
span,
|
||||
self_kw,
|
||||
thin_vec![cx.field_imm(
|
||||
span,
|
||||
field.ident.unwrap(),
|
||||
cx.expr_ident(span, Ident::new(sym::value, span))
|
||||
)],
|
||||
),
|
||||
// Self(value)
|
||||
VariantData::Tuple(_, _) => cx.expr_call_ident(
|
||||
span,
|
||||
self_kw,
|
||||
thin_vec![cx.expr_ident(span, Ident::new(sym::value, span))],
|
||||
),
|
||||
variant => {
|
||||
cx.dcx().bug(format!("Invalid derive(From) ADT variant: {variant:?}"));
|
||||
}
|
||||
},
|
||||
_ => cx.dcx().bug("Invalid derive(From) ADT input"),
|
||||
};
|
||||
BlockOrExpr::new_expr(expr)
|
||||
})),
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
from_trait_def.expand(cx, mitem, annotatable, push);
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
//! when specifying impls to be derived.
|
||||
|
||||
pub(crate) use Ty::*;
|
||||
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
|
||||
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind, TyKind};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
|
||||
|
|
@ -65,7 +65,7 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
/// A type. Supports pointers, Self, and literals.
|
||||
/// A type. Supports pointers, Self, literals, unit or an arbitrary AST path.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum Ty {
|
||||
Self_,
|
||||
|
|
@ -76,6 +76,8 @@ pub(crate) enum Ty {
|
|||
Path(Path),
|
||||
/// For () return types.
|
||||
Unit,
|
||||
/// An arbitrary type.
|
||||
AstTy(Box<ast::Ty>),
|
||||
}
|
||||
|
||||
pub(crate) fn self_ref() -> Ty {
|
||||
|
|
@ -101,6 +103,7 @@ impl Ty {
|
|||
let ty = ast::TyKind::Tup(ThinVec::new());
|
||||
cx.ty(span, ty)
|
||||
}
|
||||
AstTy(ty) => ty.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +135,10 @@ impl Ty {
|
|||
cx.path_all(span, false, vec![self_ty], params)
|
||||
}
|
||||
Path(p) => p.to_path(cx, span, self_ty, generics),
|
||||
AstTy(ty) => match &ty.kind {
|
||||
TyKind::Path(_, path) => path.clone(),
|
||||
_ => cx.dcx().span_bug(span, "non-path in a path in generic `derive`"),
|
||||
},
|
||||
Ref(..) => cx.dcx().span_bug(span, "ref in a path in generic `derive`"),
|
||||
Unit => cx.dcx().span_bug(span, "unit in a path in generic `derive`"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ pub(crate) mod clone;
|
|||
pub(crate) mod coerce_pointee;
|
||||
pub(crate) mod debug;
|
||||
pub(crate) mod default;
|
||||
pub(crate) mod from;
|
||||
pub(crate) mod hash;
|
||||
|
||||
#[path = "cmp/eq.rs"]
|
||||
|
|
|
|||
|
|
@ -446,6 +446,24 @@ pub(crate) struct DefaultHasArg {
|
|||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_derive_from_wrong_target)]
|
||||
#[note(builtin_macros_derive_from_usage_note)]
|
||||
pub(crate) struct DeriveFromWrongTarget<'a> {
|
||||
#[primary_span]
|
||||
pub(crate) span: MultiSpan,
|
||||
pub(crate) kind: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_derive_from_wrong_field_count)]
|
||||
#[note(builtin_macros_derive_from_usage_note)]
|
||||
pub(crate) struct DeriveFromWrongFieldCount {
|
||||
#[primary_span]
|
||||
pub(crate) span: MultiSpan,
|
||||
pub(crate) multiple_fields: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_derive_macro_call)]
|
||||
pub(crate) struct DeriveMacroCall {
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
|||
PartialEq: partial_eq::expand_deriving_partial_eq,
|
||||
PartialOrd: partial_ord::expand_deriving_partial_ord,
|
||||
CoercePointee: coerce_pointee::expand_deriving_coerce_pointee,
|
||||
From: from::expand_deriving_from,
|
||||
}
|
||||
|
||||
let client = rustc_proc_macro::bridge::client::Client::expand1(rustc_proc_macro::quote);
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ declare_features! (
|
|||
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
|
||||
/// Allows deref patterns.
|
||||
(incomplete, deref_patterns, "1.79.0", Some(87121)),
|
||||
/// Allows deriving the From trait on single-field structs.
|
||||
(unstable, derive_from, "CURRENT_RUSTC_VERSION", Some(144889)),
|
||||
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
|
||||
(unstable, doc_auto_cfg, "1.58.0", Some(43781)),
|
||||
/// Allows `#[doc(cfg(...))]`.
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@ symbols! {
|
|||
__D,
|
||||
__H,
|
||||
__S,
|
||||
__T,
|
||||
__awaitee,
|
||||
__try_var,
|
||||
_t,
|
||||
|
|
@ -746,6 +747,7 @@ symbols! {
|
|||
contracts_ensures,
|
||||
contracts_internals,
|
||||
contracts_requires,
|
||||
convert,
|
||||
convert_identity,
|
||||
copy,
|
||||
copy_closures,
|
||||
|
|
@ -847,6 +849,7 @@ symbols! {
|
|||
derive_const,
|
||||
derive_const_issue: "118304",
|
||||
derive_default_enum,
|
||||
derive_from,
|
||||
derive_smart_pointer,
|
||||
destruct,
|
||||
destructuring_assignment,
|
||||
|
|
@ -2331,6 +2334,7 @@ symbols! {
|
|||
va_start,
|
||||
val,
|
||||
validity,
|
||||
value,
|
||||
values,
|
||||
var,
|
||||
variant_count,
|
||||
|
|
|
|||
|
|
@ -1672,7 +1672,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Default> Default for Box<T> {
|
||||
/// Creates a `Box<T>`, with the `Default` value for T.
|
||||
/// Creates a `Box<T>`, with the `Default` value for `T`.
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let mut x: Box<mem::MaybeUninit<T>> = Box::new_uninit();
|
||||
|
|
@ -1695,6 +1695,7 @@ impl<T: Default> Default for Box<T> {
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Default for Box<[T]> {
|
||||
/// Creates an empty `[T]` inside a `Box`.
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
|
||||
|
|
@ -1716,6 +1717,19 @@ impl Default for Box<str> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> Default for Pin<Box<T>>
|
||||
where
|
||||
T: ?Sized,
|
||||
Box<T>: Default,
|
||||
{
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Box::into_pin(Box::<T>::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
|
||||
|
|
|
|||
|
|
@ -2357,7 +2357,7 @@ impl<T: Default> Default for Rc<T> {
|
|||
/// assert_eq!(*x, 0);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn default() -> Rc<T> {
|
||||
fn default() -> Self {
|
||||
unsafe {
|
||||
Self::from_inner(
|
||||
Box::leak(Box::write(
|
||||
|
|
@ -2373,7 +2373,7 @@ impl<T: Default> Default for Rc<T> {
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
|
||||
impl Default for Rc<str> {
|
||||
/// Creates an empty str inside an Rc
|
||||
/// Creates an empty `str` inside an `Rc`.
|
||||
///
|
||||
/// This may or may not share an allocation with other Rcs on the same thread.
|
||||
#[inline]
|
||||
|
|
@ -2387,7 +2387,7 @@ impl Default for Rc<str> {
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
|
||||
impl<T> Default for Rc<[T]> {
|
||||
/// Creates an empty `[T]` inside an Rc
|
||||
/// Creates an empty `[T]` inside an `Rc`.
|
||||
///
|
||||
/// This may or may not share an allocation with other Rcs on the same thread.
|
||||
#[inline]
|
||||
|
|
@ -2397,6 +2397,19 @@ impl<T> Default for Rc<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> Default for Pin<Rc<T>>
|
||||
where
|
||||
T: ?Sized,
|
||||
Rc<T>: Default,
|
||||
{
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
unsafe { Pin::new_unchecked(Rc::<T>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
trait RcEqIdent<T: ?Sized + PartialEq, A: Allocator> {
|
||||
fn eq(&self, other: &Rc<T, A>) -> bool;
|
||||
|
|
|
|||
|
|
@ -3654,6 +3654,19 @@ impl<T> Default for Arc<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> Default for Pin<Arc<T>>
|
||||
where
|
||||
T: ?Sized,
|
||||
Arc<T>: Default,
|
||||
{
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
unsafe { Pin::new_unchecked(Arc::<T>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash, A: Allocator> Hash for Arc<T, A> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
|
|
|
|||
|
|
@ -698,14 +698,14 @@ impl<T, const N: usize> Cell<[T; N]> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(as_array_of_cells)]
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let mut array: [i32; 3] = [1, 2, 3];
|
||||
/// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
|
||||
/// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
|
||||
/// ```
|
||||
#[unstable(feature = "as_array_of_cells", issue = "88248")]
|
||||
#[stable(feature = "as_array_of_cells", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "as_array_of_cells", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn as_array_of_cells(&self) -> &[Cell<T>; N] {
|
||||
// SAFETY: `Cell<T>` has the same memory layout as `T`.
|
||||
unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@ impl<A, B> Chain<A, B> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_chain)]
|
||||
///
|
||||
/// use std::iter::chain;
|
||||
///
|
||||
/// let a = [1, 2, 3];
|
||||
|
|
@ -62,7 +60,7 @@ impl<A, B> Chain<A, B> {
|
|||
/// assert_eq!(iter.next(), Some(6));
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
|
||||
#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
|
||||
where
|
||||
A: IntoIterator,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ mod zip;
|
|||
pub use self::array_chunks::ArrayChunks;
|
||||
#[unstable(feature = "std_internals", issue = "none")]
|
||||
pub use self::by_ref_sized::ByRefSized;
|
||||
#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
|
||||
#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use self::chain::chain;
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
pub use self::cloned::Cloned;
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ pub use self::adapters::StepBy;
|
|||
pub use self::adapters::TrustedRandomAccess;
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
pub use self::adapters::TrustedRandomAccessNoCoerce;
|
||||
#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
|
||||
#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use self::adapters::chain;
|
||||
pub(crate) use self::adapters::try_process;
|
||||
#[stable(feature = "iter_zip", since = "1.59.0")]
|
||||
|
|
|
|||
|
|
@ -1770,4 +1770,15 @@ pub(crate) mod builtin {
|
|||
pub macro deref($pat:pat) {
|
||||
builtin # deref($pat)
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait `From`.
|
||||
/// Currently, it can only be used on single-field structs.
|
||||
// Note that the macro is in a different module than the `From` trait,
|
||||
// to avoid triggering an unstable feature being used if someone imports
|
||||
// `std::convert::From`.
|
||||
#[rustc_builtin_macro]
|
||||
#[unstable(feature = "derive_from", issue = "144889")]
|
||||
pub macro From($item: item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,3 +117,10 @@ pub use crate::macros::builtin::deref;
|
|||
reason = "`type_alias_impl_trait` has open design concerns"
|
||||
)]
|
||||
pub use crate::macros::builtin::define_opaque;
|
||||
|
||||
#[unstable(
|
||||
feature = "derive_from",
|
||||
issue = "144889",
|
||||
reason = "`derive(From)` is unstable"
|
||||
)]
|
||||
pub use crate::macros::builtin::From;
|
||||
|
|
|
|||
|
|
@ -974,7 +974,7 @@ pub const fn dangling_mut<T>() -> *mut T {
|
|||
#[must_use]
|
||||
#[inline(always)]
|
||||
#[stable(feature = "exposed_provenance", since = "1.84.0")]
|
||||
#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")]
|
||||
#[rustc_const_stable(feature = "const_exposed_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
|
||||
pub const fn with_exposed_provenance<T>(addr: usize) -> *const T {
|
||||
|
|
@ -1015,7 +1015,7 @@ pub const fn with_exposed_provenance<T>(addr: usize) -> *const T {
|
|||
#[must_use]
|
||||
#[inline(always)]
|
||||
#[stable(feature = "exposed_provenance", since = "1.84.0")]
|
||||
#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")]
|
||||
#[rustc_const_stable(feature = "const_exposed_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
|
||||
pub const fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@
|
|||
#![feature(isolate_most_least_significant_one)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_array_chunks)]
|
||||
#![feature(iter_chain)]
|
||||
#![feature(iter_collect_into)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
|
|
|
|||
|
|
@ -2487,9 +2487,6 @@ pub fn stream_cargo(
|
|||
) -> bool {
|
||||
let mut cmd = cargo.into_cmd();
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _run_span = crate::utils::tracing::trace_cmd(&cmd);
|
||||
|
||||
// Instruct Cargo to give us json messages on stdout, critically leaving
|
||||
// stderr as piped so we can get those pretty colors.
|
||||
let mut message_format = if builder.config.json_output {
|
||||
|
|
|
|||
|
|
@ -916,6 +916,12 @@ fn copy_src_dirs(
|
|||
exclude_dirs: &[&str],
|
||||
dst_dir: &Path,
|
||||
) {
|
||||
// Iterating, filtering and copying a large number of directories can be quite slow.
|
||||
// Avoid doing it in dry run (and thus also tests).
|
||||
if builder.config.dry_run() {
|
||||
return;
|
||||
}
|
||||
|
||||
fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
|
||||
let spath = match path.to_str() {
|
||||
Some(path) => path,
|
||||
|
|
|
|||
|
|
@ -1840,9 +1840,14 @@ pub fn pretty_step_name<S: Step>() -> String {
|
|||
/// Renders `step` using its `Debug` implementation and extract the field arguments out of it.
|
||||
fn step_debug_args<S: Step>(step: &S) -> String {
|
||||
let step_dbg_repr = format!("{step:?}");
|
||||
let brace_start = step_dbg_repr.find('{').unwrap_or(0);
|
||||
let brace_end = step_dbg_repr.rfind('}').unwrap_or(step_dbg_repr.len());
|
||||
step_dbg_repr[brace_start + 1..brace_end - 1].trim().to_string()
|
||||
|
||||
// Some steps do not have any arguments, so they do not have the braces
|
||||
match (step_dbg_repr.find('{'), step_dbg_repr.rfind('}')) {
|
||||
(Some(brace_start), Some(brace_end)) => {
|
||||
step_dbg_repr[brace_start + 1..brace_end - 1].trim().to_string()
|
||||
}
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_print_step<S: Step>(step: &S) -> String {
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
//@ known-bug: #117629
|
||||
//@ edition:2021
|
||||
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
const trait Tr {
|
||||
async fn ft1() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -21,6 +21,6 @@ fn verify_features(path: &Path) {
|
|||
eprintln!("verify {path:?}");
|
||||
let file = rfs::read(&path);
|
||||
|
||||
let mut validator = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::WASM1);
|
||||
let mut validator = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::MVP);
|
||||
validator.validate_all(&file).unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#![crate_type = "lib"]
|
||||
#![allow(dead_code)]
|
||||
#![allow(deprecated)]
|
||||
#![feature(derive_from)]
|
||||
|
||||
// Empty struct.
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
@ -38,6 +39,14 @@ struct PackedPoint {
|
|||
y: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct TupleSingleField(u32);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct SingleField {
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
// A large struct. Note: because this derives `Copy`, it gets the simple
|
||||
// `clone` implemention that just does `*self`.
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
@ -86,7 +95,7 @@ struct PackedManualCopy(u32);
|
|||
impl Copy for PackedManualCopy {}
|
||||
|
||||
// A struct with an unsized field. Some derives are not usable in this case.
|
||||
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct Unsized([u32]);
|
||||
|
||||
trait Trait {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#![crate_type = "lib"]
|
||||
#![allow(dead_code)]
|
||||
#![allow(deprecated)]
|
||||
#![feature(derive_from)]
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
#[prelude_import]
|
||||
|
|
@ -249,6 +250,148 @@ impl ::core::cmp::Ord for PackedPoint {
|
|||
}
|
||||
}
|
||||
|
||||
struct TupleSingleField(u32);
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for TupleSingleField {
|
||||
#[inline]
|
||||
fn clone(&self) -> TupleSingleField {
|
||||
let _: ::core::clone::AssertParamIsClone<u32>;
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for TupleSingleField { }
|
||||
#[automatically_derived]
|
||||
impl ::core::fmt::Debug for TupleSingleField {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
::core::fmt::Formatter::debug_tuple_field1_finish(f,
|
||||
"TupleSingleField", &&self.0)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::default::Default for TupleSingleField {
|
||||
#[inline]
|
||||
fn default() -> TupleSingleField {
|
||||
TupleSingleField(::core::default::Default::default())
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::convert::From<u32> for TupleSingleField {
|
||||
#[inline]
|
||||
fn from(value: u32) -> TupleSingleField { Self(value) }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::hash::Hash for TupleSingleField {
|
||||
#[inline]
|
||||
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
||||
::core::hash::Hash::hash(&self.0, state)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::StructuralPartialEq for TupleSingleField { }
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialEq for TupleSingleField {
|
||||
#[inline]
|
||||
fn eq(&self, other: &TupleSingleField) -> bool { self.0 == other.0 }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for TupleSingleField {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) -> () {
|
||||
let _: ::core::cmp::AssertParamIsEq<u32>;
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for TupleSingleField {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &TupleSingleField)
|
||||
-> ::core::option::Option<::core::cmp::Ordering> {
|
||||
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Ord for TupleSingleField {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &TupleSingleField) -> ::core::cmp::Ordering {
|
||||
::core::cmp::Ord::cmp(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct SingleField {
|
||||
foo: bool,
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::clone::Clone for SingleField {
|
||||
#[inline]
|
||||
fn clone(&self) -> SingleField {
|
||||
let _: ::core::clone::AssertParamIsClone<bool>;
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::Copy for SingleField { }
|
||||
#[automatically_derived]
|
||||
impl ::core::fmt::Debug for SingleField {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
::core::fmt::Formatter::debug_struct_field1_finish(f, "SingleField",
|
||||
"foo", &&self.foo)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::default::Default for SingleField {
|
||||
#[inline]
|
||||
fn default() -> SingleField {
|
||||
SingleField { foo: ::core::default::Default::default() }
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::convert::From<bool> for SingleField {
|
||||
#[inline]
|
||||
fn from(value: bool) -> SingleField { Self { foo: value } }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::hash::Hash for SingleField {
|
||||
#[inline]
|
||||
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
||||
::core::hash::Hash::hash(&self.foo, state)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::marker::StructuralPartialEq for SingleField { }
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialEq for SingleField {
|
||||
#[inline]
|
||||
fn eq(&self, other: &SingleField) -> bool { self.foo == other.foo }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Eq for SingleField {
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[coverage(off)]
|
||||
fn assert_receiver_is_total_eq(&self) -> () {
|
||||
let _: ::core::cmp::AssertParamIsEq<bool>;
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::PartialOrd for SingleField {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &SingleField)
|
||||
-> ::core::option::Option<::core::cmp::Ordering> {
|
||||
::core::cmp::PartialOrd::partial_cmp(&self.foo, &other.foo)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::cmp::Ord for SingleField {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &SingleField) -> ::core::cmp::Ordering {
|
||||
::core::cmp::Ord::cmp(&self.foo, &other.foo)
|
||||
}
|
||||
}
|
||||
|
||||
// A large struct. Note: because this derives `Copy`, it gets the simple
|
||||
// `clone` implemention that just does `*self`.
|
||||
struct Big {
|
||||
|
|
@ -572,6 +715,11 @@ impl ::core::fmt::Debug for Unsized {
|
|||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::convert::From<[u32]> for Unsized {
|
||||
#[inline]
|
||||
fn from(value: [u32]) -> Unsized { Self(value) }
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl ::core::hash::Hash for Unsized {
|
||||
#[inline]
|
||||
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
|
||||
|
|
|
|||
38
tests/ui/deriving/deriving-from-wrong-target.rs
Normal file
38
tests/ui/deriving/deriving-from-wrong-target.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//@ edition: 2021
|
||||
//@ check-fail
|
||||
|
||||
#![feature(derive_from)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR `#[derive(From)]` used on a struct with no fields
|
||||
struct S1;
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR `#[derive(From)]` used on a struct with no fields
|
||||
struct S2 {}
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR `#[derive(From)]` used on a struct with multiple fields
|
||||
struct S3(u32, bool);
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR `#[derive(From)]` used on a struct with multiple fields
|
||||
struct S4 {
|
||||
a: u32,
|
||||
b: bool,
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR `#[derive(From)]` used on an enum
|
||||
enum E1 {}
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
//~| ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
struct SUnsizedField<T: ?Sized> {
|
||||
last: T,
|
||||
//~^ ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
115
tests/ui/deriving/deriving-from-wrong-target.stderr
Normal file
115
tests/ui/deriving/deriving-from-wrong-target.stderr
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
error: `#[derive(From)]` used on a struct with no fields
|
||||
--> $DIR/deriving-from-wrong-target.rs:7:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
LL |
|
||||
LL | struct S1;
|
||||
| ^^
|
||||
|
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error: `#[derive(From)]` used on a struct with no fields
|
||||
--> $DIR/deriving-from-wrong-target.rs:11:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
LL |
|
||||
LL | struct S2 {}
|
||||
| ^^
|
||||
|
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error: `#[derive(From)]` used on a struct with multiple fields
|
||||
--> $DIR/deriving-from-wrong-target.rs:15:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
LL |
|
||||
LL | struct S3(u32, bool);
|
||||
| ^^
|
||||
|
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error: `#[derive(From)]` used on a struct with multiple fields
|
||||
--> $DIR/deriving-from-wrong-target.rs:19:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
LL |
|
||||
LL | struct S4 {
|
||||
| ^^
|
||||
|
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error: `#[derive(From)]` used on an enum
|
||||
--> $DIR/deriving-from-wrong-target.rs:26:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
LL |
|
||||
LL | enum E1 {}
|
||||
| ^^
|
||||
|
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:30:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
...
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
||||
note: required by an implicit `Sized` bound in `From`
|
||||
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - struct SUnsizedField<T: ?Sized> {
|
||||
LL + struct SUnsizedField<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:30:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
...
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
||||
note: required because it appears within the type `SUnsizedField<T>`
|
||||
--> $DIR/deriving-from-wrong-target.rs:33:8
|
||||
|
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: the return type of a function must have a statically known size
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - struct SUnsizedField<T: ?Sized> {
|
||||
LL + struct SUnsizedField<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:34:11
|
||||
|
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
LL | last: T,
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - struct SUnsizedField<T: ?Sized> {
|
||||
LL + struct SUnsizedField<T> {
|
||||
|
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | last: &T,
|
||||
| +
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
58
tests/ui/deriving/deriving-from.rs
Normal file
58
tests/ui/deriving/deriving-from.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//@ edition: 2021
|
||||
//@ run-pass
|
||||
|
||||
#![feature(derive_from)]
|
||||
|
||||
#[derive(From)]
|
||||
struct TupleSimple(u32);
|
||||
|
||||
#[derive(From)]
|
||||
struct TupleNonPathType([u32; 4]);
|
||||
|
||||
#[derive(From)]
|
||||
struct TupleWithRef<'a, T>(&'a T);
|
||||
|
||||
#[derive(From)]
|
||||
struct TupleSWithBound<T: std::fmt::Debug>(T);
|
||||
|
||||
#[derive(From)]
|
||||
struct RawIdentifier {
|
||||
r#use: u32,
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
struct Field {
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
struct Const<const C: usize> {
|
||||
foo: [u32; C],
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = 42u32;
|
||||
let b: [u32; 4] = [0, 1, 2, 3];
|
||||
let c = true;
|
||||
|
||||
let s1: TupleSimple = a.into();
|
||||
assert_eq!(s1.0, a);
|
||||
|
||||
let s2: TupleNonPathType = b.into();
|
||||
assert_eq!(s2.0, b);
|
||||
|
||||
let s3: TupleWithRef<u32> = (&a).into();
|
||||
assert_eq!(s3.0, &a);
|
||||
|
||||
let s4: TupleSWithBound<u32> = a.into();
|
||||
assert_eq!(s4.0, a);
|
||||
|
||||
let s5: RawIdentifier = a.into();
|
||||
assert_eq!(s5.r#use, a);
|
||||
|
||||
let s6: Field = c.into();
|
||||
assert_eq!(s6.foo, c);
|
||||
|
||||
let s7: Const<4> = b.into();
|
||||
assert_eq!(s7.foo, b);
|
||||
}
|
||||
6
tests/ui/feature-gates/feature-gate-derive-from.rs
Normal file
6
tests/ui/feature-gates/feature-gate-derive-from.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//@ edition: 2021
|
||||
|
||||
#[derive(From)] //~ ERROR use of unstable library feature `derive_from`
|
||||
struct Foo(u32);
|
||||
|
||||
fn main() {}
|
||||
13
tests/ui/feature-gates/feature-gate-derive-from.stderr
Normal file
13
tests/ui/feature-gates/feature-gate-derive-from.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: use of unstable library feature `derive_from`
|
||||
--> $DIR/feature-gate-derive-from.rs:3:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^
|
||||
|
|
||||
= note: see issue #144889 <https://github.com/rust-lang/rust/issues/144889> for more information
|
||||
= help: add `#![feature(derive_from)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(as_array_of_cells)]
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
18
tests/ui/traits/const-traits/const-trait-async-assoc-fn.rs
Normal file
18
tests/ui/traits/const-traits/const-trait-async-assoc-fn.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
//@ edition: 2021
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
const trait Tr {
|
||||
async fn ft1() {}
|
||||
//~^ ERROR async functions are not allowed in `const` traits
|
||||
}
|
||||
|
||||
const trait Tr2 {
|
||||
fn f() -> impl std::future::Future<Output = ()>;
|
||||
}
|
||||
|
||||
impl const Tr2 for () {
|
||||
async fn f() {}
|
||||
//~^ ERROR async functions are not allowed in `const` trait impls
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
error: async functions are not allowed in `const` traits
|
||||
--> $DIR/const-trait-async-assoc-fn.rs:5:5
|
||||
|
|
||||
LL | const trait Tr {
|
||||
| ----- associated functions of `const` cannot be declared `async`
|
||||
LL | async fn ft1() {}
|
||||
| ^^^^^
|
||||
|
||||
error: async functions are not allowed in `const` trait impls
|
||||
--> $DIR/const-trait-async-assoc-fn.rs:14:5
|
||||
|
|
||||
LL | impl const Tr2 for () {
|
||||
| ----- associated functions of `const` cannot be declared `async`
|
||||
LL | async fn f() {}
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1596,3 +1596,8 @@ days-threshold = 28
|
|||
# Documentation at: https://forge.rust-lang.org/triagebot/concern.html
|
||||
[concern]
|
||||
labels = ["S-waiting-on-concerns"]
|
||||
|
||||
# Enable comments linking to triagebot range-diff when a PR is rebased
|
||||
# onto a different base commit
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/range-diff.html
|
||||
[range-diff]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue