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 db91b07fa71..7ae57a8dc79 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 664490c1997..6b5fe84ff61 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 3de41b1665d..b01362b0ed4 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 34c77d08f5a..5d606abb3cd 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 d302e7646d1..b877c80af1a 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 0b4c8a5367c..9fca1a983c3 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 b248c6bf656..f7c7c627959 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 76b8b83031a..d1b005ffb85 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 b53d956a9c0..14312f0b2f7 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 b87257188df..506b6d4e8e0 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 5d2eb5f8e73..8207709e1f9 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 465b53184dc..02d6d721873 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 50cec9e7908..03d68f4257f 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 89d59478a5d..65500cd23bd 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 31a134b856d..549de1628eb 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 33ea675f9d1..4409bf13b6c 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 0853b4399d2..1e1b315824f 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 5b904fa86ad..91ec42a33b5 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 703c4f2db34..aa107130eee 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 2c8a996cdb0..bc86ffa852b 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 6bb7ee1d5dd..1b17fc0d040 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 670d71fe25b..dacc54d272b 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 24d09514520..f198739d104 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 832bebb6113..e2bea0c8b07 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 63417b702d5..a581c282193 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 0c645fc678c..f9394826c9b 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 70c45f7f9a7..efb21e06f34 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 cf320b2747c..ee48f951629 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 7cdf743b279..802c74239d7 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 c9ea6c338b5..ede969097d5 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 485c00ad42b..d619f1e3239 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 bea60fc012e..0a1b6acd9bf 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 0533d071de3..aa4f6648c4f 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 7cf54c3e6a6..7c79dcb7522 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 34fef33bfeb..e09a5d89172 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 4409bf13b6c..a79f3271fcb 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 1e1b315824f..08f1473200c 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 efb21e06f34..87c4d02fa4f 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 14312f0b2f7..9ff10ff851a 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 02d6d721873..ec7d0e423b4 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 65500cd23bd..2d4082386b2 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 08f1473200c..4d24c7bfb40 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 b01362b0ed4..a77c1268d22 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 2d4082386b2..d59e5ab6798 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 eab612c5dfb..2a5b687ac29 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 a661f0c78ab..af1f2910461 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 446c164965d..a8843549b8a 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 8f41680a818..9487c0cf674 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 00000000000..4f9ce20fc34 --- /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 9487c0cf674..e34fc5487cf 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 4f9ce20fc34..be048511caa 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 a77c1268d22..15184ec9d27 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 b877c80af1a..758a0d63886 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 9fca1a983c3..90b0fb249aa 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 f7c7c627959..f49b88f14e6 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 9ff10ff851a..2da520d3969 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 ec7d0e423b4..7c6303b3d40 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 03d68f4257f..6df369133d0 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 d59e5ab6798..60359531b7f 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 a79f3271fcb..cc5531c4010 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 91ec42a33b5..b9758bd655c 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 aa107130eee..f45bf034ba2 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 bc86ffa852b..fff54814a38 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 dacc54d272b..719f9a4b3fd 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 f198739d104..5730081ce01 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 e2bea0c8b07..37186246548 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 a581c282193..1ed1ab0a07b 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 f9394826c9b..fb9b4c9d70e 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 87c4d02fa4f..f0dc1b00fd9 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 2a5b687ac29..309acb25184 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 0f722945c49..ed2218f09d2 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 15184ec9d27..43c756def88 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 7c6303b3d40..f7225810aca 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 fb9b4c9d70e..d5c0a2ca85f 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,