Remove gensyms from built-in derives
Also make them generally more hygienic with name resolution.
This commit is contained in:
parent
0280e8ffcc
commit
3296d0ed6d
10 changed files with 188 additions and 86 deletions
|
@ -43,17 +43,18 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>,
|
pub fn ordering_collapsed(
|
||||||
span: Span,
|
cx: &mut ExtCtxt<'_>,
|
||||||
self_arg_tags: &[ast::Ident])
|
span: Span,
|
||||||
-> P<ast::Expr> {
|
self_arg_tags: &[ast::Ident],
|
||||||
|
) -> P<ast::Expr> {
|
||||||
let lft = cx.expr_ident(span, self_arg_tags[0]);
|
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 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> {
|
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 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]);
|
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.
|
// as the outermost one, and the last as the innermost.
|
||||||
false,
|
false,
|
||||||
|cx, span, old, self_f, other_fs| {
|
|cx, span, old, self_f, other_fs| {
|
||||||
// match new {
|
// match new {
|
||||||
// ::std::cmp::Ordering::Equal => old,
|
// ::std::cmp::Ordering::Equal => old,
|
||||||
// cmp => cmp
|
// cmp => cmp
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let new = {
|
let new = {
|
||||||
let other_f = match other_fs {
|
let other_f = match other_fs {
|
||||||
[o_f] => o_f,
|
[o_f] => o_f,
|
||||||
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
|
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = vec![
|
let args = vec![
|
||||||
cx.expr_addr_of(span, self_f),
|
cx.expr_addr_of(span, self_f),
|
||||||
cx.expr_addr_of(span, other_f.clone()),
|
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,
|
let eq_arm = cx.arm(span,
|
||||||
vec![cx.pat_path(span, equals_path.clone())],
|
vec![cx.pat_path(span, equals_path.clone())],
|
||||||
old);
|
old);
|
||||||
let neq_arm = cx.arm(span,
|
let neq_arm = cx.arm(span,
|
||||||
vec![cx.pat_ident(span, test_id)],
|
vec![cx.pat_ident(span, test_id)],
|
||||||
cx.expr_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()),
|
cx.expr_path(equals_path.clone()),
|
||||||
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
|
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||||
if self_args.len() != 2 {
|
if self_args.len() != 2 {
|
||||||
|
|
|
@ -94,11 +94,12 @@ pub enum OrderingOp {
|
||||||
GeOp,
|
GeOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
|
pub fn some_ordering_collapsed(
|
||||||
span: Span,
|
cx: &mut ExtCtxt<'_>,
|
||||||
op: OrderingOp,
|
span: Span,
|
||||||
self_arg_tags: &[ast::Ident])
|
op: OrderingOp,
|
||||||
-> P<ast::Expr> {
|
self_arg_tags: &[ast::Ident],
|
||||||
|
) -> P<ast::Expr> {
|
||||||
let lft = cx.expr_ident(span, self_arg_tags[0]);
|
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 rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
|
||||||
let op_str = match op {
|
let op_str = match op {
|
||||||
|
@ -108,11 +109,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
|
||||||
GtOp => "gt",
|
GtOp => "gt",
|
||||||
GeOp => "ge",
|
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> {
|
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 = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
||||||
let ordering_expr = cx.expr_path(ordering.clone());
|
let ordering_expr = cx.expr_path(ordering.clone());
|
||||||
let equals_expr = cx.expr_some(span, ordering_expr);
|
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
|
// 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 span = span.with_ctxt(cx.backtrace());
|
||||||
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
|
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 builder_expr = cx.expr_ident(span, builder.clone());
|
||||||
|
|
||||||
let fmt = substr.nonself_args[0].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
|
// tuple struct/"normal" variant
|
||||||
let expr =
|
let expr =
|
||||||
cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
|
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 {
|
for field in fields {
|
||||||
// Use double indirection to make sure this works for unsized types
|
// 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,
|
let expr = cx.expr_method_call(span,
|
||||||
builder_expr.clone(),
|
builder_expr.clone(),
|
||||||
Ident::with_dummy_span(sym::field),
|
Ident::new(sym::field, span),
|
||||||
vec![field]);
|
vec![field]);
|
||||||
|
|
||||||
// Use `let _ = expr;` to avoid triggering the
|
// 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 field = cx.expr_addr_of(field.span, field);
|
||||||
let expr = cx.expr_method_call(span,
|
let expr = cx.expr_method_call(span,
|
||||||
builder_expr.clone(),
|
builder_expr.clone(),
|
||||||
Ident::with_dummy_span(sym::field),
|
Ident::new(sym::field, span),
|
||||||
vec![name, field]);
|
vec![name, field]);
|
||||||
stmts.push(stmt_let_undescore(cx, span, expr));
|
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::*;
|
||||||
use crate::deriving::generic::ty::*;
|
use crate::deriving::generic::ty::*;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>,
|
||||||
item: &Annotatable,
|
item: &Annotatable,
|
||||||
push: &mut dyn FnMut(Annotatable)) {
|
push: &mut dyn FnMut(Annotatable)) {
|
||||||
let krate = "rustc_serialize";
|
let krate = "rustc_serialize";
|
||||||
let typaram = &*deriving::hygienic_type_parameter(item, "__D");
|
let typaram = "__D";
|
||||||
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! The compiler code necessary to implement the `#[derive(Encodable)]`
|
//! The compiler code necessary to implement the `#[derive(RustcEncodable)]`
|
||||||
//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that
|
//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that
|
||||||
//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`.
|
//! type-defining items may be tagged with
|
||||||
|
//! `#[derive(RustcEncodable, RustcDecodable)]`.
|
||||||
//!
|
//!
|
||||||
//! For example, a type like:
|
//! For example, a type like:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #[derive(Encodable, Decodable)]
|
//! #[derive(RustcEncodable, RustcDecodable)]
|
||||||
//! struct Node { id: usize }
|
//! struct Node { id: usize }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -40,15 +41,17 @@
|
||||||
//! references other non-built-in types. A type definition like:
|
//! references other non-built-in types. A type definition like:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # #[derive(Encodable, Decodable)] struct Span;
|
//! # #[derive(RustcEncodable, RustcDecodable)]
|
||||||
//! #[derive(Encodable, Decodable)]
|
//! # struct Span;
|
||||||
|
//! #[derive(RustcEncodable, RustcDecodable)]
|
||||||
//! struct Spanned<T> { node: T, span: Span }
|
//! struct Spanned<T> { node: T, span: Span }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! would yield functions like:
|
//! would yield functions like:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! # #[derive(Encodable, Decodable)] struct Span;
|
//! # #[derive(RustcEncodable, RustcDecodable)]
|
||||||
|
//! # struct Span;
|
||||||
//! # struct Spanned<T> { node: T, span: Span }
|
//! # struct Spanned<T> { node: T, span: Span }
|
||||||
//! impl<
|
//! impl<
|
||||||
//! S: Encoder<E>,
|
//! 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::*;
|
||||||
use crate::deriving::generic::ty::*;
|
use crate::deriving::generic::ty::*;
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>,
|
||||||
item: &Annotatable,
|
item: &Annotatable,
|
||||||
push: &mut dyn FnMut(Annotatable)) {
|
push: &mut dyn FnMut(Annotatable)) {
|
||||||
let krate = "rustc_serialize";
|
let krate = "rustc_serialize";
|
||||||
let typaram = &*deriving::hygienic_type_parameter(item, "__S");
|
let typaram = "__S";
|
||||||
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -890,7 +890,7 @@ impl<'a> MethodDef<'a> {
|
||||||
|
|
||||||
for (ty, name) in self.args.iter() {
|
for (ty, name) in self.args.iter() {
|
||||||
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
|
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));
|
arg_tys.push((ident, ast_ty));
|
||||||
|
|
||||||
let arg_expr = cx.expr_ident(trait_.span, ident);
|
let arg_expr = cx.expr_ident(trait_.span, ident);
|
||||||
|
@ -1210,7 +1210,7 @@ impl<'a> MethodDef<'a> {
|
||||||
let vi_idents = self_arg_names.iter()
|
let vi_idents = self_arg_names.iter()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
let vi_suffix = format!("{}_vi", &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>>();
|
.collect::<Vec<ast::Ident>>();
|
||||||
|
|
||||||
|
@ -1387,7 +1387,10 @@ impl<'a> MethodDef<'a> {
|
||||||
let variant_value =
|
let variant_value =
|
||||||
deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);
|
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 variant_disr = cx.expr_cast(sp, variant_value, target_ty);
|
||||||
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
|
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
|
||||||
index_let_stmts.push(let_stmt);
|
index_let_stmts.push(let_stmt);
|
||||||
|
@ -1588,7 +1591,7 @@ impl<'a> TraitDef<'a> {
|
||||||
let mut ident_exprs = Vec::new();
|
let mut ident_exprs = Vec::new();
|
||||||
for (i, struct_field) in struct_def.fields().iter().enumerate() {
|
for (i, struct_field) in struct_def.fields().iter().enumerate() {
|
||||||
let sp = struct_field.span.with_ctxt(self.span.ctxt());
|
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));
|
paths.push(ident.with_span_pos(sp));
|
||||||
let val = cx.expr_path(cx.path_ident(sp, ident));
|
let val = cx.expr_path(cx.path_ident(sp, ident));
|
||||||
let val = if use_temporaries {
|
let val = if use_temporaries {
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl<'a> Path<'a> {
|
||||||
self_ty: Ident,
|
self_ty: Ident,
|
||||||
self_generics: &Generics)
|
self_generics: &Generics)
|
||||||
-> ast::Path {
|
-> 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 lt = mk_lifetimes(cx, span, &self.lifetime);
|
||||||
let tys: Vec<P<ast::Ty>> =
|
let tys: Vec<P<ast::Ty>> =
|
||||||
self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
|
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)
|
cx.trait_bound(path)
|
||||||
})
|
})
|
||||||
.collect();
|
.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 {
|
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 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 arg = Path::new_local(typaram);
|
||||||
let hash_trait_def = TraitDef {
|
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
|
/// Constructs an expression that calls an intrinsic
|
||||||
fn call_intrinsic(cx: &ExtCtxt<'_>,
|
fn call_intrinsic(cx: &ExtCtxt<'_>,
|
||||||
span: Span,
|
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…
Add table
Add a link
Reference in a new issue