Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 0 additions & 56 deletions compiler/rustc_builtin_macros/src/deriving/bounds.rs

This file was deleted.

102 changes: 41 additions & 61 deletions compiler/rustc_builtin_macros/src/deriving/clone.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, Safety, VariantData};
use rustc_ast::{self as ast, Generics, ItemKind, Safety, VariantData};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::base::ExtCtxt;
use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};

Expand All @@ -11,9 +11,8 @@ use crate::deriving::path_std;
pub(crate) fn expand_deriving_clone(
cx: &ExtCtxt<'_>,
span: Span,
mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
item: &ast::Item,
push: &mut dyn FnMut(Box<ast::Item>),
is_const: bool,
) {
// The simple form is `fn clone(&self) -> Self { *self }`, possibly with
Expand All @@ -32,35 +31,30 @@ pub(crate) fn expand_deriving_clone(
let bounds;
let substructure;
let is_simple;
match item {
Annotatable::Item(annitem) => match &annitem.kind {
ItemKind::Struct(_, Generics { params, .. }, _)
| ItemKind::Enum(_, Generics { params, .. }, _) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
bounds = smallvec![];
if has_derive_copy
&& !params
.iter()
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
{
is_simple = true;
substructure =
combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false));
} else {
is_simple = false;
substructure = combine_substructure(cs_clone);
}
}
ItemKind::Union(..) => {
bounds = smallvec![Path(path_std!(marker::Copy))];
match &item.kind {
ItemKind::Struct(_, Generics { params, .. }, _)
| ItemKind::Enum(_, Generics { params, .. }, _) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
bounds = smallvec![];
if has_derive_copy
&& !params
.iter()
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
{
is_simple = true;
substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true));
substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, false));
} else {
is_simple = false;
substructure = combine_substructure(cs_clone);
}
_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on wrong item kind"),
},

_ => cx.dcx().span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
}
ItemKind::Union(..) => {
bounds = smallvec![Path(path_std!(marker::Copy))];
is_simple = true;
substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true));
}
_ => cx.dcx().span_bug(span, "`derive(Clone)` on wrong item kind"),
}

// If the clone method is just copying the value, also mark the type as
Expand All @@ -82,7 +76,7 @@ pub(crate) fn expand_deriving_clone(
document: false,
};

trivial_def.expand_ext(cx, mitem, item, push, true);
trivial_def.expand(cx, item, push);
}

