mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Remove gensyms from built-in derives
Also make them generally more hygienic with name resolution.
This commit is contained in:
parent
0280e8ffcc
commit
3296d0ed6d
@ -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]);
|
||||
@ -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 {
|
||||
|
@ -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 {
|
||||
@ -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);
|
||||
|
@ -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();
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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));
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
@ -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,
|
||||
|
@ -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 }
|
||||
//! ```
|
||||
//!
|
||||
@ -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>,
|
||||
@ -82,7 +85,7 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::deriving::{self, pathvec_std};
|
||||
use crate::deriving::pathvec_std;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
||||
@ -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,
|
||||
|
@ -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);
|
||||
@ -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>>();
|
||||
|
||||
@ -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);
|
||||
@ -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 {
|
||||
|
@ -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();
|
||||
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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(¶m.ident.as_str());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
typaram
|
||||
}
|
||||
|
||||
/// Constructs an expression that calls an intrinsic
|
||||
fn call_intrinsic(cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
|
121
src/test/ui/derives/derive-hygiene.rs
Normal file
121
src/test/ui/derives/derive-hygiene.rs
Normal file
@ -0,0 +1,121 @@
|
||||
// Make sure that built-in derives don't rely on the user not declaring certain
|
||||
// names to work properly.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![allow(nonstandard_style)]
|
||||
#![feature(decl_macro)]
|
||||
|
||||
use std::prelude::v1::test as inline;
|
||||
|
||||
static f: () = ();
|
||||
static cmp: () = ();
|
||||
static other: () = ();
|
||||
static state: () = ();
|
||||
static __self_0_0: () = ();
|
||||
static __self_1_0: () = ();
|
||||
static __self_vi: () = ();
|
||||
static __arg_1_0: () = ();
|
||||
static debug_trait_builder: () = ();
|
||||
|
||||
struct isize;
|
||||
trait i16 {}
|
||||
|
||||
trait MethodsInDerives: Sized {
|
||||
fn debug_tuple(self) {}
|
||||
fn debug_struct(self) {}
|
||||
fn field(self) {}
|
||||
fn finish(self) {}
|
||||
fn clone(self) {}
|
||||
fn cmp(self) {}
|
||||
fn partial_cmp(self) {}
|
||||
fn eq(self) {}
|
||||
fn ne(self) {}
|
||||
fn le(self) {}
|
||||
fn lt(self) {}
|
||||
fn ge(self) {}
|
||||
fn gt(self) {}
|
||||
fn hash(self) {}
|
||||
}
|
||||
|
||||
trait GenericAny<T, U> {}
|
||||
impl<S, T, U> GenericAny<T, U> for S {}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum __H { V(i32), }
|
||||
|
||||
#[repr(i16)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum W { A, B }
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct X<A: GenericAny<A, self::X<i32>>> {
|
||||
A: A,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct Y<B>(B)
|
||||
where
|
||||
B: From<B>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum Z<C> {
|
||||
C(C),
|
||||
B { C: C },
|
||||
}
|
||||
|
||||
// Make sure that we aren't using `self::` in paths, since it doesn't work in
|
||||
// non-module scopes.
|
||||
const NON_MODULE: () = {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum __H { V(i32), }
|
||||
|
||||
#[repr(i16)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum W { A, B }
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct X<A: Fn(A) -> self::X<i32>> {
|
||||
A: A,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct Y<B>(B)
|
||||
where
|
||||
B: From<B>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum Z<C> {
|
||||
C(C),
|
||||
B { C: C },
|
||||
}
|
||||
};
|
||||
|
||||
macro m() {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum __H { V(i32), }
|
||||
|
||||
#[repr(i16)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum W { A, B }
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct X<A: GenericAny<A, self::X<i32>>> {
|
||||
A: A,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
|
||||
struct Y<B>(B)
|
||||
where
|
||||
B: From<B>;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
enum Z<C> {
|
||||
C(C),
|
||||
B { C: C },
|
||||
}
|
||||
}
|
||||
|
||||
m!();
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user