Skip to content

Commit

Permalink
Remove gensyms from built-in derives
Browse files Browse the repository at this point in the history
Also make them generally more hygienic with name resolution.
  • Loading branch information
matthewjasper committed Aug 17, 2019
1 parent 0280e8f commit 3296d0e
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 86 deletions.
59 changes: 30 additions & 29 deletions src/libsyntax_ext/deriving/cmp/ord.rs
Expand Up @@ -43,17 +43,18 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>,
}


pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>,
span: Span,
self_arg_tags: &[ast::Ident])
-> P<ast::Expr> {
pub fn ordering_collapsed(
cx: &mut ExtCtxt<'_>,
span: Span,
self_arg_tags: &[ast::Ident],
) -> P<ast::Expr> {
let lft = cx.expr_ident(span, self_arg_tags[0]);
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
cx.expr_method_call(span, lft, ast::Ident::new(sym::cmp, span), vec![rgt])
}

pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
let test_id = cx.ident_of("cmp").gensym();
let test_id = ast::Ident::new(sym::cmp, span);
let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));

let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
Expand All @@ -75,34 +76,34 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
// as the outermost one, and the last as the innermost.
false,
|cx, span, old, self_f, other_fs| {
// match new {
// ::std::cmp::Ordering::Equal => old,
// cmp => cmp
// }
// match new {
// ::std::cmp::Ordering::Equal => old,
// cmp => cmp
// }

let new = {
let other_f = match other_fs {
[o_f] => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
};
let new = {
let other_f = match other_fs {
[o_f] => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
};

let args = vec![
cx.expr_addr_of(span, self_f),
cx.expr_addr_of(span, other_f.clone()),
];
let args = vec![
cx.expr_addr_of(span, self_f),
cx.expr_addr_of(span, other_f.clone()),
];

cx.expr_call_global(span, cmp_path.clone(), args)
};
cx.expr_call_global(span, cmp_path.clone(), args)
};

let eq_arm = cx.arm(span,
vec![cx.pat_path(span, equals_path.clone())],
old);
let neq_arm = cx.arm(span,
vec![cx.pat_ident(span, test_id)],
cx.expr_ident(span, test_id));
let eq_arm = cx.arm(span,
vec![cx.pat_path(span, equals_path.clone())],
old);
let neq_arm = cx.arm(span,
vec![cx.pat_ident(span, test_id)],
cx.expr_ident(span, test_id));

cx.expr_match(span, new, vec![eq_arm, neq_arm])
},
cx.expr_match(span, new, vec![eq_arm, neq_arm])
},
cx.expr_path(equals_path.clone()),
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
if self_args.len() != 2 {
Expand Down
15 changes: 8 additions & 7 deletions src/libsyntax_ext/deriving/cmp/partial_ord.rs
Expand Up @@ -94,11 +94,12 @@ pub enum OrderingOp {
GeOp,
}

pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
span: Span,
op: OrderingOp,
self_arg_tags: &[ast::Ident])
-> P<ast::Expr> {
pub fn some_ordering_collapsed(
cx: &mut ExtCtxt<'_>,
span: Span,
op: OrderingOp,
self_arg_tags: &[ast::Ident],
) -> P<ast::Expr> {
let lft = cx.expr_ident(span, self_arg_tags[0]);
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
let op_str = match op {
Expand All @@ -108,11 +109,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
GtOp => "gt",
GeOp => "ge",
};
cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt])
cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
}

pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
let test_id = cx.ident_of("cmp").gensym();
let test_id = ast::Ident::new(sym::cmp, span);
let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
let ordering_expr = cx.expr_path(ordering.clone());
let equals_expr = cx.expr_some(span, ordering_expr);
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax_ext/deriving/debug.rs
Expand Up @@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = span.with_ctxt(cx.backtrace());
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
let builder = Ident::from_str("debug_trait_builder").gensym();
let builder = Ident::from_str_and_span("debug_trait_builder", span);
let builder_expr = cx.expr_ident(span, builder.clone());

let fmt = substr.nonself_args[0].clone();
Expand All @@ -73,7 +73,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// tuple struct/"normal" variant
let expr =
cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
stmts.push(cx.stmt_let(span, true, builder, expr));

for field in fields {
// Use double indirection to make sure this works for unsized types
Expand All @@ -82,7 +82,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>

let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::with_dummy_span(sym::field),
Ident::new(sym::field, span),
vec![field]);

// Use `let _ = expr;` to avoid triggering the
Expand All @@ -106,7 +106,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::with_dummy_span(sym::field),
Ident::new(sym::field, span),
vec![name, field]);
stmts.push(stmt_let_undescore(cx, span, expr));
}
Expand Down
6 changes: 3 additions & 3 deletions src/libsyntax_ext/deriving/decodable.rs
@@ -1,6 +1,6 @@
//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more.
//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more.

use crate::deriving::{self, pathvec_std};
use crate::deriving::pathvec_std;
use crate::deriving::generic::*;
use crate::deriving::generic::ty::*;