let trait_def = TraitDef {
Expand All @@ -94,7 +88,7 @@ pub(crate) fn expand_deriving_clone(
supports_unions: true,
methods: smallvec![MethodDef {
name: sym::clone,
generics: Bounds::empty(),
generics: cx.empty_generics(span),
explicit_self: true,
nonself_args: SmallVec::new(),
ret_ty: Self_,
Expand All @@ -108,13 +102,13 @@ pub(crate) fn expand_deriving_clone(
document: true,
};

trait_def.expand_ext(cx, mitem, item, push, is_simple)
trait_def.expand_ext(cx, item, push, is_simple)
}

fn cs_clone_simple(
cx: &ExtCtxt<'_>,
trait_span: Span,
substr: &Substructure<'_>,
substr: Substructure<'_>,
is_union: bool,
) -> BlockOrExpr {
let mut stmts = ThinVec::new();
Expand Down Expand Up @@ -155,7 +149,7 @@ fn cs_clone_simple(
&[sym::clone, sym::AssertParamIsCopy],
);
} else {
match *substr.fields {
match substr.fields {
StaticStruct(vdata, ..) => {
process_variant(vdata);
}
Expand All @@ -170,55 +164,41 @@ fn cs_clone_simple(
BlockOrExpr::new_mixed(stmts, Some(cx.expr_deref(trait_span, cx.expr_self(trait_span))))
}

fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
let ctor_path;
let all_fields;
fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr {
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
let subcall = |cx: &ExtCtxt<'_>, field: &FieldInfo| {
let args = thin_vec![field.self_expr.clone()];
let subcall = |field: FieldInfo| {
let args = thin_vec![field.self_expr];
cx.expr_call_global(field.span, fn_path.clone(), args)
};

let ctor_path;
let all_fields;
let vdata;
match substr.fields {
Struct(vdata_, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident]);
all_fields = af;
vdata = *vdata_;
vdata = vdata_;
}
EnumMatching(.., variant, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
all_fields = af;
vdata = &variant.data;
}
EnumDiscr(..) | AllFieldlessEnum(..) => {
cx.dcx().span_bug(trait_span, "enum discriminants in `derive(Clone)`")
}
StaticEnum(..) | StaticStruct(..) => {
cx.dcx().span_bug(trait_span, "associated function in `derive(Clone)`")
}
_ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Clone)`"),
}

let expr = match *vdata {
VariantData::Struct { .. } => {
let fields = all_fields
.iter()
.map(|field| {
let Some(ident) = field.name else {
cx.dcx().span_bug(
trait_span,
"unnamed field in normal struct in `derive(Clone)`",
);
};
let call = subcall(cx, field);
cx.field_imm(field.span, ident, call)
})
.into_iter()
.map(|field| cx.field_imm(field.span, field.name.unwrap(), subcall(field)))
.collect::<ThinVec<_>>();

cx.expr_struct(trait_span, ctor_path, fields)
}
VariantData::Tuple(..) => {
let subcalls = all_fields.iter().map(|f| subcall(cx, f)).collect();
let subcalls = all_fields.into_iter().map(subcall).collect();
let path = cx.expr_path(ctor_path);
cx.expr_call(trait_span, path, subcalls)
}
Expand Down
31 changes: 13 additions & 18 deletions compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use ast::HasAttrs;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::visit::BoundKind;
use rustc_ast::visit::{BoundKind, Visitor};
use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem,
self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind,
TraitBoundModifiers, VariantData, WherePredicate,
};
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_errors::E0802;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::base::ExtCtxt;
use rustc_macros::Diagnostic;
use rustc_span::{Ident, Span, Symbol, sym};
use thin_vec::{ThinVec, thin_vec};
Expand All @@ -21,16 +21,13 @@ macro_rules! path {
pub(crate) fn expand_deriving_coerce_pointee(
cx: &ExtCtxt<'_>,
span: Span,
_mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
item: &ast::Item,
push: &mut dyn FnMut(Box<ast::Item>),
_is_const: bool,
) {
item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
DetectNonGenericPointeeAttr { cx }.visit_item(item);

let (name_ident, generics) = if let Annotatable::Item(aitem) = item
&& let ItemKind::Struct(ident, g, struct_data) = &aitem.kind
{
let (name_ident, generics) = if let ItemKind::Struct(ident, g, struct_data) = &item.kind {
if !matches!(
struct_data,
VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
Expand Down Expand Up @@ -104,7 +101,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
let trait_path =
cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]);
let trait_ref = cx.trait_ref(trait_path);
push(Annotatable::Item(
push(
cx.item(
span,
attrs.clone(),
Expand Down Expand Up @@ -144,7 +141,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
items: ThinVec::new(),
}),
),
));
);
}
let mut add_impl_block = |generics, trait_symbol, trait_args| {
let mut parts = path!(span, core::ops);
Expand All @@ -167,7 +164,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
items: ThinVec::new(),
}),
);
push(Annotatable::Item(item));
push(item);
};

// Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For
Expand Down Expand Up @@ -322,18 +319,16 @@ pub(crate) fn expand_deriving_coerce_pointee(
// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
let gen_args = vec![GenericArg::Type(alt_self_type)];
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args);
add_impl_block(impl_generics, sym::CoerceUnsized, gen_args);
}

fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool {
for bound in predicates {
if let ast::WherePredicateKind::BoundPredicate(bound) = &bound.kind
&& bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee)
{
for bound in &bound.bounds {
if is_maybe_sized_bound(bound) {
return true;
}
if contains_maybe_sized_bound(&bound.bounds) {
return true;
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use rustc_ast::Safety;
use rustc_expand::base::ExtCtxt;
use rustc_span::Span;

use crate::deriving::generic::*;
use crate::deriving::path_std;

pub(crate) fn expand_deriving_const_param_ty(
cx: &ExtCtxt<'_>,
span: Span,
item: &ast::Item,
push: &mut dyn FnMut(Box<ast::Item>),
is_const: bool,
) {
let trait_def = TraitDef {
span,
path: path_std!(marker::ConstParamTy_),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))],
supports_unions: false,
methods: SmallVec::new(),
associated_types: SmallVec::new(),
is_const,
safety: Safety::Default,
document: true,
};

trait_def.expand(cx, item, push);
}
30 changes: 30 additions & 0 deletions compiler/rustc_builtin_macros/src/deriving/copy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use rustc_ast::Safety;
use rustc_expand::base::ExtCtxt;
use rustc_span::Span;

use crate::deriving::generic::*;
use crate::deriving::path_std;

pub(crate) fn expand_deriving_copy(
cx: &ExtCtxt<'_>,
span: Span,
item: &ast::Item,
push: &mut dyn FnMut(Box<ast::Item>),
is_const: bool,
) {
let trait_def = TraitDef {
span,
path: path_std!(marker::Copy),
skip_path_as_bound: false,
needs_copy_as_bound_if_packed: false,
additional_bounds: SmallVec::new(),
supports_unions: true,
methods: SmallVec::new(),
associated_types: SmallVec::new(),
is_const,
safety: Safety::Default,
document: true,
};

trait_def.expand(cx, item, push);
}
Loading
Loading