From d3c212c5527f901fcb44d59d031695248762c340 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 3 Feb 2019 12:55:00 +0100 Subject: [PATCH 01/13] Require a list of features to allow in `allow_internal_unstable` --- src/liballoc/macros.rs | 3 +- src/libcore/macros.rs | 6 ++- src/librustc/hir/lowering.rs | 37 +++++++++++++++---- src/librustc/middle/stability.rs | 9 ++--- src/librustc_allocator/expand.rs | 4 +- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 4 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_plugin/registry.rs | 6 +-- src/libstd/macros.rs | 18 ++++++--- src/libstd/thread/local.rs | 8 +++- src/libsyntax/ext/base.rs | 20 ++++++---- src/libsyntax/ext/derive.rs | 5 ++- src/libsyntax/ext/expand.rs | 27 ++++++++------ src/libsyntax/ext/source_util.rs | 2 +- src/libsyntax/ext/tt/macro_rules.rs | 13 ++++++- src/libsyntax/feature_gate.rs | 24 ++++++------ src/libsyntax/std_inject.rs | 4 +- src/libsyntax/test.rs | 6 ++- src/libsyntax_ext/deriving/mod.rs | 8 +++- src/libsyntax_ext/format.rs | 2 +- src/libsyntax_ext/lib.rs | 10 +++-- src/libsyntax_ext/proc_macro_decls.rs | 5 ++- src/libsyntax_ext/test.rs | 5 ++- src/libsyntax_ext/test_case.rs | 5 ++- src/libsyntax_pos/hygiene.rs | 6 +-- src/libsyntax_pos/lib.rs | 4 +- ...te-allow-internal-unstable-nested-macro.rs | 2 +- ...llow-internal-unstable-nested-macro.stderr | 4 +- ...ure-gate-allow-internal-unstable-struct.rs | 2 +- ...gate-allow-internal-unstable-struct.stderr | 4 +- .../feature-gate-allow-internal-unstable.rs | 2 +- ...eature-gate-allow-internal-unstable.stderr | 4 +- .../internal/auxiliary/internal_unstable.rs | 10 ++--- src/test/ui/internal/internal-unstable.rs | 2 +- 35 files changed, 182 insertions(+), 93 deletions(-) diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index db91b07fa71b4..7ae57a8dc7984 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -34,7 +34,8 @@ #[cfg(not(test))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(not(stage0), allow_internal_unstable(box_syntax))] +#[cfg_attr(stage0, allow_internal_unstable)] macro_rules! vec { ($elem:expr; $n:expr) => ( $crate::vec::from_elem($elem, $n) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 664490c1997ef..6b5fe84ff61df 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1,6 +1,7 @@ /// Entry point of thread panic, for details, see std::macros #[macro_export] -#[allow_internal_unstable] +#[cfg_attr(not(stage0), allow_internal_unstable(core_panic, __rust_unstable_column))] +#[cfg_attr(stage0, allow_internal_unstable)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( @@ -409,7 +410,8 @@ macro_rules! write { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(format_args_nl))] macro_rules! writeln { ($dst:expr) => ( write!($dst, "\n") diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 3de41b1665d6d..b01362b0ed4b3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -681,13 +681,18 @@ impl<'a> LoweringContext<'a> { Ident::with_empty_ctxt(Symbol::gensym(s)) } - fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) -> Span { + fn allow_internal_unstable( + &self, + reason: CompilerDesugaringKind, + span: Span, + allow_internal_unstable: Vec, + ) -> Span { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(source_map::ExpnInfo { call_site: span, def_site: Some(span), format: source_map::CompilerDesugaring(reason), - allow_internal_unstable: true, + allow_internal_unstable, allow_internal_unsafe: false, local_inner_macros: false, edition: source_map::hygiene::default_edition(), @@ -964,7 +969,13 @@ impl<'a> LoweringContext<'a> { attrs: ThinVec::new(), }; - let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span); + let unstable_span = self.allow_internal_unstable( + CompilerDesugaringKind::Async, + span, + vec![ + Symbol::intern("gen_future"), + ], + ); let gen_future = self.expr_std_path( unstable_span, &["future", "from_generator"], None, ThinVec::new()); hir::ExprKind::Call(P(gen_future), hir_vec![generator]) @@ -1363,6 +1374,7 @@ impl<'a> LoweringContext<'a> { let exist_ty_span = self.allow_internal_unstable( CompilerDesugaringKind::ExistentialReturnType, span, + Vec::new(), // doesn'c actually allow anything unstable ); let exist_ty_def_index = self @@ -3927,8 +3939,13 @@ impl<'a> LoweringContext<'a> { }), ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { - let unstable_span = - this.allow_internal_unstable(CompilerDesugaringKind::TryBlock, body.span); + let unstable_span = this.allow_internal_unstable( + CompilerDesugaringKind::TryBlock, + body.span, + vec![ + Symbol::intern("try_trait"), + ], + ); let mut block = this.lower_block(body, true).into_inner(); let tail = block.expr.take().map_or_else( || { @@ -4363,6 +4380,7 @@ impl<'a> LoweringContext<'a> { let desugared_span = self.allow_internal_unstable( CompilerDesugaringKind::ForLoop, head_sp, + Vec::new(), ); let iter = self.str_to_ident("iter"); @@ -4525,8 +4543,13 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = - self.allow_internal_unstable(CompilerDesugaringKind::QuestionMark, e.span); + let unstable_span = self.allow_internal_unstable( + CompilerDesugaringKind::QuestionMark, + e.span, + vec![ + Symbol::intern("try_trait") + ], + ); // `Try::into_result()` let discr = { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 34c77d08f5a7e..5d606abb3cd79 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -561,11 +561,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to /// `id`. pub fn eval_stability(self, def_id: DefId, id: Option, span: Span) -> EvalResult { - if span.allows_unstable() { - debug!("stability: skipping span={:?} since it is internal", span); - return EvalResult::Allow; - } - let lint_deprecated = |def_id: DefId, id: NodeId, note: Option, @@ -694,6 +689,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match stability { Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => { + if span.allows_unstable(&feature.as_str()) { + debug!("stability: skipping span={:?} since it is internal", span); + return EvalResult::Allow; + } if self.stability().active_features.contains(&feature) { return EvalResult::Allow; } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index d302e7646d168..b877c80af1aba 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -91,7 +91,9 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { call_site: item.span, // use the call site of the static def_site: None, format: MacroAttribute(Symbol::intern(name)), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("rustc_attrs"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 0b4c8a5367c15..9fca1a983c30d 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -570,7 +570,7 @@ impl<'a> CrateLoader<'a> { ProcMacro::Bang { name, client } => { (name, SyntaxExtension::ProcMacro { expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), edition: root.edition, }) } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index b248c6bf6565a..f7c7c627959a7 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -425,7 +425,9 @@ impl cstore::CStore { let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); let ext = SyntaxExtension::ProcMacro { expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("proc_macro_def_site"), + ], edition: data.root.edition, }; return LoadedMacro::ProcMacro(Lrc::new(ext)); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 76b8b83031a0a..d1b005ffb858a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -907,7 +907,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Check `#[unstable]` const fns or `#[rustc_const_unstable]` // functions without the feature gate active in this crate in // order to report a better error message than the one below. - if self.span.allows_unstable() { + if self.span.allows_unstable(&feature.as_str()) { // `allow_internal_unstable` can make such calls stable. is_const_fn = true; } else { diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index b53d956a9c032..14312f0b2f705 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -110,8 +110,8 @@ impl<'a> Registry<'a> { edition, } } - IdentTT(ext, _, allow_internal_unstable) => { - IdentTT(ext, Some(self.krate_span), allow_internal_unstable) + IdentTT { ext, span: _, allow_internal_unstable } => { + IdentTT { ext, span: Some(self.krate_span), allow_internal_unstable } } _ => extension, })); @@ -126,7 +126,7 @@ impl<'a> Registry<'a> { self.register_syntax_extension(Symbol::intern(name), NormalTT { expander: Box::new(expander), def_info: None, - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b87257188df10..506b6d4e8e0a8 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -53,7 +53,8 @@ /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(__rust_unstable_column, libstd_sys_internals))] macro_rules! panic { () => ({ panic!("explicit panic") @@ -111,7 +112,8 @@ macro_rules! panic { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(print_internals))] macro_rules! print { ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } @@ -143,7 +145,8 @@ macro_rules! print { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(print_internals, format_args_nl))] macro_rules! println { () => (print!("\n")); ($($arg:tt)*) => ({ @@ -174,7 +177,8 @@ macro_rules! println { /// ``` #[macro_export] #[stable(feature = "eprint", since = "1.19.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(print_internals))] macro_rules! eprint { ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); } @@ -202,7 +206,8 @@ macro_rules! eprint { /// ``` #[macro_export] #[stable(feature = "eprint", since = "1.19.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(print_internals, format_args_nl))] macro_rules! eprintln { () => (eprint!("\n")); ($($arg:tt)*) => ({ @@ -325,7 +330,8 @@ macro_rules! dbg { /// A macro to await on an async call. #[macro_export] #[unstable(feature = "await_macro", issue = "50547")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(gen_future, generators))] #[allow_internal_unsafe] macro_rules! await { ($e:expr) => { { diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 5d2eb5f8e7320..8207709e1f9f0 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -126,7 +126,8 @@ impl fmt::Debug for LocalKey { /// [`std::thread::LocalKey`]: ../std/thread/struct.LocalKey.html #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(thread_local_internals))] macro_rules! thread_local { // empty (base case for the recursion) () => {}; @@ -148,7 +149,10 @@ macro_rules! thread_local { reason = "should not be necessary", issue = "0")] #[macro_export] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable( + thread_local_internals, cfg_target_thread_local, thread_local, +))] #[allow_internal_unsafe] macro_rules! __thread_local_inner { (@key $(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 465b53184dcd7..02d6d7218733c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -621,7 +621,8 @@ pub enum SyntaxExtension { /// A function-like procedural macro. TokenStream -> TokenStream. ProcMacro { expander: Box, - allow_internal_unstable: bool, + /// Whitelist of unstable features that are treated as stable inside this macro + allow_internal_unstable: Vec, edition: Edition, }, @@ -638,8 +639,10 @@ pub enum SyntaxExtension { expander: Box, def_info: Option<(ast::NodeId, Span)>, /// Whether the contents of the macro can - /// directly use `#[unstable]` things (true == yes). - allow_internal_unstable: bool, + /// directly use `#[unstable]` things. + /// + /// Only allows things that require a feature gate in the given whitelist + allow_internal_unstable: Vec, /// Whether the contents of the macro can use `unsafe` /// without triggering the `unsafe_code` lint. allow_internal_unsafe: bool, @@ -654,8 +657,11 @@ pub enum SyntaxExtension { /// A function-like syntax extension that has an extra ident before /// the block. - /// - IdentTT(Box, Option, bool), + IdentTT { + ext: Box, + span: Option, + allow_internal_unstable: Vec, + }, /// An attribute-like procedural macro. TokenStream -> TokenStream. /// The input is the annotated item. @@ -682,7 +688,7 @@ impl SyntaxExtension { match *self { SyntaxExtension::DeclMacro { .. } | SyntaxExtension::NormalTT { .. } | - SyntaxExtension::IdentTT(..) | + SyntaxExtension::IdentTT { .. } | SyntaxExtension::ProcMacro { .. } => MacroKind::Bang, SyntaxExtension::NonMacroAttr { .. } | @@ -716,7 +722,7 @@ impl SyntaxExtension { SyntaxExtension::ProcMacroDerive(.., edition) => edition, // Unstable legacy stuff SyntaxExtension::NonMacroAttr { .. } | - SyntaxExtension::IdentTT(..) | + SyntaxExtension::IdentTT { .. } | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | SyntaxExtension::BuiltinDerive(..) => hygiene::default_edition(), diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 50cec9e7908c1..03d68f4257f1b 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -58,7 +58,10 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P call_site: span, def_site: None, format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("structural_match"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 89d59478a5df1..65500cd23bd7e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -558,7 +558,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: attr.span, def_site: None, format: MacroAttribute(Symbol::intern(&attr.path.to_string())), - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -725,7 +725,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // don't stability-check macros in the same crate // (the only time this is null is for syntax extensions registered as macros) if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span)) - && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| { + && !span.allows_unstable(&feature.as_str()) + && this.cx.ecfg.features.map_or(true, |feats| { // macro features will count as lib features !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature) }) { @@ -757,7 +758,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let opt_expanded = match *ext { DeclMacro { ref expander, def_info, edition, .. } => { if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - false, false, false, None, + Vec::new(), false, false, None, edition) { dummy_span } else { @@ -768,14 +769,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { NormalTT { ref expander, def_info, - allow_internal_unstable, + ref allow_internal_unstable, allow_internal_unsafe, local_inner_macros, unstable_feature, edition, } => { if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - allow_internal_unstable, + allow_internal_unstable.clone(), allow_internal_unsafe, local_inner_macros, unstable_feature, @@ -791,7 +792,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - IdentTT(ref expander, tt_span, allow_internal_unstable) => { + IdentTT { ext: ref expander, span: tt_span, ref allow_internal_unstable } => { if ident.name == keywords::Invalid.name() { self.cx.span_err(path.span, &format!("macro {}! expects an ident argument", path)); @@ -802,7 +803,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: span, def_site: tt_span, format: macro_bang_format(path), - allow_internal_unstable, + allow_internal_unstable: allow_internal_unstable.clone(), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), @@ -827,7 +828,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } - SyntaxExtension::ProcMacro { ref expander, allow_internal_unstable, edition } => { + SyntaxExtension::ProcMacro { ref expander, ref allow_internal_unstable, edition } => { if ident.name != keywords::Invalid.name() { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); @@ -843,7 +844,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { def_site: None, format: macro_bang_format(path), // FIXME probably want to follow macro_rules macros here. - allow_internal_unstable, + allow_internal_unstable: allow_internal_unstable.clone(), allow_internal_unsafe: false, local_inner_macros: false, edition, @@ -918,7 +919,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: span, def_site: None, format: MacroAttribute(pretty_name), - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -937,7 +938,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(invoc.fragment_kind.expect_from_annotatables(items)) } BuiltinDerive(func) => { - expn_info.allow_internal_unstable = true; + expn_info.allow_internal_unstable = vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("derive_clone_copy"), + Symbol::intern("derive_eq"), + ]; invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let mut items = Vec::new(); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 31a134b856d82..549de1628eb55 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -44,7 +44,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTr /* __rust_unstable_column!(): expands to the current column number */ pub fn expand_column_gated(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) -> Box { - if sp.allows_unstable() { + if sp.allows_unstable("__rust_unstable_column") { expand_column(cx, sp, tts) } else { cx.span_fatal(sp, "the __rust_unstable_column macro is unstable"); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 33ea675f9d1bb..4409bf13b6c7b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -376,7 +376,18 @@ pub fn compile( }); if body.legacy { - let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable"); + let allow_internal_unstable = attr::find_by_name(&def.attrs, "allow_internal_unstable") + .map_or(Vec::new(), |attr| attr + .meta_item_list() + .unwrap_or_else(|| sess.span_diagnostic.span_bug( + attr.span, "allow_internal_unstable expects list of feature names", + )) + .iter() + .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( + it.span, "allow internal unstable expects feature names", + ))) + .collect() + ); let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); let mut local_inner_macros = false; if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0853b4399d2c1..1e1b315824f1e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1091,7 +1091,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu stable", cfg_fn!(profiler_runtime))), - ("allow_internal_unstable", Normal, template!(Word), Gated(Stability::Unstable, + ("allow_internal_unstable", Normal, template!(List: "feat1, feat2"), Gated(Stability::Unstable, "allow_internal_unstable", EXPLAIN_ALLOW_INTERNAL_UNSTABLE, cfg_fn!(allow_internal_unstable))), @@ -1199,7 +1199,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu ("proc_macro", Normal, template!(Word), Ungated), ("rustc_proc_macro_decls", Normal, template!(Word), Gated(Stability::Unstable, - "rustc_proc_macro_decls", + "rustc_attrs", "used internally by rustc", cfg_fn!(rustc_attrs))), @@ -1284,7 +1284,7 @@ impl GatedCfg { pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { let (cfg, feature, has_feature) = GATED_CFGS[self.index]; - if !has_feature(features) && !self.span.allows_unstable() { + if !has_feature(features) && !self.span.allows_unstable(feature) { let explain = format!("`cfg({})` is experimental and subject to change", cfg); emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); } @@ -1303,7 +1303,7 @@ macro_rules! gate_feature_fn { name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); let has_feature: bool = has_feature(&$cx.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); - if !has_feature && !span.allows_unstable() { + if !has_feature && !span.allows_unstable($name) { leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) .emit(); } @@ -1328,7 +1328,11 @@ impl<'a> Context<'a> { for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES { if name == n { if let Gated(_, name, desc, ref has_feature) = *gateage { - gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard); + if !attr.span.allows_unstable(name) { + gate_feature_fn!( + self, has_feature, attr.span, name, desc, GateStrength::Hard + ); + } } else if name == "doc" { if let Some(content) = attr.meta_item_list() { if content.iter().any(|c| c.check_name("include")) { @@ -1493,13 +1497,13 @@ struct PostExpansionVisitor<'a> { macro_rules! gate_feature_post { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable() { + if !span.allows_unstable(stringify!($feature)) { gate_feature!(cx.context, $feature, span, $explain) } }}; ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable() { + if !span.allows_unstable(stringify!($feature)) { gate_feature!(cx.context, $feature, span, $explain, $level) } }} @@ -1610,10 +1614,8 @@ impl<'a> PostExpansionVisitor<'a> { impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_attribute(&mut self, attr: &ast::Attribute) { - if !attr.span.allows_unstable() { - // check for gated attributes - self.context.check_attribute(attr, false); - } + // check for gated attributes + self.context.check_attribute(attr, false); if attr.check_name("doc") { if let Some(content) = attr.meta_item_list() { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 5b904fa86ad09..91ec42a33b5f6 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,7 +20,9 @@ fn ignored_span(sp: Span) -> Span { call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("prelude_import"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 703c4f2db347b..aa107130eee2b 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -285,7 +285,11 @@ fn generate_test_harness(sess: &ParseSess, call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test_case")), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("main"), + Symbol::intern("test"), + Symbol::intern("rustc_attrs"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 2c8a996cdb0cb..bc86ffa852bbe 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -136,11 +136,15 @@ fn call_intrinsic(cx: &ExtCtxt<'_>, intrinsic: &str, args: Vec>) -> P { - if cx.current_expansion.mark.expn_info().unwrap().allow_internal_unstable { + let intrinsic_allowed_via_allow_internal_unstable = cx + .current_expansion.mark.expn_info().unwrap() + .allow_internal_unstable.iter() + .any(|&s| s == "core_intrinsics"); + if intrinsic_allowed_via_allow_internal_unstable { span = span.with_ctxt(cx.backtrace()); } else { // Avoid instability errors with user defined curstom derives, cc #36316 let mut info = cx.current_expansion.mark.expn_info().unwrap(); - info.allow_internal_unstable = true; + info.allow_internal_unstable = vec![Symbol::intern("core_intrinsics")]; let mark = Mark::fresh(Mark::root()); mark.set_expn_info(info); span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 6bb7ee1d5ddfd..1b17fc0d040a5 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -711,7 +711,7 @@ pub fn expand_format_args_nl<'cx>( //if !ecx.ecfg.enable_allow_internal_unstable() { // For some reason, the only one that actually works for `println` is the first check - if !sp.allows_unstable() // the enclosing span is marked as `#[allow_insternal_unsable]` + if !sp.allows_unstable("format_args_nl") // the span is marked as `#[allow_insternal_unsable]` && !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled? && !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]` { diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 670d71fe25bb8..dacc54d272bca 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -60,7 +60,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new($f as MacroExpanderFn), def_info: None, - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, @@ -103,7 +103,9 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new(format::expand_format_args), def_info: None, - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("fmt_internals"), + ], allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, @@ -113,7 +115,9 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new(format::expand_format_args_nl), def_info: None, - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("fmt_internals"), + ], allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 24d095145201e..f198739d1048b 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -333,7 +333,10 @@ fn mk_decls( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("proc_macro")), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("proc_macro_internals"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 832bebb6113e9..e2bea0c8b07e5 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -66,7 +66,10 @@ pub fn expand_test_or_bench( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test")), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("test"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index 63417b702d569..a581c28219303 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -41,7 +41,10 @@ pub fn expand( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test_case")), - allow_internal_unstable: true, + allow_internal_unstable: vec![ + Symbol::intern("test"), + Symbol::intern("rustc_attrs"), + ], allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 0c645fc678caf..f9394826c9b68 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -550,10 +550,10 @@ pub struct ExpnInfo { pub def_site: Option, /// The format with which the macro was invoked. pub format: ExpnFormat, - /// Whether the macro is allowed to use #[unstable]/feature-gated - /// features internally without forcing the whole crate to opt-in + /// List of #[unstable]/feature-gated features that the macro is allowed to use + /// internally without forcing the whole crate to opt-in /// to them. - pub allow_internal_unstable: bool, + pub allow_internal_unstable: Vec, /// Whether the macro is allowed to use `unsafe` internally /// even if the user crate has `#![forbid(unsafe_code)]`. pub allow_internal_unsafe: bool, diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 70c45f7f9a7a6..efb21e06f34cc 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -385,9 +385,9 @@ impl Span { /// Check if a span is "internal" to a macro in which `#[unstable]` /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). - pub fn allows_unstable(&self) -> bool { + pub fn allows_unstable(&self, feature: &str) -> bool { match self.ctxt().outer().expn_info() { - Some(info) => info.allow_internal_unstable, + Some(info) => info.allow_internal_unstable.iter().any(|&f| f == feature), None => false, } } diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs index cf320b2747c36..ee48f9516299a 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs @@ -5,7 +5,7 @@ macro_rules! bar { () => { // more layers don't help: - #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps + #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps macro_rules! baz { () => {} } diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr index 7cdf743b279c2..802c74239d719 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:9 | -LL | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(); | ------- in this macro invocation diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs index c9ea6c338b5cc..ede969097d5ae 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs @@ -1,7 +1,7 @@ // checks that this attribute is caught on non-macro items. // this needs a different test since this is done after expansion -#[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps +#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps struct S; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr index 485c00ad42bd6..d619f1e3239ca 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks --> $DIR/feature-gate-allow-internal-unstable-struct.rs:4:1 | -LL | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs index bea60fc012e3f..0a1b6acd9bff2 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.rs @@ -1,6 +1,6 @@ #![allow(unused_macros)] -#[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps +#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps macro_rules! foo { () => {} } diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr index 0533d071de3ac..aa4f6648c4fbd 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable.stderr @@ -1,8 +1,8 @@ error[E0658]: allow_internal_unstable side-steps feature gating and stability checks --> $DIR/feature-gate-allow-internal-unstable.rs:3:1 | -LL | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable diff --git a/src/test/ui/internal/auxiliary/internal_unstable.rs b/src/test/ui/internal/auxiliary/internal_unstable.rs index 7cf54c3e6a69f..7c79dcb752272 100644 --- a/src/test/ui/internal/auxiliary/internal_unstable.rs +++ b/src/test/ui/internal/auxiliary/internal_unstable.rs @@ -23,14 +23,14 @@ pub struct Bar { } #[stable(feature = "stable", since = "1.0.0")] -#[allow_internal_unstable] +#[allow_internal_unstable(function)] #[macro_export] macro_rules! call_unstable_allow { () => { $crate::unstable() } } #[stable(feature = "stable", since = "1.0.0")] -#[allow_internal_unstable] +#[allow_internal_unstable(struct_field)] #[macro_export] macro_rules! construct_unstable_allow { ($e: expr) => { @@ -39,21 +39,21 @@ macro_rules! construct_unstable_allow { } #[stable(feature = "stable", since = "1.0.0")] -#[allow_internal_unstable] +#[allow_internal_unstable(method)] #[macro_export] macro_rules! call_method_allow { ($e: expr) => { $e.method() } } #[stable(feature = "stable", since = "1.0.0")] -#[allow_internal_unstable] +#[allow_internal_unstable(struct_field, struct2_field)] #[macro_export] macro_rules! access_field_allow { ($e: expr) => { $e.x } } #[stable(feature = "stable", since = "1.0.0")] -#[allow_internal_unstable] +#[allow_internal_unstable()] #[macro_export] macro_rules! pass_through_allow { ($e: expr) => { $e } diff --git a/src/test/ui/internal/internal-unstable.rs b/src/test/ui/internal/internal-unstable.rs index 34fef33bfeb97..e09a5d89172e8 100644 --- a/src/test/ui/internal/internal-unstable.rs +++ b/src/test/ui/internal/internal-unstable.rs @@ -13,7 +13,7 @@ macro_rules! foo { }} } -#[allow_internal_unstable] +#[allow_internal_unstable(function)] macro_rules! bar { ($e: expr) => {{ foo!($e, From 33bf81eec018ec717bffc4468faf8d2a3bde1892 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 3 Feb 2019 13:57:03 +0100 Subject: [PATCH 02/13] Ease the transition to requiring features by just warning if there's no feature list while we could make this change (it's all unstable after all), there are crates.io crates that use the feature and that the compiler depends upon. We can instead roll out this feature while still supporting the old way. --- src/libsyntax/ext/tt/macro_rules.rs | 22 ++++++++++++++-------- src/libsyntax/feature_gate.rs | 3 ++- src/libsyntax_pos/lib.rs | 5 ++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4409bf13b6c7b..a79f3271fcb18 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -379,14 +379,20 @@ pub fn compile( let allow_internal_unstable = attr::find_by_name(&def.attrs, "allow_internal_unstable") .map_or(Vec::new(), |attr| attr .meta_item_list() - .unwrap_or_else(|| sess.span_diagnostic.span_bug( - attr.span, "allow_internal_unstable expects list of feature names", - )) - .iter() - .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( - it.span, "allow internal unstable expects feature names", - ))) - .collect() + .map(|list| list.iter() + .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( + it.span, "allow internal unstable expects feature names", + ))) + .collect() + ) + .unwrap_or_else(|| { + sess.span_diagnostic.span_warn( + attr.span, "allow_internal_unstable expects list of feature names. In the \ + future this will become a hard error. Please use `allow_internal_unstable(\ + foo, bar)` to only allow the `foo` and `bar` features", + ); + vec![Symbol::intern("allow_internal_unstable_backcompat_hack")] + }) ); let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); let mut local_inner_macros = false; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1e1b315824f1e..08f1473200c1e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1091,7 +1091,8 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu stable", cfg_fn!(profiler_runtime))), - ("allow_internal_unstable", Normal, template!(List: "feat1, feat2"), Gated(Stability::Unstable, + ("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2"), + Gated(Stability::Unstable, "allow_internal_unstable", EXPLAIN_ALLOW_INTERNAL_UNSTABLE, cfg_fn!(allow_internal_unstable))), diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index efb21e06f34cc..87c4d02fa4f3a 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -387,7 +387,10 @@ impl Span { /// `#[allow_internal_unstable]`). pub fn allows_unstable(&self, feature: &str) -> bool { match self.ctxt().outer().expn_info() { - Some(info) => info.allow_internal_unstable.iter().any(|&f| f == feature), + Some(info) => info + .allow_internal_unstable + .iter() + .any(|&f| f == feature || f == "allow_internal_unstable_backcompat_hack"), None => false, } } From 87d5383ec30e9837215b0d4a6e03b28bd9594117 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 Feb 2019 11:16:50 +0100 Subject: [PATCH 03/13] Rename the `exp` field to mirror its uses --- src/librustc_plugin/registry.rs | 4 ++-- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 14312f0b2f705..9ff10ff851ae3 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -110,8 +110,8 @@ impl<'a> Registry<'a> { edition, } } - IdentTT { ext, span: _, allow_internal_unstable } => { - IdentTT { ext, span: Some(self.krate_span), allow_internal_unstable } + IdentTT { expander, span: _, allow_internal_unstable } => { + IdentTT { expander, span: Some(self.krate_span), allow_internal_unstable } } _ => extension, })); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 02d6d7218733c..ec7d0e423b4cf 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -658,7 +658,7 @@ pub enum SyntaxExtension { /// A function-like syntax extension that has an extra ident before /// the block. IdentTT { - ext: Box, + expander: Box, span: Option, allow_internal_unstable: Vec, }, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 65500cd23bd7e..2d4082386b261 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -792,7 +792,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - IdentTT { ext: ref expander, span: tt_span, ref allow_internal_unstable } => { + IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => { if ident.name == keywords::Invalid.name() { self.cx.span_err(path.span, &format!("macro {}! expects an ident argument", path)); From 0b3d8de2a08a066fc853d5afb0f9b89905609f98 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 Feb 2019 11:18:12 +0100 Subject: [PATCH 04/13] Consistent attribute argument suggestion --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 08f1473200c1e..4d24c7bfb4038 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1091,7 +1091,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu stable", cfg_fn!(profiler_runtime))), - ("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2"), + ("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2, ..."), Gated(Stability::Unstable, "allow_internal_unstable", EXPLAIN_ALLOW_INTERNAL_UNSTABLE, From 19208367d4c56e2245e80b2a4aeafa03a150d4b7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 Feb 2019 11:24:55 +0100 Subject: [PATCH 05/13] Use a more fitting name for a respanning function --- src/librustc/hir/lowering.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b01362b0ed4b3..a77c1268d2221 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -681,7 +681,9 @@ impl<'a> LoweringContext<'a> { Ident::with_empty_ctxt(Symbol::gensym(s)) } - fn allow_internal_unstable( + /// Reuses the span but adds information like the kind of the desugaring and features that are + /// allowed inside this span. + fn mark_span_with_reason( &self, reason: CompilerDesugaringKind, span: Span, @@ -969,7 +971,7 @@ impl<'a> LoweringContext<'a> { attrs: ThinVec::new(), }; - let unstable_span = self.allow_internal_unstable( + let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, vec![ @@ -1371,7 +1373,7 @@ impl<'a> LoweringContext<'a> { // desugaring that explicitly states that we don't want to track that. // Not tracking it makes lints in rustc and clippy very fragile as // frequently opened issues show. - let exist_ty_span = self.allow_internal_unstable( + let exist_ty_span = self.mark_span_with_reason( CompilerDesugaringKind::ExistentialReturnType, span, Vec::new(), // doesn'c actually allow anything unstable @@ -3939,7 +3941,7 @@ impl<'a> LoweringContext<'a> { }), ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { - let unstable_span = this.allow_internal_unstable( + let unstable_span = this.mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, vec![ @@ -4377,7 +4379,7 @@ impl<'a> LoweringContext<'a> { // expand let head = self.lower_expr(head); let head_sp = head.span; - let desugared_span = self.allow_internal_unstable( + let desugared_span = self.mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, Vec::new(), @@ -4543,7 +4545,7 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = self.allow_internal_unstable( + let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, vec![ From da8352cee49de8b64545b8956434805879344a98 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 Feb 2019 11:49:25 +0100 Subject: [PATCH 06/13] Fixup RustcDeserialize internal features --- src/libsyntax/ext/expand.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2d4082386b261..d59e5ab67980c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -942,6 +942,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Symbol::intern("rustc_attrs"), Symbol::intern("derive_clone_copy"), Symbol::intern("derive_eq"), + Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize ]; invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); From 36e7424b86eac4e88cd2965ec6980f3b477a8621 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 Feb 2019 15:47:51 +0100 Subject: [PATCH 07/13] Update fulldeps test --- src/test/run-pass-fulldeps/auxiliary/plugin_args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs index eab612c5dfb45..2a5b687ac2947 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs @@ -43,7 +43,7 @@ pub fn plugin_registrar(reg: &mut Registry) { NormalTT { expander: Box::new(Expander { args: args, }), def_info: None, - allow_internal_unstable: false, + allow_internal_unstable: Vec::new(), allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, From 4cfc2ce46d2813f5120053929609de6f9b976cd6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 5 Feb 2019 10:56:29 +0100 Subject: [PATCH 08/13] Use `allow_internal_unstable` in rustc itself --- src/librustc_data_structures/macros.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index a661f0c78ab5d..af1f2910461ec 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -1,7 +1,8 @@ /// A simple static assertion macro. The first argument should be a unique /// ALL_CAPS identifier that describes the condition. #[macro_export] -#[allow_internal_unstable] +#[cfg_attr(stage0, allow_internal_unstable)] +#[cfg_attr(not(stage0), allow_internal_unstable(type_ascription))] macro_rules! static_assert { ($name:ident: $test:expr) => { // Use the bool to access an array such that if the bool is false, the access From a83e73dce4f0e80ff7559b3816f4f24391d4ff53 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 6 Feb 2019 10:58:06 +0100 Subject: [PATCH 09/13] Move out tests of a deprecated module to work around `#[test]` bugs https://github.com/rust-lang/rust/issues/47238 --- src/libstd/sync/mpsc/mod.rs | 3 + src/libstd/sync/mpsc/select.rs | 414 --------------------------- src/libstd/sync/mpsc/select_tests.rs | 413 ++++++++++++++++++++++++++ 3 files changed, 416 insertions(+), 414 deletions(-) create mode 100644 src/libstd/sync/mpsc/select_tests.rs diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 446c164965d6f..a8843549b8abc 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -279,6 +279,9 @@ use self::select::StartResult; use self::select::StartResult::*; use self::blocking::SignalToken; +#[cfg(all(test, not(target_os = "emscripten")))] +mod select_tests; + mod blocking; mod oneshot; mod select; diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 8f41680a818b9..9487c0cf67488 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -352,417 +352,3 @@ impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> { f.debug_struct("Handle").finish() } } - -#[allow(unused_imports)] -#[cfg(all(test, not(target_os = "emscripten")))] -mod tests { - use thread; - use sync::mpsc::*; - - // Don't use the libstd version so we can pull in the right Select structure - // (std::comm points at the wrong one) - macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - let sel = Select::new(); - $( let mut $rx = sel.handle(&$rx); )+ - unsafe { - $( $rx.add(); )+ - } - let ret = sel.wait(); - $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ - { unreachable!() } - }) - } - - #[test] - fn smoke() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - tx1.send(1).unwrap(); - select! { - foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, - _bar = rx2.recv() => { panic!() } - } - tx2.send(2).unwrap(); - select! { - _foo = rx1.recv() => { panic!() }, - bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } - } - drop(tx1); - select! { - foo = rx1.recv() => { assert!(foo.is_err()); }, - _bar = rx2.recv() => { panic!() } - } - drop(tx2); - select! { - bar = rx2.recv() => { assert!(bar.is_err()); } - } - } - - #[test] - fn smoke2() { - let (_tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (_tx3, rx3) = channel::(); - let (_tx4, rx4) = channel::(); - let (tx5, rx5) = channel::(); - tx5.send(4).unwrap(); - select! { - _foo = rx1.recv() => { panic!("1") }, - _foo = rx2.recv() => { panic!("2") }, - _foo = rx3.recv() => { panic!("3") }, - _foo = rx4.recv() => { panic!("4") }, - foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } - } - } - - #[test] - fn closed() { - let (_tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - drop(tx2); - - select! { - _a1 = rx1.recv() => { panic!() }, - a2 = rx2.recv() => { assert!(a2.is_err()); } - } - } - - #[test] - fn unblocks() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - rx3.recv().unwrap(); - for _ in 0..20 { thread::yield_now(); } - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - _b = rx2.recv() => { panic!() } - } - tx3.send(1).unwrap(); - select! { - a = rx1.recv() => { assert!(a.is_err()) }, - _b = rx2.recv() => { panic!() } - } - } - - #[test] - fn both_ready() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - tx2.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); - tx3.send(()).unwrap(); - } - - #[test] - fn stress() { - const AMT: i32 = 10000; - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for i in 0..AMT { - if i % 2 == 0 { - tx1.send(i).unwrap(); - } else { - tx2.send(i).unwrap(); - } - rx3.recv().unwrap(); - } - }); - - for i in 0..AMT { - select! { - i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, - i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } - } - tx3.send(()).unwrap(); - } - } - - #[allow(unused_must_use)] - #[test] - fn cloning() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); - } - - #[allow(unused_must_use)] - #[test] - fn cloning2() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); - } - - #[test] - fn cloning3() { - let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::<()>(); - let (tx3, rx3) = channel::<()>(); - let _t = thread::spawn(move|| { - let s = Select::new(); - let mut h1 = s.handle(&rx1); - let mut h2 = s.handle(&rx2); - unsafe { h2.add(); } - unsafe { h1.add(); } - assert_eq!(s.wait(), h2.id); - tx3.send(()).unwrap(); - }); - - for _ in 0..1000 { thread::yield_now(); } - drop(tx1.clone()); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); - } - - #[test] - fn preflight1() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight2() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight3() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } - } - - #[test] - fn preflight4() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn preflight5() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn preflight6() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn preflight7() { - let (tx, rx) = channel::<()>(); - drop(tx); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn preflight8() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn preflight9() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); - } - - #[test] - fn oneshot_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - } - - #[test] - fn stream_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - tx1.send(()).unwrap(); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - } - - #[test] - fn shared_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - drop(tx1.clone()); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); - } - - #[test] - fn sync1() { - let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } - } - - #[test] - fn sync2() { - let (tx, rx) = sync_channel::(0); - let _t = thread::spawn(move|| { - for _ in 0..100 { thread::yield_now() } - tx.send(1).unwrap(); - }); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } - } - - #[test] - fn sync3() { - let (tx1, rx1) = sync_channel::(0); - let (tx2, rx2): (Sender, Receiver) = channel(); - let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); - let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); - select! { - n = rx1.recv() => { - let n = n.unwrap(); - assert_eq!(n, 1); - assert_eq!(rx2.recv().unwrap(), 2); - }, - n = rx2.recv() => { - let n = n.unwrap(); - assert_eq!(n, 2); - assert_eq!(rx1.recv().unwrap(), 1); - } - } - } -} diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs new file mode 100644 index 0000000000000..4f9ce20fc3471 --- /dev/null +++ b/src/libstd/sync/mpsc/select_tests.rs @@ -0,0 +1,413 @@ +#![allow(unused_imports)] + +/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238 + +use thread; +use sync::mpsc::*; + +// Don't use the libstd version so we can pull in the right Select structure +// (std::comm points at the wrong one) +macro_rules! select { + ( + $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ + ) => ({ + let sel = Select::new(); + $( let mut $rx = sel.handle(&$rx); )+ + unsafe { + $( $rx.add(); )+ + } + let ret = sel.wait(); + $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ + { unreachable!() } + }) +} + +#[test] +fn smoke() { + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); + tx1.send(1).unwrap(); + select! { + foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, + _bar = rx2.recv() => { panic!() } + } + tx2.send(2).unwrap(); + select! { + _foo = rx1.recv() => { panic!() }, + bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } + } + drop(tx1); + select! { + foo = rx1.recv() => { assert!(foo.is_err()); }, + _bar = rx2.recv() => { panic!() } + } + drop(tx2); + select! { + bar = rx2.recv() => { assert!(bar.is_err()); } + } +} + +#[test] +fn smoke2() { + let (_tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (_tx3, rx3) = channel::(); + let (_tx4, rx4) = channel::(); + let (tx5, rx5) = channel::(); + tx5.send(4).unwrap(); + select! { + _foo = rx1.recv() => { panic!("1") }, + _foo = rx2.recv() => { panic!("2") }, + _foo = rx3.recv() => { panic!("3") }, + _foo = rx4.recv() => { panic!("4") }, + foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } + } +} + +#[test] +fn closed() { + let (_tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); + drop(tx2); + + select! { + _a1 = rx1.recv() => { panic!() }, + a2 = rx2.recv() => { assert!(a2.is_err()); } + } +} + +#[test] +fn unblocks() { + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (tx3, rx3) = channel::(); + + let _t = thread::spawn(move|| { + for _ in 0..20 { thread::yield_now(); } + tx1.send(1).unwrap(); + rx3.recv().unwrap(); + for _ in 0..20 { thread::yield_now(); } + }); + + select! { + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + _b = rx2.recv() => { panic!() } + } + tx3.send(1).unwrap(); + select! { + a = rx1.recv() => { assert!(a.is_err()) }, + _b = rx2.recv() => { panic!() } + } +} + +#[test] +fn both_ready() { + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); + let (tx3, rx3) = channel::<()>(); + + let _t = thread::spawn(move|| { + for _ in 0..20 { thread::yield_now(); } + tx1.send(1).unwrap(); + tx2.send(2).unwrap(); + rx3.recv().unwrap(); + }); + + select! { + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } + } + select! { + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } + } + assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); + assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); + tx3.send(()).unwrap(); +} + +#[test] +fn stress() { + const AMT: i32 = 10000; + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); + let (tx3, rx3) = channel::<()>(); + + let _t = thread::spawn(move|| { + for i in 0..AMT { + if i % 2 == 0 { + tx1.send(i).unwrap(); + } else { + tx2.send(i).unwrap(); + } + rx3.recv().unwrap(); + } + }); + + for i in 0..AMT { + select! { + i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, + i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } + } + tx3.send(()).unwrap(); + } +} + +#[allow(unused_must_use)] +#[test] +fn cloning() { + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (tx3, rx3) = channel::<()>(); + + let _t = thread::spawn(move|| { + rx3.recv().unwrap(); + tx1.clone(); + assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); + tx1.send(2).unwrap(); + rx3.recv().unwrap(); + }); + + tx3.send(()).unwrap(); + select! { + _i1 = rx1.recv() => {}, + _i2 = rx2.recv() => panic!() + } + tx3.send(()).unwrap(); +} + +#[allow(unused_must_use)] +#[test] +fn cloning2() { + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (tx3, rx3) = channel::<()>(); + + let _t = thread::spawn(move|| { + rx3.recv().unwrap(); + tx1.clone(); + assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); + tx1.send(2).unwrap(); + rx3.recv().unwrap(); + }); + + tx3.send(()).unwrap(); + select! { + _i1 = rx1.recv() => {}, + _i2 = rx2.recv() => panic!() + } + tx3.send(()).unwrap(); +} + +#[test] +fn cloning3() { + let (tx1, rx1) = channel::<()>(); + let (tx2, rx2) = channel::<()>(); + let (tx3, rx3) = channel::<()>(); + let _t = thread::spawn(move|| { + let s = Select::new(); + let mut h1 = s.handle(&rx1); + let mut h2 = s.handle(&rx2); + unsafe { h2.add(); } + unsafe { h1.add(); } + assert_eq!(s.wait(), h2.id); + tx3.send(()).unwrap(); + }); + + for _ in 0..1000 { thread::yield_now(); } + drop(tx1.clone()); + tx2.send(()).unwrap(); + rx3.recv().unwrap(); +} + +#[test] +fn preflight1() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + select! { + _n = rx.recv() => {} + } +} + +#[test] +fn preflight2() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + tx.send(()).unwrap(); + select! { + _n = rx.recv() => {} + } +} + +#[test] +fn preflight3() { + let (tx, rx) = channel(); + drop(tx.clone()); + tx.send(()).unwrap(); + select! { + _n = rx.recv() => {} + } +} + +#[test] +fn preflight4() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn preflight5() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + tx.send(()).unwrap(); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn preflight6() { + let (tx, rx) = channel(); + drop(tx.clone()); + tx.send(()).unwrap(); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn preflight7() { + let (tx, rx) = channel::<()>(); + drop(tx); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn preflight8() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + drop(tx); + rx.recv().unwrap(); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn preflight9() { + let (tx, rx) = channel(); + drop(tx.clone()); + tx.send(()).unwrap(); + drop(tx); + rx.recv().unwrap(); + let s = Select::new(); + let mut h = s.handle(&rx); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); +} + +#[test] +fn oneshot_data_waiting() { + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + let _t = thread::spawn(move|| { + select! { + _n = rx1.recv() => {} + } + tx2.send(()).unwrap(); + }); + + for _ in 0..100 { thread::yield_now() } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); +} + +#[test] +fn stream_data_waiting() { + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + tx1.send(()).unwrap(); + tx1.send(()).unwrap(); + rx1.recv().unwrap(); + rx1.recv().unwrap(); + let _t = thread::spawn(move|| { + select! { + _n = rx1.recv() => {} + } + tx2.send(()).unwrap(); + }); + + for _ in 0..100 { thread::yield_now() } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); +} + +#[test] +fn shared_data_waiting() { + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + drop(tx1.clone()); + tx1.send(()).unwrap(); + rx1.recv().unwrap(); + let _t = thread::spawn(move|| { + select! { + _n = rx1.recv() => {} + } + tx2.send(()).unwrap(); + }); + + for _ in 0..100 { thread::yield_now() } + tx1.send(()).unwrap(); + rx2.recv().unwrap(); +} + +#[test] +fn sync1() { + let (tx, rx) = sync_channel::(1); + tx.send(1).unwrap(); + select! { + n = rx.recv() => { assert_eq!(n.unwrap(), 1); } + } +} + +#[test] +fn sync2() { + let (tx, rx) = sync_channel::(0); + let _t = thread::spawn(move|| { + for _ in 0..100 { thread::yield_now() } + tx.send(1).unwrap(); + }); + select! { + n = rx.recv() => { assert_eq!(n.unwrap(), 1); } + } +} + +#[test] +fn sync3() { + let (tx1, rx1) = sync_channel::(0); + let (tx2, rx2): (Sender, Receiver) = channel(); + let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); + let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); + select! { + n = rx1.recv() => { + let n = n.unwrap(); + assert_eq!(n, 1); + assert_eq!(rx2.recv().unwrap(), 2); + }, + n = rx2.recv() => { + let n = n.unwrap(); + assert_eq!(n, 2); + assert_eq!(rx1.recv().unwrap(), 1); + } + } +} From 1dba7cb20224b5bb3a22641b2f4f2f73e5157dee Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 6 Feb 2019 10:58:29 +0100 Subject: [PATCH 10/13] Fiddle through the module visibilities for tests --- src/libstd/sync/mpsc/select.rs | 2 +- src/libstd/sync/mpsc/select_tests.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 9487c0cf67488..e34fc5487cf90 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -158,7 +158,7 @@ impl Select { } /// Helper method for skipping the preflight checks during testing - fn wait2(&self, do_preflight_checks: bool) -> usize { + pub(super) fn wait2(&self, do_preflight_checks: bool) -> usize { // Note that this is currently an inefficient implementation. We in // theory have knowledge about all receivers in the set ahead of time, // so this method shouldn't really have to iterate over all of them yet diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs index 4f9ce20fc3471..be048511caaec 100644 --- a/src/libstd/sync/mpsc/select_tests.rs +++ b/src/libstd/sync/mpsc/select_tests.rs @@ -210,7 +210,7 @@ fn cloning3() { let mut h2 = s.handle(&rx2); unsafe { h2.add(); } unsafe { h1.add(); } - assert_eq!(s.wait(), h2.id); + assert_eq!(s.wait(), h2.id()); tx3.send(()).unwrap(); }); @@ -256,7 +256,7 @@ fn preflight4() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] @@ -267,7 +267,7 @@ fn preflight5() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] @@ -278,7 +278,7 @@ fn preflight6() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] @@ -288,7 +288,7 @@ fn preflight7() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] @@ -300,7 +300,7 @@ fn preflight8() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] @@ -313,7 +313,7 @@ fn preflight9() { let s = Select::new(); let mut h = s.handle(&rx); unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id); + assert_eq!(s.wait2(false), h.id()); } #[test] From b681433b9d40ce1d851d22bedb7ccb483bedda06 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 7 Feb 2019 14:19:06 +0100 Subject: [PATCH 11/13] Use `Rc<[Symbol]>` instead of `Vec` to reduce # of allocs --- src/librustc/hir/lowering.rs | 19 ++++++++++--------- src/librustc_allocator/expand.rs | 4 ++-- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 4 ++-- src/librustc_plugin/registry.rs | 2 +- src/libsyntax/ext/base.rs | 6 +++--- src/libsyntax/ext/derive.rs | 4 ++-- src/libsyntax/ext/expand.rs | 10 +++++----- src/libsyntax/ext/tt/macro_rules.rs | 6 +++--- src/libsyntax/std_inject.rs | 4 ++-- src/libsyntax/test.rs | 4 ++-- src/libsyntax_ext/deriving/mod.rs | 7 ++++--- src/libsyntax_ext/lib.rs | 10 +++++----- src/libsyntax_ext/proc_macro_decls.rs | 4 ++-- src/libsyntax_ext/test.rs | 4 ++-- src/libsyntax_ext/test_case.rs | 4 ++-- src/libsyntax_pos/hygiene.rs | 3 ++- src/libsyntax_pos/lib.rs | 5 +++-- .../auxiliary/plugin_args.rs | 2 +- 19 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a77c1268d2221..15184ec9d27ff 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -52,6 +52,7 @@ use crate::util::nodemap::{DefIdMap, NodeMap}; use std::collections::{BTreeSet, BTreeMap}; use std::fmt::Debug; use std::mem; +use std::rc::Rc; use smallvec::SmallVec; use syntax::attr; use syntax::ast; @@ -687,7 +688,7 @@ impl<'a> LoweringContext<'a> { &self, reason: CompilerDesugaringKind, span: Span, - allow_internal_unstable: Vec, + allow_internal_unstable: Option>, ) -> Span { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(source_map::ExpnInfo { @@ -974,9 +975,9 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, - vec![ + Some(vec![ Symbol::intern("gen_future"), - ], + ].into()), ); let gen_future = self.expr_std_path( unstable_span, &["future", "from_generator"], None, ThinVec::new()); @@ -1376,7 +1377,7 @@ impl<'a> LoweringContext<'a> { let exist_ty_span = self.mark_span_with_reason( CompilerDesugaringKind::ExistentialReturnType, span, - Vec::new(), // doesn'c actually allow anything unstable + None, ); let exist_ty_def_index = self @@ -3944,9 +3945,9 @@ impl<'a> LoweringContext<'a> { let unstable_span = this.mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, - vec![ + Some(vec![ Symbol::intern("try_trait"), - ], + ].into()), ); let mut block = this.lower_block(body, true).into_inner(); let tail = block.expr.take().map_or_else( @@ -4382,7 +4383,7 @@ impl<'a> LoweringContext<'a> { let desugared_span = self.mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, - Vec::new(), + None, ); let iter = self.str_to_ident("iter"); @@ -4548,9 +4549,9 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, - vec![ + Some(vec![ Symbol::intern("try_trait") - ], + ].into()), ); // `Try::into_result()` diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index b877c80af1aba..758a0d63886b1 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -91,9 +91,9 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { call_site: item.span, // use the call site of the static def_site: None, format: MacroAttribute(Symbol::intern(name)), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("rustc_attrs"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9fca1a983c30d..90b0fb249aa61 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -570,7 +570,7 @@ impl<'a> CrateLoader<'a> { ProcMacro::Bang { name, client } => { (name, SyntaxExtension::ProcMacro { expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, edition: root.edition, }) } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index f7c7c627959a7..f49b88f14e60e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -425,9 +425,9 @@ impl cstore::CStore { let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); let ext = SyntaxExtension::ProcMacro { expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("proc_macro_def_site"), - ], + ].into()), edition: data.root.edition, }; return LoadedMacro::ProcMacro(Lrc::new(ext)); diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 9ff10ff851ae3..2da520d396948 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -126,7 +126,7 @@ impl<'a> Registry<'a> { self.register_syntax_extension(Symbol::intern(name), NormalTT { expander: Box::new(expander), def_info: None, - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ec7d0e423b4cf..7c6303b3d404f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -622,7 +622,7 @@ pub enum SyntaxExtension { ProcMacro { expander: Box, /// Whitelist of unstable features that are treated as stable inside this macro - allow_internal_unstable: Vec, + allow_internal_unstable: Option>, edition: Edition, }, @@ -642,7 +642,7 @@ pub enum SyntaxExtension { /// directly use `#[unstable]` things. /// /// Only allows things that require a feature gate in the given whitelist - allow_internal_unstable: Vec, + allow_internal_unstable: Option>, /// Whether the contents of the macro can use `unsafe` /// without triggering the `unsafe_code` lint. allow_internal_unsafe: bool, @@ -660,7 +660,7 @@ pub enum SyntaxExtension { IdentTT { expander: Box, span: Option, - allow_internal_unstable: Vec, + allow_internal_unstable: Option>, }, /// An attribute-like procedural macro. TokenStream -> TokenStream. diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 03d68f4257f1b..6df369133d01d 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -58,10 +58,10 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P call_site: span, def_site: None, format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("rustc_attrs"), Symbol::intern("structural_match"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d59e5ab67980c..60359531b7f63 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -558,7 +558,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: attr.span, def_site: None, format: MacroAttribute(Symbol::intern(&attr.path.to_string())), - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -758,7 +758,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let opt_expanded = match *ext { DeclMacro { ref expander, def_info, edition, .. } => { if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - Vec::new(), false, false, None, + None, false, false, None, edition) { dummy_span } else { @@ -919,7 +919,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: span, def_site: None, format: MacroAttribute(pretty_name), - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -938,12 +938,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(invoc.fragment_kind.expect_from_annotatables(items)) } BuiltinDerive(func) => { - expn_info.allow_internal_unstable = vec![ + expn_info.allow_internal_unstable = Some(vec![ Symbol::intern("rustc_attrs"), Symbol::intern("derive_clone_copy"), Symbol::intern("derive_eq"), Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize - ]; + ].into()); invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let mut items = Vec::new(); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a79f3271fcb18..cc5531c401046 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -377,13 +377,13 @@ pub fn compile( if body.legacy { let allow_internal_unstable = attr::find_by_name(&def.attrs, "allow_internal_unstable") - .map_or(Vec::new(), |attr| attr + .map(|attr| attr .meta_item_list() .map(|list| list.iter() .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( it.span, "allow internal unstable expects feature names", ))) - .collect() + .collect::>().into() ) .unwrap_or_else(|| { sess.span_diagnostic.span_warn( @@ -391,7 +391,7 @@ pub fn compile( future this will become a hard error. Please use `allow_internal_unstable(\ foo, bar)` to only allow the `foo` and `bar` features", ); - vec![Symbol::intern("allow_internal_unstable_backcompat_hack")] + vec![Symbol::intern("allow_internal_unstable_backcompat_hack")].into() }) ); let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 91ec42a33b5f6..b9758bd655c15 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,9 +20,9 @@ fn ignored_span(sp: Span) -> Span { call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("prelude_import"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index aa107130eee2b..f45bf034ba2f8 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -285,11 +285,11 @@ fn generate_test_harness(sess: &ParseSess, call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test_case")), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("main"), Symbol::intern("test"), Symbol::intern("rustc_attrs"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index bc86ffa852bbe..fff54814a38c4 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -138,13 +138,14 @@ fn call_intrinsic(cx: &ExtCtxt<'_>, -> P { let intrinsic_allowed_via_allow_internal_unstable = cx .current_expansion.mark.expn_info().unwrap() - .allow_internal_unstable.iter() - .any(|&s| s == "core_intrinsics"); + .allow_internal_unstable.map_or(false, |features| features.iter().any(|&s| + s == "core_intrinsics" + )); if intrinsic_allowed_via_allow_internal_unstable { span = span.with_ctxt(cx.backtrace()); } else { // Avoid instability errors with user defined curstom derives, cc #36316 let mut info = cx.current_expansion.mark.expn_info().unwrap(); - info.allow_internal_unstable = vec![Symbol::intern("core_intrinsics")]; + info.allow_internal_unstable = Some(vec![Symbol::intern("core_intrinsics")].into()); let mark = Mark::fresh(Mark::root()); mark.set_expn_info(info); span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index dacc54d272bca..719f9a4b3fdd5 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -60,7 +60,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new($f as MacroExpanderFn), def_info: None, - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, @@ -103,9 +103,9 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new(format::expand_format_args), def_info: None, - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("fmt_internals"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, @@ -115,9 +115,9 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, NormalTT { expander: Box::new(format::expand_format_args_nl), def_info: None, - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("fmt_internals"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index f198739d1048b..5730081ce018a 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -333,10 +333,10 @@ fn mk_decls( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("proc_macro")), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("rustc_attrs"), Symbol::intern("proc_macro_internals"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index e2bea0c8b07e5..371862465487b 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -66,10 +66,10 @@ pub fn expand_test_or_bench( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test")), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("rustc_attrs"), Symbol::intern("test"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index a581c28219303..1ed1ab0a07b96 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -41,10 +41,10 @@ pub fn expand( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test_case")), - allow_internal_unstable: vec![ + allow_internal_unstable: Some(vec![ Symbol::intern("test"), Symbol::intern("rustc_attrs"), - ], + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index f9394826c9b68..fb9b4c9d70e39 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -13,6 +13,7 @@ use crate::symbol::{keywords, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::{fmt, mem}; +use std::rc::Rc; /// A SyntaxContext represents a chain of macro expansions (represented by marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] @@ -553,7 +554,7 @@ pub struct ExpnInfo { /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. - pub allow_internal_unstable: Vec, + pub allow_internal_unstable: Option>, /// Whether the macro is allowed to use `unsafe` internally /// even if the user crate has `#![forbid(unsafe_code)]`. pub allow_internal_unsafe: bool, diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 87c4d02fa4f3a..f0dc1b00fd931 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -389,8 +389,9 @@ impl Span { match self.ctxt().outer().expn_info() { Some(info) => info .allow_internal_unstable - .iter() - .any(|&f| f == feature || f == "allow_internal_unstable_backcompat_hack"), + .map_or(false, |features| features.iter().any(|&f| + f == feature || f == "allow_internal_unstable_backcompat_hack" + )), None => false, } } diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs index 2a5b687ac2947..309acb25184a8 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs @@ -43,7 +43,7 @@ pub fn plugin_registrar(reg: &mut Registry) { NormalTT { expander: Box::new(Expander { args: args, }), def_info: None, - allow_internal_unstable: Vec::new(), + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, From b0cf52f6a52699be9ae6d2d01c3c172d55ad549e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 7 Feb 2019 14:53:21 +0100 Subject: [PATCH 12/13] Allow platform specific tests --- src/tools/tidy/src/pal.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 0f722945c49e6..ed2218f09d26b 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -58,6 +58,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libstd/sys_common/net.rs", "src/libterm", // Not sure how to make this crate portable, but test crate needs it. "src/libtest", // Probably should defer to unstable `std::sys` APIs. + "src/libstd/sync/mpsc", // some tests are only run on non-emscripten // std testing crates, okay for now at least "src/libcore/tests", From bbe524d7c1a1028737a93c7c71c508a68363b681 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 8 Feb 2019 10:21:21 +0100 Subject: [PATCH 13/13] Parallel rustc needs synchronizing smart pointer cloning --- src/librustc/hir/lowering.rs | 4 ++-- src/libsyntax/ext/base.rs | 6 +++--- src/libsyntax_pos/hygiene.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 15184ec9d27ff..43c756def88be 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -44,6 +44,7 @@ use crate::middle::cstore::CrateStore; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; +use rustc_data_structures::sync::Lrc; use crate::session::Session; use crate::session::config::nightly_options; use crate::util::common::FN_OUTPUT_NAME; @@ -52,7 +53,6 @@ use crate::util::nodemap::{DefIdMap, NodeMap}; use std::collections::{BTreeSet, BTreeMap}; use std::fmt::Debug; use std::mem; -use std::rc::Rc; use smallvec::SmallVec; use syntax::attr; use syntax::ast; @@ -688,7 +688,7 @@ impl<'a> LoweringContext<'a> { &self, reason: CompilerDesugaringKind, span: Span, - allow_internal_unstable: Option>, + allow_internal_unstable: Option>, ) -> Span { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(source_map::ExpnInfo { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7c6303b3d404f..f7225810aca74 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -622,7 +622,7 @@ pub enum SyntaxExtension { ProcMacro { expander: Box, /// Whitelist of unstable features that are treated as stable inside this macro - allow_internal_unstable: Option>, + allow_internal_unstable: Option>, edition: Edition, }, @@ -642,7 +642,7 @@ pub enum SyntaxExtension { /// directly use `#[unstable]` things. /// /// Only allows things that require a feature gate in the given whitelist - allow_internal_unstable: Option>, + allow_internal_unstable: Option>, /// Whether the contents of the macro can use `unsafe` /// without triggering the `unsafe_code` lint. allow_internal_unsafe: bool, @@ -660,7 +660,7 @@ pub enum SyntaxExtension { IdentTT { expander: Box, span: Option, - allow_internal_unstable: Option>, + allow_internal_unstable: Option>, }, /// An attribute-like procedural macro. TokenStream -> TokenStream. diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index fb9b4c9d70e39..d5c0a2ca85f64 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -12,8 +12,8 @@ use crate::symbol::{keywords, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sync::Lrc; use std::{fmt, mem}; -use std::rc::Rc; /// A SyntaxContext represents a chain of macro expansions (represented by marks). #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] @@ -554,7 +554,7 @@ pub struct ExpnInfo { /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. - pub allow_internal_unstable: Option>, + pub allow_internal_unstable: Option>, /// Whether the macro is allowed to use `unsafe` internally /// even if the user crate has `#![forbid(unsafe_code)]`. pub allow_internal_unsafe: bool,