Expand All @@ -17,7 +17,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable)) {
let krate = "rustc_serialize";
let typaram = &*deriving::hygienic_type_parameter(item, "__D");
let typaram = "__D";

let trait_def = TraitDef {
span,
Expand Down
21 changes: 12 additions & 9 deletions src/libsyntax_ext/deriving/encodable.rs
@@ -1,11 +1,12 @@
//! The compiler code necessary to implement the `#[derive(Encodable)]`
//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that
//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`.
//! The compiler code necessary to implement the `#[derive(RustcEncodable)]`
//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that
//! type-defining items may be tagged with
//! `#[derive(RustcEncodable, RustcDecodable)]`.
//!
//! For example, a type like:
//!
//! ```
//! #[derive(Encodable, Decodable)]
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct Node { id: usize }
//! ```
//!
Expand Down Expand Up @@ -40,15 +41,17 @@
//! references other non-built-in types. A type definition like:
//!
//! ```
//! # #[derive(Encodable, Decodable)] struct Span;
//! #[derive(Encodable, Decodable)]
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct Span;
//! #[derive(RustcEncodable, RustcDecodable)]
//! struct Spanned<T> { node: T, span: Span }
//! ```
//!
//! would yield functions like:
//!
//! ```
//! # #[derive(Encodable, Decodable)] struct Span;
//! # #[derive(RustcEncodable, RustcDecodable)]
//! # struct Span;
//! # struct Spanned<T> { node: T, span: Span }
//! impl<
//! S: Encoder<E>,
Expand Down Expand Up @@ -82,7 +85,7 @@
//! }
//! ```

use crate::deriving::{self, pathvec_std};
use crate::deriving::pathvec_std;
use crate::deriving::generic::*;
use crate::deriving::generic::ty::*;

Expand All @@ -98,7 +101,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable)) {
let krate = "rustc_serialize";
let typaram = &*deriving::hygienic_type_parameter(item, "__S");
let typaram = "__S";

let trait_def = TraitDef {
span,
Expand Down
11 changes: 7 additions & 4 deletions src/libsyntax_ext/deriving/generic/mod.rs
Expand Up @@ -890,7 +890,7 @@ impl<'a> MethodDef<'a> {

for (ty, name) in self.args.iter() {
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
let ident = cx.ident_of(name).gensym();
let ident = ast::Ident::from_str_and_span(name, trait_.span);
arg_tys.push((ident, ast_ty));

let arg_expr = cx.expr_ident(trait_.span, ident);
Expand Down Expand Up @@ -1210,7 +1210,7 @@ impl<'a> MethodDef<'a> {
let vi_idents = self_arg_names.iter()
.map(|name| {
let vi_suffix = format!("{}_vi", &name[..]);
cx.ident_of(&vi_suffix[..]).gensym()
ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
})
.collect::<Vec<ast::Ident>>();

Expand Down Expand Up @@ -1387,7 +1387,10 @@ impl<'a> MethodDef<'a> {
let variant_value =
deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);

let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name));
let target_ty = cx.ty_ident(
sp,
ast::Ident::from_str_and_span(target_type_name, sp),
);
let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
index_let_stmts.push(let_stmt);
Expand Down Expand Up @@ -1588,7 +1591,7 @@ impl<'a> TraitDef<'a> {
let mut ident_exprs = Vec::new();
for (i, struct_field) in struct_def.fields().iter().enumerate() {
let sp = struct_field.span.with_ctxt(self.span.ctxt());
let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym();
let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
paths.push(ident.with_span_pos(sp));
let val = cx.expr_path(cx.path_ident(sp, ident));
let val = if use_temporaries {
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax_ext/deriving/generic/ty.rs
Expand Up @@ -72,7 +72,7 @@ impl<'a> Path<'a> {
self_ty: Ident,
self_generics: &Generics)
-> ast::Path {
let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
let lt = mk_lifetimes(cx, span, &self.lifetime);
let tys: Vec<P<ast::Ty>> =
self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
Expand Down Expand Up @@ -209,7 +209,7 @@ fn mk_ty_param(cx: &ExtCtxt<'_>,
cx.trait_bound(path)
})
.collect();
cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
}

fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_ext/deriving/hash.rs
Expand Up @@ -16,7 +16,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>,

let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std);

let typaram = &*deriving::hygienic_type_parameter(item, "__H");
let typaram = "__H";

let arg = Path::new_local(typaram);
let hash_trait_def = TraitDef {
Expand Down
27 changes: 0 additions & 27 deletions src/libsyntax_ext/deriving/mod.rs
Expand Up @@ -54,33 +54,6 @@ impl MultiItemModifier for BuiltinDerive {
}
}

/// Construct a name for the inner type parameter that can't collide with any type parameters of
/// the item. This is achieved by starting with a base and then concatenating the names of all
/// other type parameters.
// FIXME(aburka): use real hygiene when that becomes possible
fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
let mut typaram = String::from(base);
if let Annotatable::Item(ref item) = *item {
match item.node {
ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
for param in params {
match param.kind {
ast::GenericParamKind::Type { .. } => {
typaram.push_str(&param.ident.as_str());
}
_ => {}
}
}
}

_ => {}
}
}

typaram
}

/// Constructs an expression that calls an intrinsic
fn call_intrinsic(cx: &ExtCtxt<'_>,
span: Span,
Expand Down

0 comments on commit 3296d0e

Please sign in to comment.