//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
//! ```
-pub use self::StaticFields::*;
-pub use self::SubstructureFields::*;
+pub use StaticFields::*;
+pub use SubstructureFields::*;
use std::cell::RefCell;
use std::iter;
use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
use syntax::ast::{VariantData, GenericParamKind, GenericArg};
use syntax::attr;
-use syntax::ext::base::{Annotatable, ExtCtxt};
-use syntax::ext::build::AstBuilder;
+use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
use syntax::source_map::{self, respan};
-use syntax::util::move_map::MoveMap;
+use syntax::util::map_in_place::MapInPlace;
use syntax::ptr::P;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::{Symbol, kw, sym};
use syntax::parse::ParseSess;
use syntax_pos::{DUMMY_SP, Span};
-use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
+use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
-use deriving;
+use crate::deriving;
pub mod ty;
/// Arguments other than the self argument
pub args: Vec<(Ty<'a>, &'a str)>,
- /// Return type
+ /// Returns type
pub ret_ty: Ty<'a>,
pub attributes: Vec<ast::Attribute>,
EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
/// Non-matching variants of the enum, but with all state hidden from
- /// the consequent code. The first component holds `Ident`s for all of
+ /// the consequent code. The first component holds `Ident`s for all of
/// the `Self` arguments; the second component is a slice of all of the
/// variants for the enum itself, and the third component is a list of
/// `Ident`s bound to the variant index values for each of the actual
/// Combine the values of all the fields together. The last argument is
/// all the fields of all the structures.
pub type CombineSubstructureFunc<'a> =
- Box<dyn FnMut(&mut ExtCtxt, Span, &Substructure) -> P<Expr> + 'a>;
+ Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> P<Expr> + 'a>;
-/// Deal with non-matching enum variants. The tuple is a list of
+/// Deal with non-matching enum variants. The tuple is a list of
/// identifiers (one for each `Self` argument, which could be any of the
/// variants since they have been collapsed together) and the identifiers
-/// holding the variant index value for each of the `Self` arguments. The
+/// holding the variant index value for each of the `Self` arguments. The
/// last argument is all the non-`Self` args of the method being derived.
pub type EnumNonMatchCollapsedFunc<'a> =
- Box<dyn FnMut(&mut ExtCtxt, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
+ Box<dyn FnMut(&mut ExtCtxt<'_>, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
-pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
- -> RefCell<CombineSubstructureFunc<'a>> {
+pub fn combine_substructure(f: CombineSubstructureFunc<'_>)
+ -> RefCell<CombineSubstructureFunc<'_>> {
RefCell::new(f)
}
/// This method helps to extract all the type parameters referenced from a
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
/// is not global and starts with `T`, or a `TyQPath`.
-fn find_type_parameters(ty: &ast::Ty,
- ty_param_names: &[ast::Name],
- span: Span,
- cx: &ExtCtxt)
- -> Vec<P<ast::Ty>> {
+fn find_type_parameters(
+ ty: &ast::Ty,
+ ty_param_names: &[ast::Name],
+ span: Span,
+ cx: &ExtCtxt<'_>,
+) -> Vec<P<ast::Ty>> {
use syntax::visit;
- struct Visitor<'a, 'b: 'a> {
+ struct Visitor<'a, 'b> {
cx: &'a ExtCtxt<'b>,
span: Span,
ty_param_names: &'a [ast::Name],
impl<'a> TraitDef<'a> {
pub fn expand(self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
mitem: &ast::MetaItem,
item: &'a Annotatable,
push: &mut dyn FnMut(Annotatable)) {
}
pub fn expand_ext(self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
mitem: &ast::MetaItem,
item: &'a Annotatable,
push: &mut dyn FnMut(Annotatable),
return;
}
};
+ let container_id = cx.current_expansion.id.parent();
let is_always_copy =
- attr::contains_name(&item.attrs, "rustc_copy_clone_marker") &&
+ cx.resolver.has_derives(container_id, SpecialDerives::COPY) &&
has_no_type_params;
let use_temporaries = is_packed && is_always_copy;
attrs.extend(item.attrs
.iter()
.filter(|a| {
- match &*a.name().as_str() {
- "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
- _ => false,
- }
+ [sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable]
+ .contains(&a.name_or_empty())
})
.cloned());
push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
/// create an impl like:
///
/// ```ignore (only-for-syntax-highlight)
- /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
+ /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
/// C: WhereTrait,
/// A: DerivedTrait + B1 + ... + BN,
/// B: DerivedTrait + B1 + ... + BN,
/// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and
/// therefore does not get bound by the derived trait.
fn create_derived_impl(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
type_ident: Ident,
generics: &Generics,
field_tys: Vec<P<ast::Ty>>,
defaultness: ast::Defaultness::Final,
attrs: Vec::new(),
generics: Generics::default(),
- node: ast::ImplItemKind::Type(type_def.to_ty(cx, self.span, type_ident, generics)),
+ node: ast::ImplItemKind::TyAlias(
+ type_def.to_ty(cx, self.span, type_ident, generics)),
tokens: None,
}
});
cx.typaram(self.span, param.ident, vec![], bounds, None)
}
+ GenericParamKind::Const { .. } => param.clone(),
}));
// and similarly for where clauses
GenericParamKind::Type { .. } => {
GenericArg::Type(cx.ty_ident(self.span, param.ident))
}
+ GenericParamKind::Const { .. } => {
+ GenericArg::Const(cx.const_ident(self.span, param.ident))
+ }
}).collect();
// Create the type of `self`.
let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]);
let self_type = cx.ty_path(path);
- let attr = cx.attribute(self.span,
- cx.meta_word(self.span,
- Symbol::intern("automatically_derived")));
+ let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
// Just mark it now since we know that it'll end up used downstream
attr::mark_used(&attr);
let opt_trait_ref = Some(trait_ref);
let unused_qual = {
let word = cx.meta_list_item_word(self.span, Symbol::intern("unused_qualifications"));
- cx.attribute(self.span, cx.meta_list(self.span, Symbol::intern("allow"), vec![word]))
+ cx.attribute(cx.meta_list(self.span, sym::allow, vec![word]))
};
let mut a = vec![attr, unused_qual];
};
cx.item(self.span,
- keywords::Invalid.ident(),
+ Ident::invalid(),
a,
ast::ItemKind::Impl(unsafety,
ast::ImplPolarity::Positive,
}
fn expand_struct_def(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
struct_def: &'a VariantData,
type_ident: Ident,
generics: &Generics,
}
fn expand_enum_def(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
enum_def: &'a EnumDef,
type_attrs: &[ast::Attribute],
type_ident: Ident,
impl<'a> MethodDef<'a> {
fn call_substructure_method(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
type_ident: Ident,
self_args: &[P<Expr>],
nonself_args: &[P<Expr>],
- fields: &SubstructureFields)
+ fields: &SubstructureFields<'_>)
-> P<Expr> {
let substructure = Substructure {
type_ident,
fields,
};
let mut f = self.combine_substructure.borrow_mut();
- let f: &mut CombineSubstructureFunc = &mut *f;
+ let f: &mut CombineSubstructureFunc<'_> = &mut *f;
f(cx, trait_.span, &substructure)
}
fn get_ret_ty(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
generics: &Generics,
type_ident: Ident)
-> P<ast::Ty> {
fn split_self_nonself_args
(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
type_ident: Ident,
generics: &Generics)
-> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
}
fn create_method(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
type_ident: Ident,
generics: &Generics,
abi: Abi,
arg_types: Vec<(Ident, P<ast::Ty>)>,
body: P<Expr>)
-> ast::ImplItem {
-
- // create the generics that aren't for Self
+ // Create the generics that aren't for `Self`.
let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
let args = {
let self_args = explicit_self.map(|explicit_self| {
- ast::Arg::from_self(explicit_self,
- keywords::SelfLower.ident().with_span_pos(trait_.span))
+ let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span);
+ ast::Arg::from_self(ThinVec::default(), explicit_self, ident)
});
let nonself_args = arg_types.into_iter()
.map(|(name, ty)| cx.arg(trait_.span, name, ty));
/// }
/// ```
fn expand_struct_method_body<'b>(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
trait_: &TraitDef<'b>,
struct_def: &'b VariantData,
type_ident: Ident,
}
fn expand_static_struct_method_body(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
struct_def: &VariantData,
type_ident: Ident,
self_args: &[P<Expr>],
///
/// (Of course `__self_vi` and `__arg_1_vi` are unused for
/// `PartialEq`, and those subcomputations will hopefully be removed
- /// as their results are unused. The point of `__self_vi` and
+ /// as their results are unused. The point of `__self_vi` and
/// `__arg_1_vi` is for `PartialOrd`; see #15503.)
fn expand_enum_method_body<'b>(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
trait_: &TraitDef<'b>,
enum_def: &'b EnumDef,
type_attrs: &[ast::Attribute],
/// }
/// ```
fn build_enum_match_tuple<'b>(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
trait_: &TraitDef<'b>,
enum_def: &'b EnumDef,
type_attrs: &[ast::Attribute],
type_ident: Ident,
- self_args: Vec<P<Expr>>,
+ mut self_args: Vec<P<Expr>>,
nonself_args: &[P<Expr>])
-> P<Expr> {
let sp = trait_.span;
.enumerate()
.filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty()))
.map(|(index, variant)| {
- let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| {
+ let mk_self_pat = |cx: &mut ExtCtxt<'_>, self_arg_name: &str| {
let (p, idents) = trait_.create_enum_variant_pattern(cx,
type_ident,
variant,
other: others,
attrs,
}
- }).collect::<Vec<FieldInfo>>();
+ }).collect::<Vec<FieldInfo<'_>>>();
// Now, for some given VariantK, we have built up
// expressions for referencing every field of every
// them when they are fed as r-values into a tuple
// expression; here add a layer of borrowing, turning
// `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
- let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
- let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args));
+ self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg));
+ let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args));
// Lastly we create an expression which branches on all discriminants being equal
// if discriminant_test {
// them when they are fed as r-values into a tuple
// expression; here add a layer of borrowing, turning
// `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
- let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
- let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args));
+ self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg));
+ let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args));
cx.expr_match(sp, match_arg, match_arms)
}
}
fn expand_static_enum_method_body(&self,
- cx: &mut ExtCtxt,
- trait_: &TraitDef,
+ cx: &mut ExtCtxt<'_>,
+ trait_: &TraitDef<'_>,
enum_def: &EnumDef,
type_ident: Ident,
self_args: &[P<Expr>],
// general helper methods.
impl<'a> TraitDef<'a> {
- fn summarise_struct(&self, cx: &mut ExtCtxt, struct_def: &VariantData) -> StaticFields {
+ fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
let mut named_idents = Vec::new();
let mut just_spans = Vec::new();
for field in struct_def.fields() {
}
}
+ let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
match (just_spans.is_empty(), named_idents.is_empty()) {
(false, false) => {
cx.span_bug(self.span,
}
// named fields
(_, false) => Named(named_idents),
- // empty structs
- _ if struct_def.is_struct() => Named(named_idents),
- _ => Unnamed(just_spans, struct_def.is_tuple()),
+ // unnamed fields
+ (false, _) => Unnamed(just_spans, is_tuple),
+ // empty
+ _ => Named(Vec::new()),
}
}
fn create_subpatterns(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
field_paths: Vec<ast::Ident>,
mutbl: ast::Mutability,
use_temporaries: bool)
fn create_struct_pattern
(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
struct_path: ast::Path,
struct_def: &'a VariantData,
prefix: &str,
fn create_enum_variant_pattern
(&self,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
enum_ident: ast::Ident,
variant: &'a ast::Variant,
prefix: &str,
pub fn cs_fold_fields<'a, F>(use_foldl: bool,
mut f: F,
base: P<Expr>,
- cx: &mut ExtCtxt,
+ cx: &mut ExtCtxt<'_>,
all_fields: &[FieldInfo<'a>])
-> P<Expr>
- where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
+ where F: FnMut(&mut ExtCtxt<'_>, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
{
if use_foldl {
all_fields.iter().fold(base, |old, field| {
}
}
-pub fn cs_fold_enumnonmatch(mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
- cx: &mut ExtCtxt,
+pub fn cs_fold_enumnonmatch(mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
+ cx: &mut ExtCtxt<'_>,
trait_span: Span,
- substructure: &Substructure)
+ substructure: &Substructure<'_>)
-> P<Expr>
{
match *substructure.fields {
}
}
-pub fn cs_fold_static(cx: &mut ExtCtxt,
+pub fn cs_fold_static(cx: &mut ExtCtxt<'_>,
trait_span: Span)
-> P<Expr>
{
pub fn cs_fold<F>(use_foldl: bool,
f: F,
base: P<Expr>,
- enum_nonmatch_f: EnumNonMatchCollapsedFunc,
- cx: &mut ExtCtxt,
+ enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
+ cx: &mut ExtCtxt<'_>,
trait_span: Span,
- substructure: &Substructure)
+ substructure: &Substructure<'_>)
-> P<Expr>
- where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
+ where F: FnMut(&mut ExtCtxt<'_>, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
{
match *substructure.fields {
EnumMatching(.., ref all_fields) |
/// Function to fold over fields, with three cases, to generate more efficient and concise code.
/// When the `substructure` has grouped fields, there are two cases:
-/// Zero fields: call the base case function with None (like the usual base case of `cs_fold`).
+/// Zero fields: call the base case function with `None` (like the usual base case of `cs_fold`).
/// One or more fields: call the base case function on the first value (which depends on
/// `use_fold`), and use that as the base case. Then perform `cs_fold` on the remainder of the
/// fields.
pub fn cs_fold1<F, B>(use_foldl: bool,
f: F,
mut b: B,
- enum_nonmatch_f: EnumNonMatchCollapsedFunc,
- cx: &mut ExtCtxt,
+ enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
+ cx: &mut ExtCtxt<'_>,
trait_span: Span,
- substructure: &Substructure)
+ substructure: &Substructure<'_>)
-> P<Expr>
- where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
- B: FnMut(&mut ExtCtxt, Option<(Span, P<Expr>, &[P<Expr>])>) -> P<Expr>
+ where F: FnMut(&mut ExtCtxt<'_>, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
+ B: FnMut(&mut ExtCtxt<'_>, Option<(Span, P<Expr>, &[P<Expr>])>) -> P<Expr>
{
match *substructure.fields {
EnumMatching(.., ref all_fields) |
}
}
-/// Call the method that is being derived on all the fields, and then
-/// process the collected results. i.e.
-///
-/// ```ignore (only-for-syntax-highlight)
-/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
-/// self_2.method(__arg_1_2, __arg_2_2)])
-/// ```
-#[inline]
-pub fn cs_same_method<F>(f: F,
- mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
- cx: &mut ExtCtxt,
- trait_span: Span,
- substructure: &Substructure)
- -> P<Expr>
- where F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>
-{
- match *substructure.fields {
- EnumMatching(.., ref all_fields) |
- Struct(_, ref all_fields) => {
- // call self_n.method(other_1_n, other_2_n, ...)
- let called = all_fields.iter()
- .map(|field| {
- cx.expr_method_call(field.span,
- field.self_.clone(),
- substructure.method_ident,
- field.other
- .iter()
- .map(|e| cx.expr_addr_of(field.span, e.clone()))
- .collect())
- })
- .collect();
-
- f(cx, trait_span, called)
- }
- EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
- enum_nonmatch_f(cx,
- trait_span,
- (&all_self_args[..], tuple),
- substructure.nonself_args)
- }
- StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
- }
-}
-
-/// Return true if the type has no value fields
+/// Returns `true` if the type has no value fields
/// (for an enum, no variant has any fields)
pub fn is_type_without_fields(item: &Annotatable) -> bool {
if let Annotatable::Item(ref item) = *item {