From f84d081a7e705da1f3e920801319424b53cfd8b0 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 6 Sep 2016 09:47:35 +0000 Subject: [PATCH 1/2] Avoid instaiblity errors in code generated by `syntax_ext::deriving::call_intrinsic()`. --- src/libsyntax_ext/deriving/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 5582166c12e9c..fcbce36389082 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -338,10 +338,19 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { /// Constructs an expression that calls an intrinsic fn call_intrinsic(cx: &ExtCtxt, - span: Span, + mut span: Span, intrinsic: &str, args: Vec>) -> P { + span.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo { + call_site: span, + callee: codemap::NameAndSpan { + format: codemap::MacroAttribute(intern("derive")), + span: Some(span), + allow_internal_unstable: true, + }, + }); + let path = cx.std_path(&["intrinsics", intrinsic]); let call = cx.expr_call_global(span, path, args); From d6ea10ec764bbddd39cc4a3d34b6a4987ac867a6 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 7 Sep 2016 03:09:09 +0000 Subject: [PATCH 2/2] Add regression test. --- .../auxiliary/custom_derive_partial_eq.rs | 81 +++++++++++++++++++ .../custom-derive-partial-eq.rs | 22 +++++ 2 files changed, 103 insertions(+) create mode 100644 src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs create mode 100644 src/test/run-pass-fulldeps/custom-derive-partial-eq.rs diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs new file mode 100644 index 0000000000000..956f789dab839 --- /dev/null +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs @@ -0,0 +1,81 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![feature(plugin_registrar, rustc_private, item_like_imports)] + +extern crate syntax; +extern crate syntax_ext; +extern crate rustc_plugin; + +use syntax_ext::deriving; +use deriving::generic::*; +use deriving::generic::ty::*; + +use rustc_plugin::Registry; +use syntax::ast::*; +use syntax::codemap::Span; +use syntax::ext::base::*; +use syntax::ext::build::AstBuilder; +use syntax::parse::token::{intern, InternedString}; +use syntax::ptr::P; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_syntax_extension(intern("derive_CustomPartialEq"), + MultiDecorator(Box::new(expand_deriving_partial_eq))); +} + +fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, item: &Annotatable, + push: &mut FnMut(Annotatable)) { + // structures are equal if all fields are equal, and non equal, if + // any fields are not equal or if the enum variants are different + fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { + cs_fold(true, + |cx, span, subexpr, self_f, other_fs| { + let other_f = (other_fs.len(), other_fs.get(0)).1.unwrap(); + let eq = cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone()); + cx.expr_binary(span, BinOpKind::And, subexpr, eq) + }, + cx.expr_bool(span, true), + Box::new(|cx, span, _, _| cx.expr_bool(span, false)), + cx, + span, + substr) + } + + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + let methods = vec![MethodDef { + name: "eq", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec!(borrowed_self()), + ret_ty: Literal(deriving::generic::ty::Path::new_local("bool")), + attributes: attrs, + is_unsafe: false, + unify_fieldless_variants: true, + combine_substructure: combine_substructure(Box::new(cs_eq)), + }]; + + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: deriving::generic::ty::Path::new(vec!["std", "cmp", "PartialEq"]), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + is_unsafe: false, + supports_unions: false, + methods: methods, + associated_types: Vec::new(), + }; + trait_def.expand(cx, mitem, item, push) +} diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs new file mode 100644 index 0000000000000..8cc7ab4219dc5 --- /dev/null +++ b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs @@ -0,0 +1,22 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:custom_derive_partial_eq.rs +// ignore-stage1 +// ignore-pretty : (#23623) problems when ending with // comments + +#![feature(plugin, custom_derive)] +#![plugin(custom_derive_partial_eq)] +#![allow(unused)] + +#[derive(CustomPartialEq)] // Check that this is not a stability error. +enum E { V1, V2 } + +fn main() {}