From a0fba3e7059890a376b96e6dd3889fb748115592 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 5 Jan 2017 01:19:54 +0200 Subject: [PATCH 01/18] fix promotion of MIR terminators promotion of MIR terminators used to try to promote the destination it is trying to promote, leading to stack overflow. Fixes #37991. --- src/librustc_mir/transform/promote_consts.rs | 144 +++++++++---------- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/test/run-pass/issue-37991.rs | 20 +++ 3 files changed, 87 insertions(+), 79 deletions(-) create mode 100644 src/test/run-pass/issue-37991.rs diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 41698574e0f1f..2a4b2b515cc68 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -66,6 +66,7 @@ impl TempState { /// A "root candidate" for promotion, which will become the /// returned value in a promoted MIR, unless it's a subset /// of a larger candidate. +#[derive(Debug)] pub enum Candidate { /// Borrow of a constant temporary. Ref(Location), @@ -190,15 +191,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { /// promoted MIR, recursing through temps. fn promote_temp(&mut self, temp: Local) -> Local { let old_keep_original = self.keep_original; - let (bb, stmt_idx) = match self.temps[temp] { - TempState::Defined { - location: Location { block, statement_index }, - uses - } if uses > 0 => { + let loc = match self.temps[temp] { + TempState::Defined { location, uses } if uses > 0 => { if uses > 1 { self.keep_original = true; } - (block, statement_index) + location } state => { span_bug!(self.promoted.span, "{:?} not promotable: {:?}", @@ -209,91 +207,80 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.temps[temp] = TempState::PromotedOut; } - let no_stmts = self.source[bb].statements.len(); + let no_stmts = self.source[loc.block].statements.len(); + let new_temp = self.promoted.local_decls.push( + LocalDecl::new_temp(self.source.local_decls[temp].ty)); + + debug!("promote({:?} @ {:?}/{:?}, {:?})", + temp, loc, no_stmts, self.keep_original); // First, take the Rvalue or Call out of the source MIR, // or duplicate it, depending on keep_original. - let (mut rvalue, mut call) = (None, None); - let source_info = if stmt_idx < no_stmts { - let statement = &mut self.source[bb].statements[stmt_idx]; - let rhs = match statement.kind { - StatementKind::Assign(_, ref mut rhs) => rhs, - _ => { - span_bug!(statement.source_info.span, "{:?} is not an assignment", - statement); - } + if loc.statement_index < no_stmts { + let (mut rvalue, source_info) = { + let statement = &mut self.source[loc.block].statements[loc.statement_index]; + let rhs = match statement.kind { + StatementKind::Assign(_, ref mut rhs) => rhs, + _ => { + span_bug!(statement.source_info.span, "{:?} is not an assignment", + statement); + } + }; + + (if self.keep_original { + rhs.clone() + } else { + let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]); + mem::replace(rhs, unit) + }, statement.source_info) }; - if self.keep_original { - rvalue = Some(rhs.clone()); - } else { - let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]); - rvalue = Some(mem::replace(rhs, unit)); - } - statement.source_info - } else if self.keep_original { - let terminator = self.source[bb].terminator().clone(); - call = Some(terminator.kind); - terminator.source_info + + self.visit_rvalue(&mut rvalue, loc); + self.assign(new_temp, rvalue, source_info.span); } else { - let terminator = self.source[bb].terminator_mut(); - let target = match terminator.kind { - TerminatorKind::Call { - destination: ref mut dest @ Some(_), - ref mut cleanup, .. - } => { - // No cleanup necessary. - cleanup.take(); - - // We'll put a new destination in later. - dest.take().unwrap().1 - } - ref kind => { - span_bug!(terminator.source_info.span, "{:?} not promotable", kind); + let mut terminator = if self.keep_original { + self.source[loc.block].terminator().clone() + } else { + let terminator = self.source[loc.block].terminator_mut(); + let target = match terminator.kind { + TerminatorKind::Call { destination: Some((_, target)), .. } => target, + ref kind => { + span_bug!(terminator.source_info.span, "{:?} not promotable", kind); + } + }; + Terminator { + source_info: terminator.source_info, + kind: mem::replace(&mut terminator.kind, TerminatorKind::Goto { + target: target + }) } }; - call = Some(mem::replace(&mut terminator.kind, TerminatorKind::Goto { - target: target - })); - terminator.source_info - }; - // Then, recurse for components in the Rvalue or Call. - if stmt_idx < no_stmts { - self.visit_rvalue(rvalue.as_mut().unwrap(), Location { - block: bb, - statement_index: stmt_idx - }); - } else { - self.visit_terminator_kind(bb, call.as_mut().unwrap(), Location { - block: bb, - statement_index: no_stmts - }); - } - - let new_temp = self.promoted.local_decls.push( - LocalDecl::new_temp(self.source.local_decls[temp].ty)); - - // Inject the Rvalue or Call into the promoted MIR. - if stmt_idx < no_stmts { - self.assign(new_temp, rvalue.unwrap(), source_info.span); - } else { let last = self.promoted.basic_blocks().last().unwrap(); let new_target = self.new_block(); - let mut call = call.unwrap(); - match call { - TerminatorKind::Call { ref mut destination, ..} => { - *destination = Some((Lvalue::Local(new_temp), new_target)); + + terminator.kind = match terminator.kind { + TerminatorKind::Call { mut func, mut args, .. } => { + self.visit_operand(&mut func, loc); + for arg in &mut args { + self.visit_operand(arg, loc); + } + TerminatorKind::Call { + func: func, + args: args, + cleanup: None, + destination: Some((Lvalue::Local(new_temp), new_target)) + } } - _ => bug!() - } - let terminator = self.promoted[last].terminator_mut(); - terminator.source_info.span = source_info.span; - terminator.kind = call; - } + ref kind => { + span_bug!(terminator.source_info.span, "{:?} not promotable", kind); + } + }; - // Restore the old duplication state. - self.keep_original = old_keep_original; + *self.promoted[last].terminator_mut() = terminator; + }; + self.keep_original = old_keep_original; new_temp } @@ -355,6 +342,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, mut temps: IndexVec, candidates: Vec) { // Visit candidates in reverse, in case they're nested. + debug!("promote_candidates({:?})", candidates); for candidate in candidates.into_iter().rev() { let (span, ty) = match candidate { Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 893478a933182..d144651fb7db6 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -993,9 +993,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { Entry::Vacant(entry) => { // Guard against `const` recursion. entry.insert(Qualif::RECURSIVE); + Mode::Const } } - Mode::Const } MirSource::Static(_, hir::MutImmutable) => Mode::Static, MirSource::Static(_, hir::MutMutable) => Mode::StaticMut, diff --git a/src/test/run-pass/issue-37991.rs b/src/test/run-pass/issue-37991.rs new file mode 100644 index 0000000000000..cacc653871ad5 --- /dev/null +++ b/src/test/run-pass/issue-37991.rs @@ -0,0 +1,20 @@ +// 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. + +#![feature(const_fn)] + +const fn foo() -> i64 { + 3 +} + +fn main() { + let val = &(foo() % 2); + assert_eq!(*val, 1); +} From 2d32335778c2ee9f6902dabc4777ae185c98c3b1 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 3 Jan 2017 00:36:34 +0000 Subject: [PATCH 02/18] Fix regression with duplicate `#[macro_export] macro_rules!`. --- src/librustc_resolve/resolve_imports.rs | 8 +++++++- src/test/run-pass/auxiliary/issue_38715.rs | 15 +++++++++++++++ src/test/run-pass/issue-38715.rs | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/auxiliary/issue_38715.rs create mode 100644 src/test/run-pass/issue-38715.rs diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 208c43d898ce0..5ea79ece37af4 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -20,6 +20,7 @@ use {resolve_error, ResolutionError}; use rustc::ty; use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def::*; +use rustc::util::nodemap::FxHashSet; use syntax::ast::{Ident, NodeId, Name}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; @@ -723,7 +724,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); if module as *const _ == self.graph_root as *const _ { - reexports = mem::replace(&mut self.macro_exports, Vec::new()); + let mut exported_macro_names = FxHashSet(); + for export in mem::replace(&mut self.macro_exports, Vec::new()).into_iter().rev() { + if exported_macro_names.insert(export.name) { + reexports.push(export); + } + } } for (&(name, ns), resolution) in module.resolutions.borrow().iter() { diff --git a/src/test/run-pass/auxiliary/issue_38715.rs b/src/test/run-pass/auxiliary/issue_38715.rs new file mode 100644 index 0000000000000..cad3996eadbfb --- /dev/null +++ b/src/test/run-pass/auxiliary/issue_38715.rs @@ -0,0 +1,15 @@ +// 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. + +#[macro_export] +macro_rules! foo { ($i:ident) => {} } + +#[macro_export] +macro_rules! foo { () => {} } diff --git a/src/test/run-pass/issue-38715.rs b/src/test/run-pass/issue-38715.rs new file mode 100644 index 0000000000000..054785e62b8ea --- /dev/null +++ b/src/test/run-pass/issue-38715.rs @@ -0,0 +1,20 @@ +// 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:issue_38715.rs + +// Test that `#[macro_export] macro_rules!` shadow earlier `#[macro_export] macro_rules!` + +#[macro_use] +extern crate issue_38715; + +fn main() { + foo!(); +} From 13eba5e84853d8ca58a55ac95970030f42d56fe6 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Sat, 31 Dec 2016 16:02:06 +1030 Subject: [PATCH 03/18] Stop macro calls in structs for proc_macro_derive from panicing --- src/librustc_resolve/macros.rs | 5 ++++ src/libsyntax_ext/deriving/custom.rs | 5 +++- .../proc-macro/auxiliary/derive-nothing.rs | 24 +++++++++++++++ .../proc-macro/struct-field-macro.rs | 29 +++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 613829bab8be3..980493973d545 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -28,6 +28,7 @@ use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::fold::Folder; +use syntax::fold; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::Visitor; @@ -117,6 +118,10 @@ impl<'a> base::Resolver for Resolver<'a> { } path } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } } EliminateCrateVar(self).fold_item(item).expect_one("") diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 6f02a348f91dc..811aea4a9eb7e 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -12,7 +12,7 @@ use std::panic; use errors::FatalError; use proc_macro::{TokenStream, __internal}; -use syntax::ast::{self, ItemKind, Attribute}; +use syntax::ast::{self, ItemKind, Attribute, Mac}; use syntax::attr::{mark_used, mark_known}; use syntax::codemap::Span; use syntax::ext::base::*; @@ -28,6 +28,9 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { mark_known(attr); } } + + fn visit_mac(&mut self, _mac: &Mac) { + } } pub struct CustomDerive { diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs new file mode 100644 index 0000000000000..a9257cb4c8b78 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs @@ -0,0 +1,24 @@ +// 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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro)] +#![feature(proc_macro_lib)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Nothing)] +pub fn nothing(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs new file mode 100644 index 0000000000000..68da011e5a5bb --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs @@ -0,0 +1,29 @@ +// 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:derive-nothing.rs +// ignore-stage1 + +#![feature(proc_macro)] + +#[macro_use] +extern crate derive_nothing; + +macro_rules! int { + () => { i32 } +} + +#[derive(Nothing)] +struct S { + x: int!(), +} + +fn main() { +} From d86ed7896218134b23a208b5496da066c200538d Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Sat, 31 Dec 2016 17:55:59 +1030 Subject: [PATCH 04/18] Style fixes --- src/librustc_resolve/macros.rs | 3 +-- src/libsyntax_ext/deriving/custom.rs | 3 +-- src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 980493973d545..59452d3040e8f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -27,8 +27,7 @@ use syntax::ext::expand::Expansion; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, GateIssue}; -use syntax::fold::Folder; -use syntax::fold; +use syntax::fold::{self, Folder}; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::Visitor; diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 811aea4a9eb7e..64ec460a52460 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -29,8 +29,7 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { } } - fn visit_mac(&mut self, _mac: &Mac) { - } + fn visit_mac(&mut self, _mac: &Mac) {} } pub struct CustomDerive { diff --git a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs index 68da011e5a5bb..818308b05a44e 100644 --- a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs @@ -25,5 +25,4 @@ struct S { x: int!(), } -fn main() { -} +fn main() {} From 7bb20bcfedba996bec708108ca57fec0043ee72a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 29 Dec 2016 16:00:53 -0500 Subject: [PATCH 05/18] Dont check stability for items that are not pub to universe. Includes special case handling for trait methods. Fix #38412. --- src/librustc/middle/stability.rs | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 3e32957aecfe0..5cd82bd363b45 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -18,7 +18,7 @@ use hir::map as hir_map; use lint; use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE}; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use middle::privacy::AccessLevels; use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; @@ -436,6 +436,36 @@ struct Checker<'a, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + // (See issue #38412) + fn skip_stability_check_due_to_privacy(self, def_id: DefId) -> bool { + let visibility = { + // Check if `def_id` is a trait method. + match self.sess.cstore.associated_item(def_id) { + Some(ty::AssociatedItem { container: ty::TraitContainer(trait_def_id), .. }) => { + // Trait methods do not declare visibility (even + // for visibility info in cstore). Use containing + // trait instead, so methods of pub traits are + // themselves considered pub. + self.sess.cstore.visibility(trait_def_id) + } + _ => { + // Otherwise, cstore info works directly. + self.sess.cstore.visibility(def_id) + } + } + }; + + match visibility { + // must check stability for pub items. + ty::Visibility::Public => false, + + // these are not visible outside crate; therefore + // stability markers are irrelevant, if even present. + ty::Visibility::Restricted(..) | + ty::Visibility::Invisible => true, + } + } + pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) { if self.sess.codemap().span_allows_unstable(span) { debug!("stability: \ @@ -496,6 +526,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.stability.borrow_mut().used_features.insert(feature.clone(), level.clone()); } + // Issue 38412: private items lack stability markers. + if self.skip_stability_check_due_to_privacy(def_id) { + return + } + match stability { Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => { if !self.stability.borrow().active_features.contains(feature) { From 2d858a0b6b01959c33b0d3d6fe23070b51ff1517 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 3 Jan 2017 09:54:38 -0500 Subject: [PATCH 06/18] Regression test and exploratory unit test. --- .../auxiliary/pub_and_stability.rs | 144 ++++++++++++++++++ .../explore-issue-38412.rs | 85 +++++++++++ src/test/compile-fail/issue-38412.rs | 20 +++ 3 files changed, 249 insertions(+) create mode 100644 src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs create mode 100644 src/test/compile-fail-fulldeps/explore-issue-38412.rs create mode 100644 src/test/compile-fail/issue-38412.rs diff --git a/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs b/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs new file mode 100644 index 0000000000000..9dc4cf1252ec3 --- /dev/null +++ b/src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs @@ -0,0 +1,144 @@ +// Copyright 2017 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. + +// This crate attempts to enumerate the various scenarios for how a +// type can define fields and methods with various visiblities and +// stabilities. +// +// The basic stability pattern in this file has four cases: +// 1. no stability attribute at all +// 2. a stable attribute (feature "unit_test") +// 3. an unstable attribute that unit test declares (feature "unstable_declared") +// 4. an unstable attribute that unit test fails to declare (feature "unstable_undeclared") +// +// This file also covers four kinds of visibility: private, +// pub(module), pub(crate), and pub. +// +// However, since stability attributes can only be observed in +// cross-crate linkage scenarios, there is little reason to take the +// cross-product (4 stability cases * 4 visiblity cases), because the +// first three visibility cases cannot be accessed outside this crate, +// and therefore stability is only relevant when the visibility is pub +// to the whole universe. +// +// (The only reason to do so would be if one were worried about the +// compiler having some subtle bug where adding a stability attribute +// introduces a privacy violation. As a way to provide evidence that +// this is not occurring, I have put stability attributes on some +// non-pub fields, marked with SILLY below) + +#![feature(staged_api)] +#![feature(pub_restricted)] + +#![stable(feature = "unit_test", since = "0.0.0")] + +#[stable(feature = "unit_test", since = "0.0.0")] +pub use m::{Record, Trait, Tuple}; + +mod m { + #[derive(Default)] + #[stable(feature = "unit_test", since = "0.0.0")] + pub struct Record { + #[stable(feature = "unit_test", since = "0.0.0")] + pub a_stable_pub: i32, + #[unstable(feature = "unstable_declared", issue = "38412")] + pub a_unstable_declared_pub: i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub a_unstable_undeclared_pub: i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY + pub(crate) b_crate: i32, + #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY + pub(m) c_mod: i32, + #[stable(feature = "unit_test", since = "0.0.0")] // SILLY + d_priv: i32 + } + + #[derive(Default)] + #[stable(feature = "unit_test", since = "1.0.0")] + pub struct Tuple( + #[stable(feature = "unit_test", since = "0.0.0")] + pub i32, + #[unstable(feature = "unstable_declared", issue = "38412")] + pub i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub i32, + + pub(crate) i32, + pub(m) i32, + i32); + + impl Record { + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn new() -> Self { Default::default() } + } + + impl Tuple { + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn new() -> Self { Default::default() } + } + + + #[stable(feature = "unit_test", since = "0.0.0")] + pub trait Trait { + #[stable(feature = "unit_test", since = "0.0.0")] + type Type; + #[stable(feature = "unit_test", since = "0.0.0")] + fn stable_trait_method(&self) -> Self::Type; + #[unstable(feature = "unstable_undeclared", issue = "38412")] + fn unstable_undeclared_trait_method(&self) -> Self::Type; + #[unstable(feature = "unstable_declared", issue = "38412")] + fn unstable_declared_trait_method(&self) -> Self::Type; + } + + #[stable(feature = "unit_test", since = "0.0.0")] + impl Trait for Record { + type Type = i32; + fn stable_trait_method(&self) -> i32 { self.d_priv } + fn unstable_undeclared_trait_method(&self) -> i32 { self.d_priv } + fn unstable_declared_trait_method(&self) -> i32 { self.d_priv } + } + + #[stable(feature = "unit_test", since = "0.0.0")] + impl Trait for Tuple { + type Type = i32; + fn stable_trait_method(&self) -> i32 { self.3 } + fn unstable_undeclared_trait_method(&self) -> i32 { self.3 } + fn unstable_declared_trait_method(&self) -> i32 { self.3 } + } + + impl Record { + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub fn unstable_undeclared(&self) -> i32 { self.d_priv } + #[unstable(feature = "unstable_declared", issue = "38412")] + pub fn unstable_declared(&self) -> i32 { self.d_priv } + #[stable(feature = "unit_test", since = "0.0.0")] + pub fn stable(&self) -> i32 { self.d_priv } + + #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY + pub(crate) fn pub_crate(&self) -> i32 { self.d_priv } + #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY + pub(m) fn pub_mod(&self) -> i32 { self.d_priv } + #[stable(feature = "unit_test", since = "0.0.0")] // SILLY + fn private(&self) -> i32 { self.d_priv } + } + + impl Tuple { + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub fn unstable_undeclared(&self) -> i32 { self.0 } + #[unstable(feature = "unstable_declared", issue = "38412")] + pub fn unstable_declared(&self) -> i32 { self.0 } + #[stable(feature = "unit_test", since = "0.0.0")] + pub fn stable(&self) -> i32 { self.0 } + + pub(crate) fn pub_crate(&self) -> i32 { self.0 } + pub(m) fn pub_mod(&self) -> i32 { self.0 } + fn private(&self) -> i32 { self.0 } + } +} diff --git a/src/test/compile-fail-fulldeps/explore-issue-38412.rs b/src/test/compile-fail-fulldeps/explore-issue-38412.rs new file mode 100644 index 0000000000000..aab92575321e3 --- /dev/null +++ b/src/test/compile-fail-fulldeps/explore-issue-38412.rs @@ -0,0 +1,85 @@ +// Copyright 2014 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:pub_and_stability.rs + +#![feature(staged_api)] +#![feature(unused_feature)] + +// A big point of this test is that we *declare* `unstable_declared`, +// but do *not* declare `unstable_undeclared`. This way we can check +// that the compiler is letting in uses of declared feature-gated +// stuff but still rejecting uses of undeclared feature-gated stuff. +#![feature(unstable_declared)] + +extern crate pub_and_stability; +use pub_and_stability::{Record, Trait, Tuple}; + +fn main() { + // Okay + let Record { .. } = Record::new(); + // Okay (for now; see RFC Issue #902) + let Tuple(..) = Tuple::new(); + + // Okay + let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new(); + // Okay (for now; see RFC Issue #902) + let Tuple(_, _, ..) = Tuple::new(); // analogous to above + + let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = + Record::new(); + //~^^ ERROR use of unstable library feature 'unstable_undeclared' + + let Tuple(_, _, _, ..) = Tuple::new(); // analogous to previous + //~^ ERROR use of unstable library feature 'unstable_undeclared' + + let r = Record::new(); + let t = Tuple::new(); + + r.a_stable_pub; + r.a_unstable_declared_pub; + r.a_unstable_undeclared_pub; //~ ERROR use of unstable library feature + r.b_crate; //~ ERROR is private + r.c_mod; //~ ERROR is private + r.d_priv; //~ ERROR is private + + t.0; + t.1; + t.2; //~ ERROR use of unstable library feature + t.3; //~ ERROR is private + t.4; //~ ERROR is private + t.5; //~ ERROR is private + + r.stable_trait_method(); + r.unstable_declared_trait_method(); + r.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + + r.stable(); + r.unstable_declared(); + r.unstable_undeclared(); //~ ERROR use of unstable library feature + + r.pub_crate(); //~ ERROR `pub_crate` is private + r.pub_mod(); //~ ERROR `pub_mod` is private + r.private(); //~ ERROR `private` is private + + let t = Tuple::new(); + t.stable_trait_method(); + t.unstable_declared_trait_method(); + t.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + + t.stable(); + t.unstable_declared(); + t.unstable_undeclared(); //~ ERROR use of unstable library feature + + t.pub_crate(); //~ ERROR `pub_crate` is private + t.pub_mod(); //~ ERROR `pub_mod` is private + t.private(); //~ ERROR `private` is private + +} diff --git a/src/test/compile-fail/issue-38412.rs b/src/test/compile-fail/issue-38412.rs new file mode 100644 index 0000000000000..00305eb2bc04b --- /dev/null +++ b/src/test/compile-fail/issue-38412.rs @@ -0,0 +1,20 @@ +// 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. + +fn main() { + let Box(a) = loop { }; + //~^ ERROR field `0` of struct `std::boxed::Box` is private + + // (The below is a trick to allow compiler to infer a type for + // variable `a` without attempting to ascribe a type to the + // pattern or otherwise attempting to name the Box type, which + // would run afoul of issue #22207) + let _b: *mut i32 = *a; +} From 544d7e231fa70a70af2fe380947100f20297b8e2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Jan 2017 09:46:44 -0500 Subject: [PATCH 07/18] rebase: remove `tcx` from `associated_item` --- src/librustc/middle/cstore.rs | 5 ++--- src/librustc/middle/stability.rs | 2 +- src/librustc/ty/mod.rs | 4 ++-- src/librustc_metadata/cstore_impl.rs | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index f2be97c832370..7ec0ef00780f2 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -298,8 +298,7 @@ pub trait CrateStore<'tcx> { // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option; - fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option; + fn associated_item(&self, def: DefId) -> Option; // flags fn is_const_fn(&self, did: DefId) -> bool; @@ -462,7 +461,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } - fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + fn associated_item<'a>(&self, def: DefId) -> Option { bug!("associated_item") } // flags diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5cd82bd363b45..a2c4b59db14f5 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // these are not visible outside crate; therefore // stability markers are irrelevant, if even present. ty::Visibility::Restricted(..) | - ty::Visibility::Invisible => true, + ty::Visibility::PrivateExternal => true, } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index df12c252907a5..dd1a6caa02fd4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2062,7 +2062,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn associated_item(self, def_id: DefId) -> AssociatedItem { self.associated_items.memoize(def_id, || { if !def_id.is_local() { - return self.sess.cstore.associated_item(self.global_tcx(), def_id) + return self.sess.cstore.associated_item(def_id) .expect("missing AssociatedItem in metadata"); } @@ -2540,7 +2540,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// ID of the impl that the method belongs to. Otherwise, return `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.associated_item(self.global_tcx(), def_id) + return self.sess.cstore.associated_item(def_id) .and_then(|item| { match item.container { TraitContainer(_) => None, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 1a1bb1432eec1..79daab6bbc4fc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -189,8 +189,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index) } - fn associated_item<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option + fn associated_item<'a>(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_associated_item(def.index) From 825c536e3720c939b374591cba9b8eee5efc524a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 22 Dec 2016 19:46:08 +0200 Subject: [PATCH 08/18] Don't leak the compiler's internal representation of scopes in error messages. --- src/librustc/infer/error_reporting.rs | 56 ++++++++++++++++++++------- src/test/compile-fail/issue-27942.rs | 31 +++++++++++++++ src/test/compile-fail/issue-37884.rs | 27 +++++++++++++ 3 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 src/test/compile-fail/issue-27942.rs create mode 100644 src/test/compile-fail/issue-37884.rs diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 90d752ae6ee29..28edf3c587b19 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -114,6 +114,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { + match item.node { + hir::MethodTraitItem(..) => "method body", + hir::ConstTraitItem(..) | + hir::TypeTraitItem(..) => "associated item" + } + } + + fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str { + match item.node { + hir::ImplItemKind::Method(..) => "method body", + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Type(_) => "associated item" + } + } + fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, heading: &str, span: Span) -> (String, Option) { @@ -149,6 +165,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }, Some(ast_map::NodeStmt(_)) => "statement", Some(ast_map::NodeItem(it)) => item_scope_tag(&it), + Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), + Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it), Some(_) | None => { err.span_note(span, &unknown_scope()); return; @@ -187,23 +205,31 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } }; - match self.map.find(fr.scope.node_id(&self.region_maps)) { - Some(ast_map::NodeBlock(ref blk)) => { - let (msg, opt_span) = explain_span(self, "block", blk.span); - (format!("{} {}", prefix, msg), opt_span) - } - Some(ast_map::NodeItem(it)) => { - let tag = item_scope_tag(&it); - let (msg, opt_span) = explain_span(self, tag, it.span); - (format!("{} {}", prefix, msg), opt_span) + let node = fr.scope.node_id(&self.region_maps); + let unknown; + let tag = match self.map.find(node) { + Some(ast_map::NodeBlock(_)) | + Some(ast_map::NodeExpr(_)) => "body", + Some(ast_map::NodeItem(it)) => item_scope_tag(&it), + Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), + Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it), + + // this really should not happen, but it does: + // FIXME(#27942) + Some(_) => { + unknown = format!("unexpected node ({}) for scope {:?}. \ + Please report a bug.", + self.map.node_to_string(node), fr.scope); + &unknown } - Some(_) | None => { - // this really should not happen, but it does: - // FIXME(#27942) - (format!("{} unknown free region bounded by scope {:?}", - prefix, fr.scope), None) + None => { + unknown = format!("unknown node for scope {:?}. \ + Please report a bug.", fr.scope); + &unknown } - } + }; + let (msg, opt_span) = explain_span(self, tag, self.map.span(node)); + (format!("{} {}", prefix, msg), opt_span) } ty::ReStatic => ("the static lifetime".to_owned(), None), diff --git a/src/test/compile-fail/issue-27942.rs b/src/test/compile-fail/issue-27942.rs new file mode 100644 index 0000000000000..b8552794eb5ae --- /dev/null +++ b/src/test/compile-fail/issue-27942.rs @@ -0,0 +1,31 @@ +// 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. + +pub trait Resources<'a> {} + +pub trait Buffer<'a, R: Resources<'a>> { + fn select(&self) -> BufferViewHandle; + //~^ ERROR mismatched types + //~| lifetime mismatch + //~| NOTE expected type `Resources<'_>` + //~| NOTE found type `Resources<'a>` + //~| NOTE the lifetime 'a as defined on the method body at 14:4... + //~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body + //~| ERROR mismatched types + //~| lifetime mismatch + //~| NOTE expected type `Resources<'_>` + //~| NOTE found type `Resources<'a>` + //~| NOTE the anonymous lifetime #1 defined on the method body at 14:4... + //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body +} + +pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R); + +fn main() {} diff --git a/src/test/compile-fail/issue-37884.rs b/src/test/compile-fail/issue-37884.rs new file mode 100644 index 0000000000000..a73b1dbe34cff --- /dev/null +++ b/src/test/compile-fail/issue-37884.rs @@ -0,0 +1,27 @@ +// 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. + +struct RepeatMut<'a, T>(T, &'a ()); + +impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { + type Item = &'a mut T; + fn next(&'a mut self) -> Option + //~^ ERROR method not compatible with trait + //~| lifetime mismatch + //~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>` + //~| NOTE found type `fn(&'a mut RepeatMut<'a, T>) -> std::option::Option<&mut T>` + { + //~^ NOTE the anonymous lifetime #1 defined on the body + //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body + Some(&mut self.0) + } +} + +fn main() {} From ca3710a3ddca316cee557085df99adc02c030934 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 4 Jan 2017 04:36:20 +0200 Subject: [PATCH 09/18] Update for changes to TraitItem on master. --- src/librustc/infer/error_reporting.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 28edf3c587b19..a0604f229a6e5 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -116,9 +116,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { match item.node { - hir::MethodTraitItem(..) => "method body", - hir::ConstTraitItem(..) | - hir::TypeTraitItem(..) => "associated item" + hir::TraitItemKind::Method(..) => "method body", + hir::TraitItemKind::Const(..) | + hir::TraitItemKind::Type(..) => "associated item" } } From 7815a16341151badbd07569951c8bd10232f559d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 20 Dec 2016 21:22:09 +0000 Subject: [PATCH 10/18] Fix rustdoc ICE. --- src/librustc_metadata/decoder.rs | 1 + src/test/run-make/issue-38237/Makefile | 5 +++++ src/test/run-make/issue-38237/bar.rs | 14 ++++++++++++++ src/test/run-make/issue-38237/baz.rs | 18 ++++++++++++++++++ src/test/run-make/issue-38237/foo.rs | 20 ++++++++++++++++++++ 5 files changed, 58 insertions(+) create mode 100644 src/test/run-make/issue-38237/Makefile create mode 100644 src/test/run-make/issue-38237/bar.rs create mode 100644 src/test/run-make/issue-38237/baz.rs create mode 100644 src/test/run-make/issue-38237/foo.rs diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 539c05b71bb1c..af325cefa6271 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1021,6 +1021,7 @@ impl<'a, 'tcx> CrateMetadata { let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), Some(None) => return, + None if self.proc_macros.is_some() => return, None => None, }; diff --git a/src/test/run-make/issue-38237/Makefile b/src/test/run-make/issue-38237/Makefile new file mode 100644 index 0000000000000..0a681401b1afb --- /dev/null +++ b/src/test/run-make/issue-38237/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs; $(RUSTC) bar.rs + $(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR) diff --git a/src/test/run-make/issue-38237/bar.rs b/src/test/run-make/issue-38237/bar.rs new file mode 100644 index 0000000000000..794e08c2fe338 --- /dev/null +++ b/src/test/run-make/issue-38237/bar.rs @@ -0,0 +1,14 @@ +// 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. + +#![crate_type = "lib"] + +#[derive(Debug)] +pub struct S; diff --git a/src/test/run-make/issue-38237/baz.rs b/src/test/run-make/issue-38237/baz.rs new file mode 100644 index 0000000000000..c2a2c89db016f --- /dev/null +++ b/src/test/run-make/issue-38237/baz.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate foo; +extern crate bar; + +pub struct Bar; +impl ::std::ops::Deref for Bar { + type Target = bar::S; + fn deref(&self) -> &Self::Target { unimplemented!() } +} diff --git a/src/test/run-make/issue-38237/foo.rs b/src/test/run-make/issue-38237/foo.rs new file mode 100644 index 0000000000000..c291ffbf4e856 --- /dev/null +++ b/src/test/run-make/issue-38237/foo.rs @@ -0,0 +1,20 @@ +// 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. + +#![crate_type = "proc-macro"] +#![feature(proc_macro, proc_macro_lib)] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { ts } + +#[derive(Debug)] +struct S; From e3a2352164da9e7c2cabbd3b363d038be770efbf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Jan 2017 10:06:25 -0500 Subject: [PATCH 11/18] Revert "Update for changes to TraitItem on master." This reverts commit 1d23be75b95b1dad318020fcf110836a7f17fc80. --- src/librustc/infer/error_reporting.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index a0604f229a6e5..28edf3c587b19 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -116,9 +116,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { match item.node { - hir::TraitItemKind::Method(..) => "method body", - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(..) => "associated item" + hir::MethodTraitItem(..) => "method body", + hir::ConstTraitItem(..) | + hir::TypeTraitItem(..) => "associated item" } } From 3308770abf31d0cf96b956586f417f758a524591 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Fri, 9 Dec 2016 10:54:05 -0800 Subject: [PATCH 12/18] Prevent where < ident > from parsing. In order to be forward compatible with `where<'a>` syntax for higher rank parameters, prevent potential conflicts with UFCS from parsing correctly for the near term. --- src/libsyntax/parse/parser.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a1d4ad9d629c9..41bc8aff1db3e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4378,6 +4378,23 @@ impl<'a> Parser<'a> { return Ok(where_clause); } + // This is a temporary hack. + // + // We are considering adding generics to the `where` keyword as an alternative higher-rank + // parameter syntax (as in `where<'a>` or `where`. To avoid that being a breaking + // change, for now we refuse to parse `where < (ident | lifetime) (> | , | :)`. + if token::Lt == self.token { + let ident_or_lifetime = self.look_ahead(1, |t| t.is_ident() || t.is_lifetime()); + if ident_or_lifetime { + let gt_comma_or_colon = self.look_ahead(2, |t| { + *t == token::Gt || *t == token::Comma || *t == token::Colon + }); + if gt_comma_or_colon { + return Err(self.fatal("TODO How to even explain this error?")); + } + } + } + let mut parsed_something = false; loop { let lo = self.span.lo; From 4a0fba37897ed978d9245dafddfa8ba3377104e0 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Fri, 9 Dec 2016 20:39:42 -0800 Subject: [PATCH 13/18] Improve error message. --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 41bc8aff1db3e..46806678cbdd3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4390,7 +4390,7 @@ impl<'a> Parser<'a> { *t == token::Gt || *t == token::Comma || *t == token::Colon }); if gt_comma_or_colon { - return Err(self.fatal("TODO How to even explain this error?")); + self.err("syntax `where` is reserved for future use"); } } } From e8265751d46e29a7cd75f9e8894087b2b459708b Mon Sep 17 00:00:00 2001 From: Without Boats Date: Fri, 9 Dec 2016 20:40:01 -0800 Subject: [PATCH 14/18] Add test. --- src/test/parse-fail/where_with_bound.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/parse-fail/where_with_bound.rs diff --git a/src/test/parse-fail/where_with_bound.rs b/src/test/parse-fail/where_with_bound.rs new file mode 100644 index 0000000000000..cb57500df797e --- /dev/null +++ b/src/test/parse-fail/where_with_bound.rs @@ -0,0 +1,16 @@ +// 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. + +// compile-flags: -Z parse-only + +fn foo() where ::Item: ToString, T: Iterator { } + //~^ syntax `where` is reserved for future use + +fn main() {} From 0af9fafa0741bf3b095772f166fc3b2b4bc8d5f9 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Fri, 9 Dec 2016 21:17:58 -0800 Subject: [PATCH 15/18] Fix mistake. --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 46806678cbdd3..5bd03cc68ad90 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4390,7 +4390,7 @@ impl<'a> Parser<'a> { *t == token::Gt || *t == token::Comma || *t == token::Colon }); if gt_comma_or_colon { - self.err("syntax `where` is reserved for future use"); + self.span_err(self.span, "syntax `where` is reserved for future use"); } } } From bce648cf9dd438b7c1812f4e41210536efb96502 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 30 Dec 2016 09:29:21 -0800 Subject: [PATCH 16/18] rustbuild: Fix source tarballs and the vendor dir The source tarball creation step would attempt to skip a number of files that we want to ignore ourselves, but once we've hit the vendor directory we don't want to skip anything so be sure to vendor everything inside that directory. Closes #38690 --- src/bootstrap/dist.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index be51a6753fb62..d9663a507d961 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -391,6 +391,13 @@ pub fn rust_src(build: &Build) { } } + // If we're inside the vendor directory then we need to preserve + // everything as Cargo's vendoring support tracks all checksums and we + // want to be sure we don't accidentally leave out a file. + if spath.contains("vendor") { + return true + } + let excludes = [ "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules", ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}", From ce1a38ce20f627e5b6ecd89367102ec786ac30e2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 1 Jan 2017 16:14:35 -0800 Subject: [PATCH 17/18] rustc: Stabilize the `proc_macro` feature This commit stabilizes the `proc_macro` and `proc_macro_lib` features in the compiler to stabilize the "Macros 1.1" feature of the language. Many more details can be found on the tracking issue, #35900. Closes #35900 --- src/libproc_macro/lib.rs | 9 ++++++--- src/librustc_driver/driver.rs | 3 +-- src/librustc_metadata/lib.rs | 1 - src/libsyntax/ext/expand.rs | 1 - src/libsyntax/feature_gate.rs | 12 +++--------- src/libsyntax_ext/deriving/mod.rs | 8 +------- src/libsyntax_ext/lib.rs | 1 - src/libsyntax_ext/proc_macro_registrar.rs | 10 +--------- .../proc-macro/attribute.rs | 1 - .../proc-macro/auxiliary/derive-a-b.rs | 1 - .../proc-macro/auxiliary/derive-a.rs | 2 -- .../proc-macro/auxiliary/derive-b.rs | 2 -- .../proc-macro/auxiliary/derive-bad.rs | 2 -- .../proc-macro/auxiliary/derive-panic.rs | 2 -- .../proc-macro/auxiliary/derive-unstable-2.rs | 2 -- .../proc-macro/auxiliary/derive-unstable.rs | 2 -- .../proc-macro/define-two.rs | 1 - .../proc-macro/derive-bad.rs | 2 -- .../proc-macro/derive-still-gated.rs | 1 - .../proc-macro/expand-to-unstable-2.rs | 1 - .../proc-macro/expand-to-unstable.rs | 1 - .../proc-macro/export-macro.rs | 1 - .../proc-macro/feature-gate-1.rs | 13 ------------- .../proc-macro/feature-gate-2.rs | 13 ------------- .../proc-macro/feature-gate-3.rs | 15 --------------- .../proc-macro/feature-gate-4.rs | 17 ----------------- .../proc-macro/feature-gate-5.rs | 12 ------------ .../proc-macro/illegal-proc-macro-derive-use.rs | 2 -- .../compile-fail-fulldeps/proc-macro/import.rs | 1 - .../proc-macro/issue-37788.rs | 2 -- .../proc-macro/item-error.rs | 1 - .../proc-macro/load-panic.rs | 2 -- .../proc-macro/proc-macro-attributes.rs | 1 - .../proc-macro/pub-at-crate-root.rs | 1 - .../proc-macro/shadow-builtin.rs | 1 - .../compile-fail-fulldeps/proc-macro/shadow.rs | 2 -- .../proc-macro/signature.rs | 1 - src/test/run-make/issue-37839/a.rs | 1 - src/test/run-make/issue-37893/a.rs | 1 - src/test/run-make/issue-38237/foo.rs | 1 - src/test/run-make/rustc-macro-dep-files/bar.rs | 2 -- src/test/run-make/rustc-macro-dep-files/foo.rs | 2 -- .../run-pass-fulldeps/proc-macro/add-impl.rs | 2 -- .../run-pass-fulldeps/proc-macro/append-impl.rs | 1 - .../proc-macro/auxiliary/add-impl.rs | 2 -- .../proc-macro/auxiliary/append-impl.rs | 2 -- .../proc-macro/auxiliary/derive-a.rs | 2 -- .../proc-macro/auxiliary/derive-atob.rs | 2 -- .../proc-macro/auxiliary/derive-b.rs | 2 -- .../proc-macro/auxiliary/derive-ctod.rs | 2 -- .../proc-macro/auxiliary/derive-nothing.rs | 2 -- .../proc-macro/auxiliary/derive-reexport.rs | 2 +- .../proc-macro/auxiliary/derive-same-struct.rs | 3 --- .../proc-macro/auxiliary/double.rs | 2 -- .../proc-macro/auxiliary/expand-with-a-macro.rs | 2 -- .../run-pass-fulldeps/proc-macro/crate-var.rs | 1 - .../run-pass-fulldeps/proc-macro/derive-b.rs | 2 -- .../proc-macro/derive-same-struct.rs | 2 -- .../run-pass-fulldeps/proc-macro/derive-test.rs | 2 -- .../proc-macro/expand-with-a-macro.rs | 1 - .../run-pass-fulldeps/proc-macro/load-two.rs | 2 -- src/test/run-pass-fulldeps/proc-macro/smoke.rs | 2 -- .../proc-macro/struct-field-macro.rs | 2 -- .../proc-macro/use-reexport.rs | 2 -- src/test/rustdoc/rustc-macro-crate.rs | 2 -- 65 files changed, 13 insertions(+), 188 deletions(-) delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-1.rs delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-2.rs delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-3.rs delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-4.rs delete mode 100644 src/test/compile-fail-fulldeps/proc-macro/feature-gate-5.rs diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 5ee9fecfb21b3..1491bdc6c8d31 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -15,8 +15,7 @@ //! Currently the primary use of this crate is to provide the ability to define //! new custom derive modes through `#[proc_macro_derive]`. //! -//! Added recently as part of [RFC 1681] this crate is currently *unstable* and -//! requires the `#![feature(proc_macro_lib)]` directive to use. +//! Added recently as part of [RFC 1681] this crate is stable as of Rust 1.15.0. //! //! [RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md //! @@ -27,7 +26,7 @@ //! area for macro authors is stabilized. #![crate_name = "proc_macro"] -#![unstable(feature = "proc_macro_lib", issue = "27812")] +#![stable(feature = "proc_macro_lib", since = "1.15.0")] #![crate_type = "rlib"] #![crate_type = "dylib"] #![cfg_attr(not(stage0), deny(warnings))] @@ -55,12 +54,14 @@ use syntax::ptr::P; /// /// The API of this type is intentionally bare-bones, but it'll be expanded over /// time! +#[stable(feature = "proc_macro_lib", since = "1.15.0")] pub struct TokenStream { inner: Vec>, } /// Error returned from `TokenStream::from_str`. #[derive(Debug)] +#[stable(feature = "proc_macro_lib", since = "1.15.0")] pub struct LexError { _inner: (), } @@ -131,6 +132,7 @@ pub mod __internal { } } +#[stable(feature = "proc_macro_lib", since = "1.15.0")] impl FromStr for TokenStream { type Err = LexError; @@ -154,6 +156,7 @@ impl FromStr for TokenStream { } } +#[stable(feature = "proc_macro_lib", since = "1.15.0")] impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for item in self.inner.iter() { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ace00f031859d..7a1256926657c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -714,8 +714,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, is_proc_macro_crate, is_test_crate, num_crate_types, - sess.diagnostic(), - &sess.features.borrow()) + sess.diagnostic()) }); } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 56f3cfc12c97f..25fa201a69468 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -21,7 +21,6 @@ #![feature(conservative_impl_trait)] #![feature(core_intrinsics)] #![feature(proc_macro_internals)] -#![feature(proc_macro_lib)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 19545e2e642b1..8abd3d252c8e4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -923,7 +923,6 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_allow_internal_unstable = allow_internal_unstable, fn enable_custom_derive = custom_derive, fn enable_pushpop_unsafe = pushpop_unsafe, - fn enable_proc_macro = proc_macro, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 77c53542dcbec..10d76692b1e4c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -279,9 +279,6 @@ declare_features! ( // instead of just the platforms on which it is the C ABI (active, abi_sysv64, "1.13.0", Some(36167)), - // Macros 1.1 - (active, proc_macro, "1.13.0", Some(35900)), - // Allows untagged unions `union U { ... }` (active, untagged_unions, "1.13.0", Some(32836)), @@ -364,6 +361,8 @@ declare_features! ( // Allows `..` in tuple (struct) patterns (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), (accepted, item_like_imports, "1.14.0", Some(35120)), + // Macros 1.1 + (accepted, proc_macro, "1.15.0", Some(35900)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -637,11 +636,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG is an experimental feature", cfg_fn!(fundamental))), - ("proc_macro_derive", Normal, Gated(Stability::Unstable, - "proc_macro", - "the `#[proc_macro_derive]` attribute \ - is an experimental feature", - cfg_fn!(proc_macro))), + ("proc_macro_derive", Normal, Ungated), ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", @@ -747,7 +742,6 @@ const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)), ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)), ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)), - ("proc_macro", "proc_macro", cfg_fn!(proc_macro)), ]; #[derive(Debug, Eq, PartialEq)] diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 535d7de19e341..ac4b07bbf2420 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -15,7 +15,7 @@ use syntax::attr::HasAttrs; use syntax::codemap; use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension}; use syntax::ext::build::AstBuilder; -use syntax::feature_gate::{self, emit_feature_err}; +use syntax::feature_gate; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -218,12 +218,6 @@ pub fn expand_derive(cx: &mut ExtCtxt, .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap())) .next(); if let Some((i, titem)) = macros_11_derive { - if !cx.ecfg.features.unwrap().proc_macro { - let issue = feature_gate::GateIssue::Language; - let msg = "custom derive macros are experimentally supported"; - emit_feature_err(cx.parse_sess, "proc_macro", titem.span, issue, msg); - } - let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); let path = ast::Path::from_ident(titem.span, tname); let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 66d6c0570ace7..74464ca5313b7 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -19,7 +19,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(not(stage0), deny(warnings))] -#![feature(proc_macro_lib)] #![feature(proc_macro_internals)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 5323ace79d849..c93e2c054d240 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -17,7 +17,6 @@ use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::ext::expand::ExpansionConfig; use syntax::parse::ParseSess; -use syntax::feature_gate::Features; use syntax::fold::Folder; use syntax::ptr::P; use syntax::symbol::Symbol; @@ -47,8 +46,7 @@ pub fn modify(sess: &ParseSess, is_proc_macro_crate: bool, is_test_crate: bool, num_crate_types: usize, - handler: &errors::Handler, - features: &Features) -> ast::Crate { + handler: &errors::Handler) -> ast::Crate { let ecfg = ExpansionConfig::default("proc_macro".to_string()); let mut cx = ExtCtxt::new(sess, ecfg, resolver); @@ -66,12 +64,6 @@ pub fn modify(sess: &ParseSess, if !is_proc_macro_crate { return krate - } else if !features.proc_macro { - let mut err = handler.struct_err("the `proc-macro` crate type is \ - experimental"); - err.help("add #![feature(proc_macro)] to the crate attributes to \ - enable"); - err.emit(); } if num_crate_types > 1 { diff --git a/src/test/compile-fail-fulldeps/proc-macro/attribute.rs b/src/test/compile-fail-fulldeps/proc-macro/attribute.rs index abf11637631f4..5d5e61270b61d 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attribute.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attribute.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-b.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-b.rs index 8a92ca74f376a..cd8750bc89c42 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-b.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a-b.rs @@ -11,7 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro, proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a.rs index 8d26207273d42..53b2c23e5d7df 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-a.rs @@ -11,8 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs index 70b778b1030e7..5787546fb1e5a 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -11,8 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-bad.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-bad.rs index aae8b63e25354..841b39eaed07b 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-bad.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-bad.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic // force-host -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-panic.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-panic.rs index f426fe5437671..3274f0324e1cb 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-panic.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-panic.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic // force-host -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable-2.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable-2.rs index d8952e3478b6c..2d492d341ebba 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable-2.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable-2.rs @@ -11,8 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable.rs index 1187b5102e23f..a7b5d1e3e54cf 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-unstable.rs @@ -11,8 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/define-two.rs b/src/test/compile-fail-fulldeps/proc-macro/define-two.rs index bdb3c09c4d723..87b32096d7b01 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/define-two.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/define-two.rs @@ -11,7 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs index 4cc6b9f984c94..0e4ac9fe1eaf5 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs @@ -10,8 +10,6 @@ // aux-build:derive-bad.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_bad; diff --git a/src/test/compile-fail-fulldeps/proc-macro/derive-still-gated.rs b/src/test/compile-fail-fulldeps/proc-macro/derive-still-gated.rs index eb0bb00be9175..f36236c53562d 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/derive-still-gated.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/derive-still-gated.rs @@ -10,7 +10,6 @@ // aux-build:derive-a.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs index 4f4ed90f8fca2..e4fcbb117a505 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs @@ -10,7 +10,6 @@ // aux-build:derive-unstable-2.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs index 84ac776a765a2..836e336fc22f0 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs @@ -10,7 +10,6 @@ // aux-build:derive-unstable.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/export-macro.rs b/src/test/compile-fail-fulldeps/proc-macro/export-macro.rs index 48b73e7333185..477039bd7a2fa 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/export-macro.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/export-macro.rs @@ -11,7 +11,6 @@ // error-pattern: cannot export macro_rules! macros from a `proc-macro` crate #![crate_type = "proc-macro"] -#![feature(proc_macro)] #[macro_export] macro_rules! foo { diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-1.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-1.rs deleted file mode 100644 index f5618fc6425e2..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-1.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -// error-pattern: the `proc-macro` crate type is experimental - -#![crate_type = "proc-macro"] diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-2.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-2.rs deleted file mode 100644 index 9c4053266f471..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -extern crate proc_macro; //~ ERROR: use of unstable library feature - -fn main() {} diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-3.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-3.rs deleted file mode 100644 index bb6b575962250..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -#![crate_type = "proc-macro"] - -#[proc_macro_derive(Foo)] //~ ERROR: is an experimental feature -pub fn foo() { -} diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-4.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-4.rs deleted file mode 100644 index 6a8fcdf4ab782..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-4.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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:derive-a.rs - -#[macro_use] -extern crate derive_a; - -#[derive(A)] //~ ERROR custom derive macros are experimentally supported -struct S; diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-5.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-5.rs deleted file mode 100644 index 672579ce8f14b..0000000000000 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-5.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -#[cfg(proc_macro)] //~ ERROR: experimental and subject to change -fn foo() {} diff --git a/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs index 70c8db5ddd2ec..f37980c5e0f54 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(proc_macro, proc_macro_lib)] - extern crate proc_macro; #[proc_macro_derive(Foo)] diff --git a/src/test/compile-fail-fulldeps/proc-macro/import.rs b/src/test/compile-fail-fulldeps/proc-macro/import.rs index 8f907183cc39b..fae2439344fb0 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/import.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/import.rs @@ -10,7 +10,6 @@ // aux-build:derive-a.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/issue-37788.rs b/src/test/compile-fail-fulldeps/proc-macro/issue-37788.rs index 6d1030026dba2..691c280580122 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/issue-37788.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/issue-37788.rs @@ -10,8 +10,6 @@ // aux-build:derive-a-b.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_a_b; diff --git a/src/test/compile-fail-fulldeps/proc-macro/item-error.rs b/src/test/compile-fail-fulldeps/proc-macro/item-error.rs index 2a68accf91f71..4133e75e3a62d 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/item-error.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/item-error.rs @@ -10,7 +10,6 @@ // aux-build:derive-b.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs index 39c27e82fa5b3..f9906b650fb87 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs @@ -10,8 +10,6 @@ // aux-build:derive-panic.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_panic; diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs index 651a277d4abd5..4ad1cf79d61c6 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs @@ -10,7 +10,6 @@ // aux-build:derive-b.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs b/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs index 2bf25892c44d2..238dde5160cd4 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/shadow-builtin.rs b/src/test/compile-fail-fulldeps/proc-macro/shadow-builtin.rs index 1bcd4b15eb863..8c5affb7b5ab3 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/shadow-builtin.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/shadow-builtin.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs index dc828fbf7d160..d76cf003ed14d 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/shadow.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/shadow.rs @@ -10,8 +10,6 @@ // aux-build:derive-a.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_a; #[macro_use] diff --git a/src/test/compile-fail-fulldeps/proc-macro/signature.rs b/src/test/compile-fail-fulldeps/proc-macro/signature.rs index b7df9489dff30..6d6b5a23e941f 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/signature.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/signature.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] #![allow(warnings)] extern crate proc_macro; diff --git a/src/test/run-make/issue-37839/a.rs b/src/test/run-make/issue-37839/a.rs index 3dff45388c75b..052317438c2f7 100644 --- a/src/test/run-make/issue-37839/a.rs +++ b/src/test/run-make/issue-37839/a.rs @@ -8,6 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(proc_macro)] #![allow(unused)] #![crate_type = "proc-macro"] diff --git a/src/test/run-make/issue-37893/a.rs b/src/test/run-make/issue-37893/a.rs index 3dff45388c75b..052317438c2f7 100644 --- a/src/test/run-make/issue-37893/a.rs +++ b/src/test/run-make/issue-37893/a.rs @@ -8,6 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(proc_macro)] #![allow(unused)] #![crate_type = "proc-macro"] diff --git a/src/test/run-make/issue-38237/foo.rs b/src/test/run-make/issue-38237/foo.rs index c291ffbf4e856..6fb315731de17 100644 --- a/src/test/run-make/issue-38237/foo.rs +++ b/src/test/run-make/issue-38237/foo.rs @@ -9,7 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-make/rustc-macro-dep-files/bar.rs b/src/test/run-make/rustc-macro-dep-files/bar.rs index a2db98049d287..03330c3d1700d 100644 --- a/src/test/run-make/rustc-macro-dep-files/bar.rs +++ b/src/test/run-make/rustc-macro-dep-files/bar.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(proc_macro)] - #[macro_use] extern crate foo; diff --git a/src/test/run-make/rustc-macro-dep-files/foo.rs b/src/test/run-make/rustc-macro-dep-files/foo.rs index bd9e9158c5052..2f2524f6ef115 100644 --- a/src/test/run-make/rustc-macro-dep-files/foo.rs +++ b/src/test/run-make/rustc-macro-dep-files/foo.rs @@ -9,8 +9,6 @@ // except according to those terms. #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/add-impl.rs b/src/test/run-pass-fulldeps/proc-macro/add-impl.rs index e82282f3d8c58..7ea7ceafc2876 100644 --- a/src/test/run-pass-fulldeps/proc-macro/add-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/add-impl.rs @@ -10,8 +10,6 @@ // aux-build:add-impl.rs -#![feature(proc_macro)] - #[macro_use] extern crate add_impl; diff --git a/src/test/run-pass-fulldeps/proc-macro/append-impl.rs b/src/test/run-pass-fulldeps/proc-macro/append-impl.rs index f062111df9daf..591f3331d28c0 100644 --- a/src/test/run-pass-fulldeps/proc-macro/append-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/append-impl.rs @@ -10,7 +10,6 @@ // aux-build:append-impl.rs -#![feature(proc_macro)] #![allow(warnings)] #[macro_use] diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs index 1d34049db249f..3959eccd81e35 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs index 7260bc4a5e7bb..fdce709e5bad6 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs @@ -11,8 +11,6 @@ // force-host // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs index eaada5542274c..a253c6224aa68 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs index a942adc4c8020..713fb7d10f2fd 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs index a02b798c8023e..c18cda895325b 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-ctod.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-ctod.rs index 50f1a390b2939..19caafd17b5f3 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-ctod.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-ctod.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs index a9257cb4c8b78..cfe428bf5f323 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs index 05a6cbec69c5a..fae2d27ab6b75 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs @@ -10,7 +10,7 @@ // ignore-test -#![feature(macro_reexport, proc_macro)] +#![feature(macro_reexport)] #[macro_reexport(A)] extern crate derive_a; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs index bc8a0d575913b..a2c25ae50e8ec 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs @@ -11,9 +11,6 @@ // no-prefer-dynamic // compile-flags:--crate-type proc-macro -#![feature(proc_macro)] -#![feature(proc_macro_lib)] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs index 969ed91f595e6..f4404b737f952 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs index 50eaf035962f1..e6831b6bfdf65 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs @@ -11,8 +11,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![deny(warnings)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs index d19b49ab18c07..ba1417ecb56e4 100644 --- a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs +++ b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs @@ -10,7 +10,6 @@ // aux-build:double.rs -#![feature(proc_macro)] #![allow(unused)] #[macro_use] diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs index f5bb93f012490..f1e1626ddf8ca 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs @@ -11,8 +11,6 @@ // aux-build:derive-b.rs // ignore-stage1 -#![feature(proc_macro)] - #[macro_use] extern crate derive_b; diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs index 608f86bca5768..ce3ba60b0ecf4 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs @@ -10,8 +10,6 @@ // aux-build:derive-same-struct.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_same_struct; diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-test.rs b/src/test/run-pass-fulldeps/proc-macro/derive-test.rs index 2f44515a873de..a07e8b6cd7e64 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-test.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-test.rs @@ -12,8 +12,6 @@ // compile-flags: --test #![crate_type = "proc-macro"] -#![feature(proc_macro)] -#![feature(proc_macro, proc_macro_lib)] extern crate proc_macro; diff --git a/src/test/run-pass-fulldeps/proc-macro/expand-with-a-macro.rs b/src/test/run-pass-fulldeps/proc-macro/expand-with-a-macro.rs index 16f3535adae3b..4ccd4615fb609 100644 --- a/src/test/run-pass-fulldeps/proc-macro/expand-with-a-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/expand-with-a-macro.rs @@ -11,7 +11,6 @@ // aux-build:expand-with-a-macro.rs // ignore-stage1 -#![feature(proc_macro)] #![deny(warnings)] #[macro_use] diff --git a/src/test/run-pass-fulldeps/proc-macro/load-two.rs b/src/test/run-pass-fulldeps/proc-macro/load-two.rs index 431c8c5902749..d15a83a2cbe43 100644 --- a/src/test/run-pass-fulldeps/proc-macro/load-two.rs +++ b/src/test/run-pass-fulldeps/proc-macro/load-two.rs @@ -11,8 +11,6 @@ // aux-build:derive-atob.rs // aux-build:derive-ctod.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_atob; #[macro_use] diff --git a/src/test/run-pass-fulldeps/proc-macro/smoke.rs b/src/test/run-pass-fulldeps/proc-macro/smoke.rs index cd7edb726447b..54d651df1f9af 100644 --- a/src/test/run-pass-fulldeps/proc-macro/smoke.rs +++ b/src/test/run-pass-fulldeps/proc-macro/smoke.rs @@ -11,8 +11,6 @@ // aux-build:derive-a.rs // ignore-stage1 -#![feature(proc_macro)] - #[macro_use] extern crate derive_a; diff --git a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs index 818308b05a44e..c9056e08d4426 100644 --- a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs @@ -11,8 +11,6 @@ // aux-build:derive-nothing.rs // ignore-stage1 -#![feature(proc_macro)] - #[macro_use] extern crate derive_nothing; diff --git a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs b/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs index 7f09d8faebbb5..f0a1bfe652857 100644 --- a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs +++ b/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs @@ -11,8 +11,6 @@ // aux-build:derive-a.rs // aux-build:derive-reexport.rs -#![feature(proc_macro)] - #[macro_use] extern crate derive_reexport; diff --git a/src/test/rustdoc/rustc-macro-crate.rs b/src/test/rustdoc/rustc-macro-crate.rs index fe80a90955045..dc28732b55ee2 100644 --- a/src/test/rustdoc/rustc-macro-crate.rs +++ b/src/test/rustdoc/rustc-macro-crate.rs @@ -10,8 +10,6 @@ // no-prefer-dynamic -#![feature(proc_macro)] -#![feature(proc_macro_lib)] #![crate_type = "proc-macro"] extern crate proc_macro; From 2cb7a60ef6bdc38c8ca9dcf26c170c46d67e1b1d Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sun, 1 Jan 2017 20:33:37 -0500 Subject: [PATCH 18/18] Document custom derive. These are some bare-bones documentation for custom derive, needed to stabilize "macros 1.1", https://github.com/rust-lang/rust/issues/35900 The book chapter is based off of a blog post by @cbreeden, https://cbreeden.github.io/Macros11/ Normally, we have a policy of not mentioning external crates in documentation. However, given that syn/quote are basically neccesary for properly using macros 1.1, I feel that not including them here would make the documentation very bad. So the rules should be bent in this instance. --- src/doc/book/SUMMARY.md | 1 + src/doc/book/procedural-macros.md | 213 ++++++++++++++++++++++++++++++ src/doc/reference.md | 50 +++++-- src/libproc_macro/lib.rs | 6 +- 4 files changed, 258 insertions(+), 12 deletions(-) create mode 100644 src/doc/book/procedural-macros.md diff --git a/src/doc/book/SUMMARY.md b/src/doc/book/SUMMARY.md index 18aa9f24580d5..babbafa078f4a 100644 --- a/src/doc/book/SUMMARY.md +++ b/src/doc/book/SUMMARY.md @@ -52,6 +52,7 @@ * [Borrow and AsRef](borrow-and-asref.md) * [Release Channels](release-channels.md) * [Using Rust without the standard library](using-rust-without-the-standard-library.md) + * [Procedural Macros (and custom derive)](procedural-macros.md) * [Nightly Rust](nightly-rust.md) * [Compiler Plugins](compiler-plugins.md) * [Inline Assembly](inline-assembly.md) diff --git a/src/doc/book/procedural-macros.md b/src/doc/book/procedural-macros.md new file mode 100644 index 0000000000000..37d3d20c06d96 --- /dev/null +++ b/src/doc/book/procedural-macros.md @@ -0,0 +1,213 @@ +% Procedural Macros (and custom Derive) + +As you've seen throughout the rest of the book, Rust provides a mechanism +called "derive" that lets you implement traits easily. For example, + +```rust +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +``` + +is a lot simpler than + +```rust +struct Point { + x: i32, + y: i32, +} + +use std::fmt; + +impl fmt::Debug for Point { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y) + } +} +``` + +Rust includes several traits that you can derive, but it also lets you define +your own. We can accomplish this task through a feature of Rust called +"procedural macros." Eventually, procedural macros will allow for all sorts of +advanced metaprogramming in Rust, but today, they're only for custom derive. + +Let's build a very simple trait, and derive it with custom derive. + +## Hello World + +So the first thing we need to do is start a new crate for our project. + +```bash +$ cargo new --bin hello-world +``` + +All we want is to be able to call `hello_world()` on a derived type. Something +like this: + +```rust,ignore +#[derive(HelloWorld)] +struct Pancakes; + +fn main() { + Pancakes::hello_world(); +} +``` + +With some kind of nice output, like `Hello, World! My name is Pancakes.`. + +Let's go ahead and write up what we think our macro will look like from a user +perspective. In `src/main.rs` we write: + +```rust,ignore +#[macro_use] +extern crate hello_world_derive; + +trait HelloWorld { + fn hello_world(); +} + +#[derive(HelloWorld)] +struct FrenchToast; + +#[derive(HelloWorld)] +struct Waffles; + +fn main() { + FrenchToast::hello_world(); + Waffles::hello_world(); +} +``` + +Great. So now we just need to actually write the procedural macro. At the +moment, procedural macros need to be in their own crate. Eventually, this +restriction may be lifted, but for now, it's required. As such, there's a +convention; for a crate named `foo`, a custom derive procedural macro is called +`foo-derive`. Let's start a new crate called `hello-world-derive` inside our +`hello-world` project. + +```bash +$ cargo new hello-world-derive +``` + +To make sure that our `hello-world` crate is able to find this new crate we've +created, we'll add it to our toml: + +```toml +[dependencies] +hello-world-derive = { path = "hello-world-derive" } +``` + +As for our the source of our `hello-world-derive` crate, here's an example: + +```rust,ignore +extern crate proc_macro; +extern crate syn; +#[macro_use] +extern crate quote; + +use proc_macro::TokenStream; + +#[proc_macro_derive(HelloWorld)] +pub fn hello_world(input: TokenStream) -> TokenStream { + // Construct a string representation of the type definition + let s = input.to_string(); + + // Parse the string representation + let ast = syn::parse_macro_input(&s).unwrap(); + + // Build the impl + let gen = impl_hello_world(&ast); + + // Return the generated impl + gen.parse().unwrap() +} +``` + +So there is a lot going on here. We have introduced two new crates: [`syn`] and +[`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted +to a `String`. This `String` is a string representation of the Rust code for which +we are deriving `HelloWorld` for. At the moment, the only thing you can do with a +`TokenStream` is convert it to a string. A richer API will exist in the future. + +So what we really need is to be able to _parse_ Rust code into something +usable. This is where `syn` comes to play. `syn` is a crate for parsing Rust +code. The other crate we've introduced is `quote`. It's essentially the dual of +`syn` as it will make generating Rust code really easy. We could write this +stuff on our own, but it's much simpler to use these libraries. Writing a full +parser for Rust code is no simple task. + +[`syn`]: https://crates.io/crates/syn +[`quote`]: https://crates.io/crates/quote + +The comments seem to give us a pretty good idea of our overall strategy. We +are going to take a `String` of the Rust code for the type we are deriving, parse +it using `syn`, construct the implementation of `hello_world` (using `quote`), +then pass it back to Rust compiler. + +One last note: you'll see some `unwrap()`s there. If you want to provide an +error for a procedural macro, then you should `panic!` with the error message. +In this case, we're keeping it as simple as possible. + +Great, so let's write `impl_hello_world(&ast)`. + +```rust,ignore +fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens { + let name = &ast.ident; + quote! { + impl HelloWorld for #name { + fn hello_world() { + println!("Hello, World! My name is {}", stringify!(#name)); + } + } + } +} +``` + +So this is where quotes comes in. The `ast` argument is a struct that gives us +a representation of our type (which can be either a `struct` or an `enum`). +Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html), +there is some useful information there. We are able to get the name of the +type using `ast.ident`. The `quote!` macro let's us write up the Rust code +that we wish to return and convert it into `Tokens`. `quote!` let's us use some +really cool templating mechanics; we simply write `#name` and `quote!` will +replace it with the variable named `name`. You can even do some repetition +similar to regular macros work. You should check out the +[docs](https://docs.rs/quote) for a good introduction. + +So I think that's it. Oh, well, we do need to add dependencies for `syn` and +`quote` in the `cargo.toml` for `hello-world-derive`. + +```toml +[dependencies] +syn = "0.10.5" +quote = "0.3.10" +``` + +That should be it. Let's try to compile `hello-world`. + +```bash +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> hello-world-derive/src/lib.rs:8:3 + | +8 | #[proc_macro_derive(HelloWorld)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +``` + +Oh, so it appears that we need to declare that our `hello-world-derive` crate is +a `proc-macro` crate type. How do we do this? Like this: + +```toml +[lib] +proc-macro = true +``` + +Ok so now, let's compile `hello-world`. Executing `cargo run` now yields: + +```bash +Hello, World! My name is FrenchToast +Hello, World! My name is Waffles +``` + +We've done it! diff --git a/src/doc/reference.md b/src/doc/reference.md index bf286aaec4bb3..e7cfe4bb2eeb5 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -555,26 +555,24 @@ mod a { # fn main() {} ``` -# Syntax extensions +# Macros A number of minor features of Rust are not central enough to have their own syntax, and yet are not implementable as functions. Instead, they are given names, and invoked through a consistent syntax: `some_extension!(...)`. -Users of `rustc` can define new syntax extensions in two ways: - -* [Compiler plugins][plugin] can include arbitrary Rust code that - manipulates syntax trees at compile time. Note that the interface - for compiler plugins is considered highly unstable. +Users of `rustc` can define new macros in two ways: * [Macros](book/macros.html) define new syntax in a higher-level, declarative way. +* [Procedural Macros][procedural macros] can be used to implement custom derive. + +And one unstable way: [compiler plugins][plugin]. ## Macros `macro_rules` allows users to define syntax extension in a declarative way. We -call such extensions "macros by example" or simply "macros" — to be distinguished -from the "procedural macros" defined in [compiler plugins][plugin]. +call such extensions "macros by example" or simply "macros". Currently, macros can expand to expressions, statements, items, or patterns. @@ -652,6 +650,28 @@ Rust syntax is restricted in two ways: [RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md +## Procedrual Macros + +"Procedrual macros" are the second way to implement a macro. For now, the only +thing they can be used for is to implement derive on your own types. See +[the book][procedural macros] for a tutorial. + +Procedural macros involve a few different parts of the language and its +standard libraries. First is the `proc_macro` crate, included with Rust, +that defines an interface for building a procedrual macro. The +`#[proc_macro_derive(Foo)]` attribute is used to mark the the deriving +function. This function must have the type signature: + +```rust,ignore +use proc_macro::TokenStream; + +#[proc_macro_derive(Hello)] +pub fn hello_world(input: TokenStream) -> TokenStream +``` + +Finally, procedural macros must be in their own crate, with the `proc-macro` +crate type. + # Crates and source files Although Rust, like any other language, can be implemented by an interpreter as @@ -2309,6 +2329,9 @@ impl PartialEq for Foo { } ``` +You can implement `derive` for your own type through [procedural +macros](#procedural-macros). + ### Compiler Features Certain aspects of Rust may be implemented in the compiler, but they're not @@ -4112,6 +4135,16 @@ be ignored in favor of only building the artifacts specified by command line. in dynamic libraries. This form of output is used to produce statically linked executables as well as `staticlib` outputs. +* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output + produced is not specified, but if a `-L` path is provided to it then the + compiler will recognize the output artifacts as a macro and it can be loaded + for a program. If a crate is compiled with the `proc-macro` crate type it + will forbid exporting any items in the crate other than those functions + tagged `#[proc_macro_derive]` and those functions must also be placed at the + crate root. Finally, the compiler will automatically set the + `cfg(proc_macro)` annotation whenever any crate type of a compilation is the + `proc-macro` crate type. + Note that these outputs are stackable in the sense that if multiple are specified, then the compiler will produce each form of output at once without having to recompile. However, this only applies for outputs specified by the @@ -4289,3 +4322,4 @@ that have since been removed): [ffi]: book/ffi.html [plugin]: book/compiler-plugins.html +[procedural macros]: book/procedural-macros.html diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 1491bdc6c8d31..22b365fa64f0e 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -15,15 +15,13 @@ //! Currently the primary use of this crate is to provide the ability to define //! new custom derive modes through `#[proc_macro_derive]`. //! -//! Added recently as part of [RFC 1681] this crate is stable as of Rust 1.15.0. -//! -//! [RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md -//! //! Note that this crate is intentionally very bare-bones currently. The main //! type, `TokenStream`, only supports `fmt::Display` and `FromStr` //! implementations, indicating that it can only go to and come from a string. //! This functionality is intended to be expanded over time as more surface //! area for macro authors is stabilized. +//! +//! See [the book](../../book/procedural-macros.html) for more. #![crate_name = "proc_macro"] #![stable(feature = "proc_macro_lib", since = "1.15.0")]