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:
bors 2025-08-15 23:10:31 +00:00
commit 1ae7c49072
38 changed files with 722 additions and 36 deletions

View file

@ -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

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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

View 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);
}

View file

@ -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`"),
}

View file

@ -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"]

View file

@ -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 {

View file

@ -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);

View file

@ -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(...))]`.

View file

@ -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,

View file

@ -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> {

View file

@ -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;

View file

@ -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) {

View file

@ -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]) }

View file

@ -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,

View file

@ -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;

View file

@ -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")]

View file

@ -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 */
}
}

View file

@ -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;

View file

@ -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 {

View file

@ -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)]

View file

@ -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 {

View file

@ -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,

View file

@ -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 {

View file

@ -1,10 +0,0 @@
//@ known-bug: #117629
//@ edition:2021
#![feature(const_trait_impl)]
const trait Tr {
async fn ft1() {}
}
fn main() {}

View file

@ -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();
}

View file

@ -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 {

View file

@ -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) -> () {

View 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() {}

View 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`.

View 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);
}

View file

@ -0,0 +1,6 @@
//@ edition: 2021
#[derive(From)] //~ ERROR use of unstable library feature `derive_from`
struct Foo(u32);
fn main() {}

View 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`.

View file

@ -1,7 +1,5 @@
//@ run-pass
#![feature(as_array_of_cells)]
use std::cell::Cell;
fn main() {

View 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() {}

View file

@ -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

View file

@ -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]