From 45bb4097b4bb2670f93d0836d40d31bbde38aab2 Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Mon, 3 Jun 2019 22:11:57 +0100 Subject: [PATCH 01/19] Only show methods that appear in the impl block for types in the Implementors and Implementations on Foreign Types sections of trait documentation pages. --- src/librustdoc/html/render.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3555e2e7498b8..88ac5aa58d64e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3066,7 +3066,7 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<' _ => false, }; render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since(), false, Some(use_absolute), false)?; + implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?; Ok(()) } @@ -3077,7 +3077,7 @@ fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>, let did = i.trait_did().unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); render_impl(w, cx, i, assoc_link, - RenderMode::Normal, containing_item.stable_since(), true, None, false)?; + RenderMode::Normal, containing_item.stable_since(), true, None, false, true)?; } Ok(()) } @@ -3307,7 +3307,7 @@ fn item_trait( ); render_impl(w, cx, &implementor, assoc_link, RenderMode::Normal, implementor.impl_item.stable_since(), false, - None, true)?; + None, true, false)?; } write_loading_content(w, "")?; } @@ -3979,7 +3979,7 @@ fn render_assoc_items(w: &mut fmt::Formatter<'_>, }; for i in &non_trait { render_impl(w, cx, i, AssocItemLink::Anchor(None), render_mode, - containing_item.stable_since(), true, None, false)?; + containing_item.stable_since(), true, None, false, true)?; } } if let AssocItemRender::DerefFor { .. } = what { @@ -4161,7 +4161,8 @@ fn spotlight_decl(decl: &clean::FnDecl) -> Result { fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocItemLink<'_>, render_mode: RenderMode, outer_version: Option<&str>, show_def_docs: bool, - use_absolute: Option, is_on_foreign_type: bool) -> fmt::Result { + use_absolute: Option, is_on_foreign_type: bool, + show_default_items: bool) -> fmt::Result { if render_mode == RenderMode::Normal { let id = cx.derive_id(match i.inner_impl().trait_ { Some(ref t) => if is_on_foreign_type { @@ -4345,9 +4346,13 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt // If we've implemented a trait, then also emit documentation for all // default items which weren't overridden in the implementation block. - if let Some(t) = trait_ { - render_default_items(w, cx, t, &i.inner_impl(), - render_mode, outer_version, show_def_docs)?; + // We don't emit documentation for default items if they appear in the + // Implementations on Foreign Types or Implementors sections. + if show_default_items { + if let Some(t) = trait_ { + render_default_items(w, cx, t, &i.inner_impl(), + render_mode, outer_version, show_def_docs)?; + } } write!(w, "")?; From 5fa8b52835e01efc7ba7b5020a1a4dd99b3a9717 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Jun 2019 23:17:14 +0200 Subject: [PATCH 02/19] move stray run-pass const tests into const/ folder --- src/test/run-pass/{ctfe => consts}/assoc-const.rs | 0 src/test/run-pass/{ctfe => consts}/bswap-const.rs | 0 .../run-pass/{ctfe => consts}/chained-constants-stackoverflow.rs | 0 .../run-pass/{ctfe => consts}/const-block-non-item-statement-3.rs | 0 .../run-pass/{ctfe => consts}/const-block-non-item-statement.rs | 0 src/test/run-pass/{ctfe => consts}/const-fn-type-name.rs | 0 src/test/run-pass/{ => consts}/const-int-conversion.rs | 0 src/test/run-pass/{ => consts}/const-int-overflowing.rs | 0 src/test/run-pass/{ => consts}/const-int-rotate.rs | 0 src/test/run-pass/{ => consts}/const-int-saturating-arith.rs | 0 src/test/run-pass/{ => consts}/const-int-sign.rs | 0 src/test/run-pass/{ => consts}/const-int-wrapping.rs | 0 src/test/run-pass/{ => consts}/const-needs_drop.rs | 0 src/test/run-pass/{ctfe => consts}/deref_in_pattern.rs | 0 src/test/run-pass/{ctfe => consts}/ice-48279.rs | 0 src/test/run-pass/{ctfe => consts}/issue-37550.rs | 0 src/test/run-pass/{ctfe => consts}/issue-broken-mir.rs | 0 src/test/run-pass/{ctfe => consts}/locals-in-const-fn.rs | 0 src/test/run-pass/{ctfe => consts}/match-const-fn-structs.rs | 0 src/test/run-pass/{ctfe => consts}/mozjs-error.rs | 0 src/test/run-pass/{ctfe => consts}/non-scalar-cast.rs | 0 src/test/run-pass/{ctfe => consts}/promotion.rs | 0 src/test/run-pass/{ctfe => consts}/references.rs | 0 src/test/run-pass/{ctfe => consts}/repeat_match.rs | 0 src/test/run-pass/{ctfe => consts}/return-in-const-fn.rs | 0 src/test/run-pass/{ctfe => consts}/signed_enum_discr.rs | 0 src/test/run-pass/{ctfe => consts}/transmute-const.rs | 0 src/test/run-pass/{ctfe => consts}/tuple-struct-constructors.rs | 0 28 files changed, 0 insertions(+), 0 deletions(-) rename src/test/run-pass/{ctfe => consts}/assoc-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/bswap-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/chained-constants-stackoverflow.rs (100%) rename src/test/run-pass/{ctfe => consts}/const-block-non-item-statement-3.rs (100%) rename src/test/run-pass/{ctfe => consts}/const-block-non-item-statement.rs (100%) rename src/test/run-pass/{ctfe => consts}/const-fn-type-name.rs (100%) rename src/test/run-pass/{ => consts}/const-int-conversion.rs (100%) rename src/test/run-pass/{ => consts}/const-int-overflowing.rs (100%) rename src/test/run-pass/{ => consts}/const-int-rotate.rs (100%) rename src/test/run-pass/{ => consts}/const-int-saturating-arith.rs (100%) rename src/test/run-pass/{ => consts}/const-int-sign.rs (100%) rename src/test/run-pass/{ => consts}/const-int-wrapping.rs (100%) rename src/test/run-pass/{ => consts}/const-needs_drop.rs (100%) rename src/test/run-pass/{ctfe => consts}/deref_in_pattern.rs (100%) rename src/test/run-pass/{ctfe => consts}/ice-48279.rs (100%) rename src/test/run-pass/{ctfe => consts}/issue-37550.rs (100%) rename src/test/run-pass/{ctfe => consts}/issue-broken-mir.rs (100%) rename src/test/run-pass/{ctfe => consts}/locals-in-const-fn.rs (100%) rename src/test/run-pass/{ctfe => consts}/match-const-fn-structs.rs (100%) rename src/test/run-pass/{ctfe => consts}/mozjs-error.rs (100%) rename src/test/run-pass/{ctfe => consts}/non-scalar-cast.rs (100%) rename src/test/run-pass/{ctfe => consts}/promotion.rs (100%) rename src/test/run-pass/{ctfe => consts}/references.rs (100%) rename src/test/run-pass/{ctfe => consts}/repeat_match.rs (100%) rename src/test/run-pass/{ctfe => consts}/return-in-const-fn.rs (100%) rename src/test/run-pass/{ctfe => consts}/signed_enum_discr.rs (100%) rename src/test/run-pass/{ctfe => consts}/transmute-const.rs (100%) rename src/test/run-pass/{ctfe => consts}/tuple-struct-constructors.rs (100%) diff --git a/src/test/run-pass/ctfe/assoc-const.rs b/src/test/run-pass/consts/assoc-const.rs similarity index 100% rename from src/test/run-pass/ctfe/assoc-const.rs rename to src/test/run-pass/consts/assoc-const.rs diff --git a/src/test/run-pass/ctfe/bswap-const.rs b/src/test/run-pass/consts/bswap-const.rs similarity index 100% rename from src/test/run-pass/ctfe/bswap-const.rs rename to src/test/run-pass/consts/bswap-const.rs diff --git a/src/test/run-pass/ctfe/chained-constants-stackoverflow.rs b/src/test/run-pass/consts/chained-constants-stackoverflow.rs similarity index 100% rename from src/test/run-pass/ctfe/chained-constants-stackoverflow.rs rename to src/test/run-pass/consts/chained-constants-stackoverflow.rs diff --git a/src/test/run-pass/ctfe/const-block-non-item-statement-3.rs b/src/test/run-pass/consts/const-block-non-item-statement-3.rs similarity index 100% rename from src/test/run-pass/ctfe/const-block-non-item-statement-3.rs rename to src/test/run-pass/consts/const-block-non-item-statement-3.rs diff --git a/src/test/run-pass/ctfe/const-block-non-item-statement.rs b/src/test/run-pass/consts/const-block-non-item-statement.rs similarity index 100% rename from src/test/run-pass/ctfe/const-block-non-item-statement.rs rename to src/test/run-pass/consts/const-block-non-item-statement.rs diff --git a/src/test/run-pass/ctfe/const-fn-type-name.rs b/src/test/run-pass/consts/const-fn-type-name.rs similarity index 100% rename from src/test/run-pass/ctfe/const-fn-type-name.rs rename to src/test/run-pass/consts/const-fn-type-name.rs diff --git a/src/test/run-pass/const-int-conversion.rs b/src/test/run-pass/consts/const-int-conversion.rs similarity index 100% rename from src/test/run-pass/const-int-conversion.rs rename to src/test/run-pass/consts/const-int-conversion.rs diff --git a/src/test/run-pass/const-int-overflowing.rs b/src/test/run-pass/consts/const-int-overflowing.rs similarity index 100% rename from src/test/run-pass/const-int-overflowing.rs rename to src/test/run-pass/consts/const-int-overflowing.rs diff --git a/src/test/run-pass/const-int-rotate.rs b/src/test/run-pass/consts/const-int-rotate.rs similarity index 100% rename from src/test/run-pass/const-int-rotate.rs rename to src/test/run-pass/consts/const-int-rotate.rs diff --git a/src/test/run-pass/const-int-saturating-arith.rs b/src/test/run-pass/consts/const-int-saturating-arith.rs similarity index 100% rename from src/test/run-pass/const-int-saturating-arith.rs rename to src/test/run-pass/consts/const-int-saturating-arith.rs diff --git a/src/test/run-pass/const-int-sign.rs b/src/test/run-pass/consts/const-int-sign.rs similarity index 100% rename from src/test/run-pass/const-int-sign.rs rename to src/test/run-pass/consts/const-int-sign.rs diff --git a/src/test/run-pass/const-int-wrapping.rs b/src/test/run-pass/consts/const-int-wrapping.rs similarity index 100% rename from src/test/run-pass/const-int-wrapping.rs rename to src/test/run-pass/consts/const-int-wrapping.rs diff --git a/src/test/run-pass/const-needs_drop.rs b/src/test/run-pass/consts/const-needs_drop.rs similarity index 100% rename from src/test/run-pass/const-needs_drop.rs rename to src/test/run-pass/consts/const-needs_drop.rs diff --git a/src/test/run-pass/ctfe/deref_in_pattern.rs b/src/test/run-pass/consts/deref_in_pattern.rs similarity index 100% rename from src/test/run-pass/ctfe/deref_in_pattern.rs rename to src/test/run-pass/consts/deref_in_pattern.rs diff --git a/src/test/run-pass/ctfe/ice-48279.rs b/src/test/run-pass/consts/ice-48279.rs similarity index 100% rename from src/test/run-pass/ctfe/ice-48279.rs rename to src/test/run-pass/consts/ice-48279.rs diff --git a/src/test/run-pass/ctfe/issue-37550.rs b/src/test/run-pass/consts/issue-37550.rs similarity index 100% rename from src/test/run-pass/ctfe/issue-37550.rs rename to src/test/run-pass/consts/issue-37550.rs diff --git a/src/test/run-pass/ctfe/issue-broken-mir.rs b/src/test/run-pass/consts/issue-broken-mir.rs similarity index 100% rename from src/test/run-pass/ctfe/issue-broken-mir.rs rename to src/test/run-pass/consts/issue-broken-mir.rs diff --git a/src/test/run-pass/ctfe/locals-in-const-fn.rs b/src/test/run-pass/consts/locals-in-const-fn.rs similarity index 100% rename from src/test/run-pass/ctfe/locals-in-const-fn.rs rename to src/test/run-pass/consts/locals-in-const-fn.rs diff --git a/src/test/run-pass/ctfe/match-const-fn-structs.rs b/src/test/run-pass/consts/match-const-fn-structs.rs similarity index 100% rename from src/test/run-pass/ctfe/match-const-fn-structs.rs rename to src/test/run-pass/consts/match-const-fn-structs.rs diff --git a/src/test/run-pass/ctfe/mozjs-error.rs b/src/test/run-pass/consts/mozjs-error.rs similarity index 100% rename from src/test/run-pass/ctfe/mozjs-error.rs rename to src/test/run-pass/consts/mozjs-error.rs diff --git a/src/test/run-pass/ctfe/non-scalar-cast.rs b/src/test/run-pass/consts/non-scalar-cast.rs similarity index 100% rename from src/test/run-pass/ctfe/non-scalar-cast.rs rename to src/test/run-pass/consts/non-scalar-cast.rs diff --git a/src/test/run-pass/ctfe/promotion.rs b/src/test/run-pass/consts/promotion.rs similarity index 100% rename from src/test/run-pass/ctfe/promotion.rs rename to src/test/run-pass/consts/promotion.rs diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/consts/references.rs similarity index 100% rename from src/test/run-pass/ctfe/references.rs rename to src/test/run-pass/consts/references.rs diff --git a/src/test/run-pass/ctfe/repeat_match.rs b/src/test/run-pass/consts/repeat_match.rs similarity index 100% rename from src/test/run-pass/ctfe/repeat_match.rs rename to src/test/run-pass/consts/repeat_match.rs diff --git a/src/test/run-pass/ctfe/return-in-const-fn.rs b/src/test/run-pass/consts/return-in-const-fn.rs similarity index 100% rename from src/test/run-pass/ctfe/return-in-const-fn.rs rename to src/test/run-pass/consts/return-in-const-fn.rs diff --git a/src/test/run-pass/ctfe/signed_enum_discr.rs b/src/test/run-pass/consts/signed_enum_discr.rs similarity index 100% rename from src/test/run-pass/ctfe/signed_enum_discr.rs rename to src/test/run-pass/consts/signed_enum_discr.rs diff --git a/src/test/run-pass/ctfe/transmute-const.rs b/src/test/run-pass/consts/transmute-const.rs similarity index 100% rename from src/test/run-pass/ctfe/transmute-const.rs rename to src/test/run-pass/consts/transmute-const.rs diff --git a/src/test/run-pass/ctfe/tuple-struct-constructors.rs b/src/test/run-pass/consts/tuple-struct-constructors.rs similarity index 100% rename from src/test/run-pass/ctfe/tuple-struct-constructors.rs rename to src/test/run-pass/consts/tuple-struct-constructors.rs From ea1bec3a8afbc79c8c1a5b989e1c3d2425400040 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 14 Jun 2019 09:53:59 -0700 Subject: [PATCH 03/19] Turn down the myriad-closures test This tests takes nearly 5 minutes to compile on CI where the CPUs we have aren't exactly the fastest. This test does actually require all closures to exist to exhibit the original bug, but it seems a little excessive to test a single bug on CI on all platforms which simply pegs a single CPU for 5 minutes with no parallelism opportunities, so this turns down the test to still exercise it somewhat at least. --- src/test/run-pass-fulldeps/myriad-closures.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/run-pass-fulldeps/myriad-closures.rs b/src/test/run-pass-fulldeps/myriad-closures.rs index a1ea0e685d659..a6d3530f13902 100644 --- a/src/test/run-pass-fulldeps/myriad-closures.rs +++ b/src/test/run-pass-fulldeps/myriad-closures.rs @@ -32,7 +32,7 @@ macro_rules! mk_fn { } fn main() { - // Make 2^12 functions, each containing 16 closures, - // resulting in 2^16 closures overall. - go_bacterial!(mk_fn 1 1 1 1 1 1 1 1 1 1 1 1); + // Make 2^8 functions, each containing 16 closures, + // resulting in 2^12 closures overall. + go_bacterial!(mk_fn 1 1 1 1 1 1 1 1); } From 007aabae930d753742f6916d91d3fc8838db08a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 14 Jun 2019 18:09:57 +0200 Subject: [PATCH 04/19] Remove unnecessary lift calls --- src/librustc/infer/canonical/canonicalizer.rs | 30 +++++-------------- src/librustc/infer/canonical/mod.rs | 4 +-- .../infer/canonical/query_response.rs | 16 +++++----- src/librustc/infer/opaque_types/mod.rs | 5 ---- src/librustc/middle/mem_categorization.rs | 5 +--- src/librustc/traits/codegen/mod.rs | 10 ++----- src/librustc/traits/project.rs | 1 - src/librustc/traits/query/normalize.rs | 1 - src/librustc/traits/query/type_op/mod.rs | 6 ++-- .../traits/query/type_op/normalize.rs | 2 +- src/librustc/traits/specialize/mod.rs | 7 +---- src/librustc/ty/error.rs | 9 ++++-- src/librustc/ty/sty.rs | 13 ++++---- src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/nll/region_infer/mod.rs | 4 +-- .../borrow_check/nll/type_check/mod.rs | 4 +-- src/librustc_mir/build/expr/as_rvalue.rs | 4 +-- .../dataflow/drop_flag_effects.rs | 2 +- src/librustc_mir/hair/constant.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 7 +---- src/librustc_mir/hair/pattern/_match.rs | 2 +- .../normalize_erasing_regions.rs | 3 +- 22 files changed, 50 insertions(+), 89 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index b4779eec65f4c..a156075b81271 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -14,7 +14,7 @@ use crate::mir::interpret::ConstValue; use std::sync::atomic::Ordering; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::Kind; -use crate::ty::{self, BoundVar, InferConst, Lift, List, Ty, TyCtxt, TypeFlags}; +use crate::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags}; use crate::ty::flags::FlagComputation; use rustc_data_structures::fx::FxHashMap; @@ -43,7 +43,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { query_state: &mut OriginalQueryValues<'tcx>, ) -> Canonicalized<'tcx, V> where - V: TypeFoldable<'tcx> + Lift<'tcx>, + V: TypeFoldable<'tcx>, { self.tcx .sess @@ -87,7 +87,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result pub fn canonicalize_response(&self, value: &V) -> Canonicalized<'tcx, V> where - V: TypeFoldable<'tcx> + Lift<'tcx>, + V: TypeFoldable<'tcx>, { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( @@ -101,7 +101,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn canonicalize_user_type_annotation(&self, value: &V) -> Canonicalized<'tcx, V> where - V: TypeFoldable<'tcx> + Lift<'tcx>, + V: TypeFoldable<'tcx>, { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( @@ -132,7 +132,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { query_state: &mut OriginalQueryValues<'tcx>, ) -> Canonicalized<'tcx, V> where - V: TypeFoldable<'tcx> + Lift<'tcx>, + V: TypeFoldable<'tcx>, { self.tcx .sess @@ -506,7 +506,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { query_state: &mut OriginalQueryValues<'tcx>, ) -> Canonicalized<'tcx, V> where - V: TypeFoldable<'tcx> + Lift<'tcx>, + V: TypeFoldable<'tcx>, { let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::KEEP_IN_LOCAL_TCX | @@ -520,20 +520,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { TypeFlags::HAS_CT_PLACEHOLDER }; - let gcx = tcx.global_tcx(); - // Fast path: nothing that needs to be canonicalized. if !value.has_type_flags(needs_canonical_flags) { - let out_value = gcx.lift(value).unwrap_or_else(|| { - bug!( - "failed to lift `{:?}` (nothing to canonicalize)", - value - ) - }); let canon_value = Canonical { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), - value: out_value, + value: value.clone(), }; return canon_value; } @@ -553,13 +545,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { // Once we have canonicalized `out_value`, it should not // contain anything that ties it to this inference context // anymore, so it should live in the global arena. - let out_value = gcx.lift(&out_value).unwrap_or_else(|| { - bug!( - "failed to lift `{:?}`, canonicalized from `{:?}`", - out_value, - value - ) - }); + debug_assert!(!out_value.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX)); let canonical_variables = tcx.intern_canonical_var_infos(&canonicalizer.variables); diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 8b1c34a487f5c..b2c7bd73b6812 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -194,10 +194,10 @@ pub struct QueryResponse<'tcx, R> { pub value: R, } -pub type Canonicalized<'tcx, V> = Canonical<'tcx, >::Lifted>; +pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>; pub type CanonicalizedQueryResponse<'tcx, T> = - &'tcx Canonical<'tcx, QueryResponse<'tcx, >::Lifted>>; + &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>; /// Indicates whether or not we were able to prove the query to be /// true. diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8b11ebf9b924b..3e92fed005cd1 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -26,7 +26,7 @@ use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::ty::fold::TypeFoldable; use crate::ty::subst::{Kind, UnpackedKind}; -use crate::ty::{self, BoundVar, InferConst, Lift, Ty, TyCtxt}; +use crate::ty::{self, BoundVar, InferConst, Ty, TyCtxt}; use crate::util::captures::Captures; impl<'tcx> InferCtxtBuilder<'tcx> { @@ -53,8 +53,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> { ) -> Fallible> where K: TypeFoldable<'tcx>, - R: Debug + Lift<'tcx> + TypeFoldable<'tcx>, - Canonical<'tcx, as Lift<'tcx>>::Lifted>: ArenaAllocatable, + R: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable, { self.enter_with_canonical( DUMMY_SP, @@ -99,8 +99,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Fallible> where - T: Debug + Lift<'tcx> + TypeFoldable<'tcx>, - Canonical<'tcx, as Lift<'tcx>>::Lifted>: ArenaAllocatable, + T: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable, { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; let canonical_result = self.canonicalize_response(&query_response); @@ -126,9 +126,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { &self, inference_vars: CanonicalVarValues<'tcx>, answer: T, - ) -> Canonical<'tcx, QueryResponse<'tcx, >::Lifted>> + ) -> Canonical<'tcx, QueryResponse<'tcx, T>> where - T: Debug + Lift<'tcx> + TypeFoldable<'tcx>, + T: Debug + TypeFoldable<'tcx>, { self.canonicalize_response(&QueryResponse { var_values: inference_vars, @@ -147,7 +147,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result, NoSolution> where - T: Debug + TypeFoldable<'tcx> + Lift<'tcx>, + T: Debug + TypeFoldable<'tcx>, { let tcx = self.tcx; diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 8e9af8b39385f..7b7a9cba76e63 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -469,11 +469,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { definition_ty ); - // We can unwrap here because our reverse mapper always - // produces things with 'tcx lifetime, though the type folder - // obscures that. - let definition_ty = gcx.lift(&definition_ty).unwrap(); - definition_ty } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3b21b81df7b43..0304f76ec96e9 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -819,10 +819,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { .unwrap_or(ty::ClosureKind::LATTICE_BOTTOM), None => - self.tcx.global_tcx() - .lift(&closure_substs) - .expect("no inference cx, but inference variables in closure ty") - .closure_kind(closure_def_id, self.tcx.global_tcx()), + closure_substs.closure_kind(closure_def_id, self.tcx.global_tcx()), } } _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty), diff --git a/src/librustc/traits/codegen/mod.rs b/src/librustc/traits/codegen/mod.rs index bb4095333f19d..97fb430a3e051 100644 --- a/src/librustc/traits/codegen/mod.rs +++ b/src/librustc/traits/codegen/mod.rs @@ -141,9 +141,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, fulfill_cx: &mut FulfillmentContext<'tcx>, result: &T, - ) -> T::Lifted + ) -> T where - T: TypeFoldable<'tcx> + ty::Lift<'tcx>, + T: TypeFoldable<'tcx>, { debug!("drain_fulfillment_cx_or_panic()"); @@ -155,10 +155,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let result = self.resolve_vars_if_possible(result); - let result = self.tcx.erase_regions(&result); - - self.tcx.lift_to_global(&result).unwrap_or_else(|| - bug!("Uninferred types/regions/consts in `{:?}`", result) - ) + self.tcx.erase_regions(&result) } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index d189bb231163e..d6d0d12b2ba6a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -409,7 +409,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); return evaluated; } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 50476721e8247..1b82c412e982e 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -203,7 +203,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); return evaluated; } diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs index b298edfec5944..4a07a3120f3e8 100644 --- a/src/librustc/traits/query/type_op/mod.rs +++ b/src/librustc/traits/query/type_op/mod.rs @@ -8,7 +8,7 @@ use std::rc::Rc; use crate::traits::query::Fallible; use crate::traits::ObligationCause; use crate::ty::fold::TypeFoldable; -use crate::ty::{Lift, ParamEnvAnd, TyCtxt}; +use crate::ty::{ParamEnvAnd, TyCtxt}; pub mod ascribe_user_type; pub mod custom; @@ -44,8 +44,8 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug { /// which produces the resulting query region constraints. /// /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html -pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'tcx> { - type QueryResponse: TypeFoldable<'tcx> + Lift<'tcx>; +pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { + type QueryResponse: TypeFoldable<'tcx>; /// Give query the option for a simple fast path that never /// actually hits the tcx cache lookup etc. Return `Some(r)` with diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs index 5a768d9d58fcd..3fe85d8d83eb9 100644 --- a/src/librustc/traits/query/type_op/normalize.rs +++ b/src/librustc/traits/query/type_op/normalize.rs @@ -20,7 +20,7 @@ where impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize where - T: Normalizable<'tcx>, + T: Normalizable<'tcx> + 'tcx, { type QueryResponse = T; diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 3d47e94fb007c..43bb4edd9b27d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -132,12 +132,7 @@ pub fn find_associated_item<'tcx>( let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, substs, node_item.node); - let substs = infcx.tcx.erase_regions(&substs); - tcx.lift(&substs).unwrap_or_else(|| - bug!("find_method: translate_substs \ - returned {:?} which contains inference types/regions", - substs) - ) + infcx.tcx.erase_regions(&substs) }); (node_item.item.def_id, substs) } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index d5e0450035038..b8bdde4a78738 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -192,9 +192,12 @@ impl<'tcx> ty::TyS<'tcx> { ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(), ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(), - ty::Array(_, n) => match n.assert_usize(tcx) { - Some(n) => format!("array of {} elements", n).into(), - None => "array".into(), + ty::Array(_, n) => { + let n = tcx.lift_to_global(&n).unwrap(); + match n.assert_usize(tcx) { + Some(n) => format!("array of {} elements", n).into(), + None => "array".into(), + } } ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "*-ptr".into(), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 810a26d373648..8bfbd8b854b03 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2262,7 +2262,6 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self { - let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).unwrap_or_else(|e| { panic!("could not compute layout for {:?}: {:?}", ty, e) }).size; @@ -2289,7 +2288,6 @@ impl<'tcx> Const<'tcx> { if self.ty != ty.value { return None; } - let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).ok()?.size; self.val.try_to_bits(size) } @@ -2300,15 +2298,14 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn assert_bits(&self, tcx: TyCtxt<'_>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option { + pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option { assert_eq!(self.ty, ty.value); - let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).ok()?.size; self.val.try_to_bits(size) } #[inline] - pub fn assert_bool(&self, tcx: TyCtxt<'_>) -> Option { + pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option { self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.bool)).and_then(|v| match v { 0 => Some(false), 1 => Some(true), @@ -2317,18 +2314,18 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn assert_usize(&self, tcx: TyCtxt<'_>) -> Option { + pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option { self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.usize)).map(|v| v as u64) } #[inline] - pub fn unwrap_bits(&self, tcx: TyCtxt<'_>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { + pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 { self.assert_bits(tcx, ty).unwrap_or_else(|| bug!("expected bits of {}, got {:#?}", ty.value, self)) } #[inline] - pub fn unwrap_usize(&self, tcx: TyCtxt<'_>) -> u64 { + pub fn unwrap_usize(&self, tcx: TyCtxt<'tcx>) -> u64 { self.assert_usize(tcx).unwrap_or_else(|| bug!("expected constant usize, got {:#?}", self)) } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 161a08c5773e7..b05e291710a48 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -670,7 +670,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx // "Lift" into the gcx -- once regions are erased, this type should be in the // global arenas; this "lift" operation basically just asserts that is true, but // that is useful later. - let drop_place_ty = gcx.lift(&drop_place_ty).unwrap(); + gcx.lift_to_global(&drop_place_ty).unwrap(); debug!("visit_terminator_drop \ loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 2b38fcee47960..41ed564d0f0e1 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -863,8 +863,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); debug!("try_promote_type_test_subject: folded ty = {:?}", ty); - // `lift` will only fail if we failed to promote some region. - let ty = gcx.lift(&ty)?; + // `lift_to_global` will only fail if we failed to promote some region. + gcx.lift_to_global(&ty)?; Some(ClosureOutlivesSubject::Ty(ty)) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 77e0b54781c94..9d33b371d9b55 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1866,7 +1866,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. let gcx = tcx.global_tcx(); - let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap(); + let erased_ty = tcx.erase_regions(&ty); if !erased_ty.is_sized(gcx.at(span), self.param_env) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return @@ -2652,7 +2652,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn normalize(&mut self, value: T, location: impl NormalizeLocation) -> T where - T: type_op::normalize::Normalizable<'tcx> + Copy, + T: type_op::normalize::Normalizable<'tcx> + Copy + 'tcx, { debug!("normalize(value={:?}, location={:?})", value, location); let param_env = self.param_env; diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 6d6e5de4761ab..243c13c2982d0 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -569,7 +569,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap()); + let param_ty = ty::ParamEnv::empty().and(ty); let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); let n = (!0u128) >> (128 - bits); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); @@ -580,7 +580,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get the minimum value of the appropriate type fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { assert!(ty.is_signed()); - let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap()); + let param_ty = ty::ParamEnv::empty().and(ty); let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); let n = 1 << (bits - 1); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index e8a32477f1c3f..37f2a91578249 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -151,7 +151,7 @@ pub(crate) fn on_all_drop_children_bits<'tcx, F>( debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty); let gcx = tcx.global_tcx(); - let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap(); + let erased_ty = tcx.erase_regions(&ty); if erased_ty.needs_drop(gcx, ctxt.param_env) { each_child(child); } else { diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index 2cd04631118d1..bc01e3ee95b97 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -18,7 +18,7 @@ crate fn lit_to_const<'tcx>( use syntax::ast::*; let trunc = |n| { - let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap()); + let param_ty = ParamEnv::reveal_all().and(ty); let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = truncate(n, width); diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 7740042c783fc..1eb5ab0776a30 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -191,12 +191,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { } pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool { - let (ty, param_env) = self.tcx.lift_to_global(&(ty, self.param_env)).unwrap_or_else(|| { - bug!("MIR: Cx::needs_drop({:?}, {:?}) got \ - type with inference types/regions", - ty, self.param_env); - }); - ty.needs_drop(self.tcx.global_tcx(), param_env) + ty.needs_drop(self.tcx.global_tcx(), self.param_env) } pub fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 1d7c450f69506..9349e08b7d046 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1311,7 +1311,7 @@ fn is_useful_specialized<'p, 'a: 'p, 'tcx: 'a>( /// Returns `None` in case of a catch-all, which can't be specialized. fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, pat: &Pattern<'tcx>, - pcx: PatternContext<'_>) + pcx: PatternContext<'tcx>) -> Option>> { match *pat.kind { diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index bfa1a80bb320f..d138ce753b07e 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -37,8 +37,7 @@ fn normalize_ty_after_erasing_regions<'tcx>( ); let normalized_value = infcx.resolve_vars_if_possible(&normalized_value); - let normalized_value = infcx.tcx.erase_regions(&normalized_value); - tcx.lift_to_global(&normalized_value).unwrap() + infcx.tcx.erase_regions(&normalized_value) } Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), } From 56e30e1f3f953f3b8b88f46e32a2ec1f5573943c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2019 13:28:22 -0700 Subject: [PATCH 05/19] Tweak transparent enums and unions diagnostic spans --- src/librustc_typeck/check/mod.rs | 68 +++++++++----- .../feature-gate-transparent_enums.stderr | 6 +- .../feature-gate-transparent_unions.stderr | 7 +- src/test/ui/repr/repr-transparent.stderr | 94 +++++++------------ 4 files changed, 83 insertions(+), 92 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c857eac5d3c18..5b51c02b812e0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1794,25 +1794,39 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) { if !adt.repr.transparent() { return; } + let sp = tcx.sess.source_map().def_span(sp); if adt.is_enum() { if !tcx.features().transparent_enums { - emit_feature_err(&tcx.sess.parse_sess, - sym::transparent_enums, - sp, - GateIssue::Language, - "transparent enums are unstable"); + emit_feature_err( + &tcx.sess.parse_sess, + sym::transparent_enums, + sp, + GateIssue::Language, + "transparent enums are unstable", + ); } if adt.variants.len() != 1 { let variant_spans: Vec<_> = adt.variants.iter().map(|variant| { tcx.hir().span_if_local(variant.def_id).unwrap() }).collect(); - let mut err = struct_span_err!(tcx.sess, sp, E0731, - "transparent enum needs exactly one variant, but has {}", - adt.variants.len()); - if !variant_spans.is_empty() { - err.span_note(variant_spans, &format!("the following variants exist on `{}`", - tcx.def_path_str(def_id))); + let msg = format!( + "needs exactly one variant, but has {}", + adt.variants.len(), + ); + let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); + err.span_label(sp, &msg); + match &variant_spans[..] { + &[] => {}, + &[ref start.., ref end] => { + for variant_span in start { + err.span_label(*variant_span, ""); + } + err.span_label(*end, &format!( + "too many variants in `{}`", + tcx.def_path_str(def_id), + )); + }, } err.emit(); if adt.variants.is_empty() { @@ -1847,23 +1861,31 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) { if non_zst_count != 1 { let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect(); - let mut err = struct_span_err!(tcx.sess, sp, E0690, - "{}transparent {} needs exactly one non-zero-sized field, but has {}", - if adt.is_enum() { "the variant of a " } else { "" }, - adt.descr(), - non_zst_count); - if !field_spans.is_empty() { - err.span_note(field_spans, - &format!("the following non-zero-sized fields exist on `{}`:", - tcx.def_path_str(def_id))); + let msg = format!("needs exactly one non-zero-sized field, but has {}", non_zst_count); + let mut err = struct_span_err!( + tcx.sess, + sp, + E0690, + "{}transparent {} {}", + if adt.is_enum() { "the variant of a " } else { "" }, + adt.descr(), + msg, + ); + err.span_label(sp, &msg); + for sp in &field_spans { + err.span_label(*sp, "this field is non-zero-sized"); } err.emit(); } for (span, zst, align1) in field_infos { if zst && !align1 { - span_err!(tcx.sess, span, E0691, - "zero-sized field in transparent {} has alignment larger than 1", - adt.descr()); + struct_span_err!( + tcx.sess, + span, + E0691, + "zero-sized field in transparent {} has alignment larger than 1", + adt.descr(), + ).span_label(span, "has alignment larger than 1").emit(); } } } diff --git a/src/test/ui/feature-gates/feature-gate-transparent_enums.stderr b/src/test/ui/feature-gates/feature-gate-transparent_enums.stderr index 4b22654e9e411..8ba079b89f509 100644 --- a/src/test/ui/feature-gates/feature-gate-transparent_enums.stderr +++ b/src/test/ui/feature-gates/feature-gate-transparent_enums.stderr @@ -1,10 +1,8 @@ error[E0658]: transparent enums are unstable --> $DIR/feature-gate-transparent_enums.rs:2:1 | -LL | / enum OkButUnstableEnum { -LL | | Foo((), String, ()), -LL | | } - | |_^ +LL | enum OkButUnstableEnum { + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/60405 = help: add #![feature(transparent_enums)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-transparent_unions.stderr b/src/test/ui/feature-gates/feature-gate-transparent_unions.stderr index 933b227de63b9..341324c3d6764 100644 --- a/src/test/ui/feature-gates/feature-gate-transparent_unions.stderr +++ b/src/test/ui/feature-gates/feature-gate-transparent_unions.stderr @@ -1,11 +1,8 @@ error[E0658]: transparent unions are unstable --> $DIR/feature-gate-transparent_unions.rs:2:1 | -LL | / union OkButUnstableUnion { -LL | | field: u8, -LL | | zst: (), -LL | | } - | |_^ +LL | union OkButUnstableUnion { + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/60405 = help: add #![feature(transparent_unions)] to the crate attributes to enable diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index ea16bdf53783d..f0c1fbe8ac9e1 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -2,61 +2,57 @@ error[E0690]: transparent struct needs exactly one non-zero-sized field, but has --> $DIR/repr-transparent.rs:11:1 | LL | struct NoFields; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:14:1 | LL | struct ContainsOnlyZst(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:17:1 | LL | struct ContainsOnlyZstArray([bool; 0]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:20:1 | LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2 --> $DIR/repr-transparent.rs:24:1 | LL | struct MultipleNonZst(u8, u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: the following non-zero-sized fields exist on `MultipleNonZst`: - --> $DIR/repr-transparent.rs:24:23 - | -LL | struct MultipleNonZst(u8, u8); - | ^^ ^^ + | ^^^^^^^^^^^^^^^^^^^^^^--^^--^^ + | | | | + | | | this field is non-zero-sized + | | this field is non-zero-sized + | needs exactly one non-zero-sized field, but has 2 error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2 --> $DIR/repr-transparent.rs:30:1 | LL | pub struct StructWithProjection(f32, ::It); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: the following non-zero-sized fields exist on `StructWithProjection`: - --> $DIR/repr-transparent.rs:30:33 - | -LL | pub struct StructWithProjection(f32, ::It); - | ^^^ ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^ + | | | | + | | | this field is non-zero-sized + | | this field is non-zero-sized + | needs exactly one non-zero-sized field, but has 2 error[E0691]: zero-sized field in transparent struct has alignment larger than 1 --> $DIR/repr-transparent.rs:34:32 | LL | struct NontrivialAlignZst(u32, [u16; 0]); - | ^^^^^^^^ + | ^^^^^^^^ has alignment larger than 1 error[E0691]: zero-sized field in transparent struct has alignment larger than 1 --> $DIR/repr-transparent.rs:40:24 | LL | struct GenericAlign(ZstAlign32, u32); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ has alignment larger than 1 error[E0084]: unsupported representation for zero-variant enum --> $DIR/repr-transparent.rs:42:1 @@ -70,71 +66,49 @@ error[E0731]: transparent enum needs exactly one variant, but has 0 --> $DIR/repr-transparent.rs:43:1 | LL | enum Void {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^ needs exactly one variant, but has 0 error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:47:1 | -LL | / enum FieldlessEnum { -LL | | Foo, -LL | | } - | |_^ +LL | enum FieldlessEnum { + | ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2 --> $DIR/repr-transparent.rs:52:1 | -LL | / enum TooManyFieldsEnum { -LL | | Foo(u32, String), -LL | | } - | |_^ - | -note: the following non-zero-sized fields exist on `TooManyFieldsEnum`: - --> $DIR/repr-transparent.rs:53:9 - | +LL | enum TooManyFieldsEnum { + | ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 LL | Foo(u32, String), - | ^^^ ^^^^^^ + | --- ------ this field is non-zero-sized + | | + | this field is non-zero-sized error[E0731]: transparent enum needs exactly one variant, but has 2 --> $DIR/repr-transparent.rs:58:1 | -LL | / enum TooManyVariants { -LL | | Foo(String), -LL | | Bar, -LL | | } - | |_^ - | -note: the following variants exist on `TooManyVariants` - --> $DIR/repr-transparent.rs:59:5 - | +LL | enum TooManyVariants { + | ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 LL | Foo(String), - | ^^^^^^^^^^^ + | ----------- LL | Bar, - | ^^^ + | --- too many variants in `TooManyVariants` error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0 --> $DIR/repr-transparent.rs:64:1 | -LL | / union UnitUnion { -LL | | u: (), -LL | | } - | |_^ +LL | union UnitUnion { + | ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2 --> $DIR/repr-transparent.rs:69:1 | -LL | / union TooManyFields { -LL | | u: u32, -LL | | s: i32 -LL | | } - | |_^ - | -note: the following non-zero-sized fields exist on `TooManyFields`: - --> $DIR/repr-transparent.rs:70:5 - | +LL | union TooManyFields { + | ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 LL | u: u32, - | ^^^^^^ + | ------ this field is non-zero-sized LL | s: i32 - | ^^^^^^ + | ------ this field is non-zero-sized error: aborting due to 15 previous errors From f06b76122cde7ddd4f6778d77952b63baa70bdfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Jun 2019 18:21:53 -0700 Subject: [PATCH 06/19] review comments: move diagnostic code out of happy path --- src/librustc_typeck/check/mod.rs | 93 ++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b51c02b812e0..2cb955c7c2ef0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1789,6 +1789,52 @@ fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) { + let variant_spans: Vec<_> = adt.variants.iter().map(|variant| { + tcx.hir().span_if_local(variant.def_id).unwrap() + }).collect(); + let msg = format!( + "needs exactly one variant, but has {}", + adt.variants.len(), + ); + let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); + err.span_label(sp, &msg); + if let &[ref start.., ref end] = &variant_spans[..] { + for variant_span in start { + err.span_label(*variant_span, ""); + } + err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did))); + } + err.emit(); +} + +/// Emit an error when encountering more or less than one non-zero-sized field in a transparent +/// enum. +fn bad_non_zero_sized_fields<'tcx>( + tcx: TyCtxt<'tcx>, + adt: &'tcx ty::AdtDef, + field_count: usize, + field_spans: impl Iterator, + sp: Span, +) { + let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count); + let mut err = struct_span_err!( + tcx.sess, + sp, + E0690, + "{}transparent {} {}", + if adt.is_enum() { "the variant of a " } else { "" }, + adt.descr(), + msg, + ); + err.span_label(sp, &msg); + for sp in field_spans { + err.span_label(sp, "this field is non-zero-sized"); + } + err.emit(); +} + fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) { let adt = tcx.adt_def(def_id); if !adt.repr.transparent() { @@ -1807,28 +1853,7 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) { ); } if adt.variants.len() != 1 { - let variant_spans: Vec<_> = adt.variants.iter().map(|variant| { - tcx.hir().span_if_local(variant.def_id).unwrap() - }).collect(); - let msg = format!( - "needs exactly one variant, but has {}", - adt.variants.len(), - ); - let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); - err.span_label(sp, &msg); - match &variant_spans[..] { - &[] => {}, - &[ref start.., ref end] => { - for variant_span in start { - err.span_label(*variant_span, ""); - } - err.span_label(*end, &format!( - "too many variants in `{}`", - tcx.def_path_str(def_id), - )); - }, - } - err.emit(); + bad_variant_count(tcx, adt, sp, def_id); if adt.variants.is_empty() { // Don't bother checking the fields. No variants (and thus no fields) exist. return; @@ -1856,26 +1881,14 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) { (span, zst, align1) }); - let non_zst_fields = field_infos.clone().filter(|(_span, zst, _align1)| !*zst); + let non_zst_fields = field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { + Some(span) + } else { + None + }); let non_zst_count = non_zst_fields.clone().count(); if non_zst_count != 1 { - let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect(); - - let msg = format!("needs exactly one non-zero-sized field, but has {}", non_zst_count); - let mut err = struct_span_err!( - tcx.sess, - sp, - E0690, - "{}transparent {} {}", - if adt.is_enum() { "the variant of a " } else { "" }, - adt.descr(), - msg, - ); - err.span_label(sp, &msg); - for sp in &field_spans { - err.span_label(*sp, "this field is non-zero-sized"); - } - err.emit(); + bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp); } for (span, zst, align1) in field_infos { if zst && !align1 { From 961ba8f9efbb51d80e7e73a609f6587c0ffa0623 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Jun 2019 18:58:39 +0300 Subject: [PATCH 07/19] syntax: Factor out common fields from `SyntaxExtension` variants --- .../src/language-features/plugin.md | 2 +- src/librustc_allocator/expand.rs | 2 +- src/librustc_metadata/creader.rs | 50 +++-- src/librustc_metadata/cstore_impl.rs | 13 +- src/librustc_metadata/decoder.rs | 7 +- src/librustc_plugin/registry.rs | 22 +-- src/librustc_resolve/build_reduced_graph.rs | 11 +- src/librustc_resolve/macros.rs | 32 ++-- src/librustdoc/clean/inline.rs | 12 +- .../passes/collect_intra_doc_links.rs | 4 +- src/libsyntax/ext/base.rs | 148 +++++++++------ src/libsyntax/ext/derive.rs | 2 +- src/libsyntax/ext/expand.rs | 178 +++++------------- src/libsyntax/ext/tt/macro_rules.rs | 12 +- src/libsyntax/std_inject.rs | 2 +- src/libsyntax/test.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 21 ++- src/libsyntax_ext/lib.rs | 69 +++---- src/libsyntax_ext/proc_macro_decls.rs | 7 +- src/libsyntax_ext/test.rs | 2 +- src/libsyntax_ext/test_case.rs | 2 +- .../auxiliary/plugin-args.rs | 18 +- 22 files changed, 269 insertions(+), 349 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 1994cf491889b..0e38e2865d893 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -132,7 +132,7 @@ The advantages over a simple `fn(&str) -> u32` are: In addition to procedural macros, you can define new [`derive`](../../reference/attributes/derive.md)-like attributes and other kinds of extensions. See `Registry::register_syntax_extension` and the -`SyntaxExtension` enum. For a more involved macro example, see +`SyntaxExtension` struct. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 3ec06b17aff22..ecc165ca5ea9f 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -91,7 +91,7 @@ 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: Some(vec![sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: self.sess.edition, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5fef8e53e1d0c..d3d00fa4adcfe 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -26,7 +26,7 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; -use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::symbol::{Symbol, sym}; use syntax::visit; use syntax::{span_err, span_fatal}; @@ -611,33 +611,31 @@ impl<'a> CrateLoader<'a> { }; let extensions = decls.iter().map(|&decl| { - match decl { + let (name, kind, helper_attrs) = match decl { ProcMacro::CustomDerive { trait_name, attributes, client } => { - let attrs = attributes.iter().cloned().map(Symbol::intern).collect::>(); - (trait_name, SyntaxExtension::Derive( - Box::new(ProcMacroDerive { - client, - attrs: attrs.clone(), - }), - attrs, - root.edition, - )) + let helper_attrs = + attributes.iter().cloned().map(Symbol::intern).collect::>(); + ( + trait_name, + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { + client, attrs: helper_attrs.clone() + })), + helper_attrs, + ) } - ProcMacro::Attr { name, client } => { - (name, SyntaxExtension::Attr( - Box::new(AttrProcMacro { client }), - root.edition, - )) - } - ProcMacro::Bang { name, client } => { - (name, SyntaxExtension::Bang { - expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: None, - edition: root.edition, - }) - } - } - }).map(|(name, ext)| (Symbol::intern(name), Lrc::new(ext))).collect(); + ProcMacro::Attr { name, client } => ( + name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() + ), + ProcMacro::Bang { name, client } => ( + name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() + ) + }; + + (Symbol::intern(name), Lrc::new(SyntaxExtension { + helper_attrs, + ..SyntaxExtension::default(kind, root.edition) + })) + }).collect(); // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 86536b179f222..04a9c4e9a1a11 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -30,9 +30,11 @@ use syntax::ast; use syntax::attr; use syntax::source_map; use syntax::edition::Edition; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; use syntax::symbol::{Symbol, sym}; +use syntax_ext::proc_macro_impl::BangProcMacro; use syntax_pos::{Span, NO_EXPANSION, FileName}; use rustc_data_structures::bit_set::BitSet; @@ -427,14 +429,11 @@ impl cstore::CStore { if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { - use syntax::ext::base::SyntaxExtension; - use syntax_ext::proc_macro_impl::BangProcMacro; - let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - let ext = SyntaxExtension::Bang { - expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()), - edition: data.root.edition, + let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })); + let ext = SyntaxExtension { + allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()), + ..SyntaxExtension::default(kind, data.root.edition) }; return LoadedMacro::ProcMacro(Lrc::new(ext)); } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 4bafe16b8e66d..a776966bda489 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -511,8 +511,9 @@ impl<'a, 'tcx> CrateMetadata { if !self.is_proc_macro(index) { self.entry(index).kind.def_kind() } else { - let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind(); - Some(DefKind::Macro(kind)) + Some(DefKind::Macro( + self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind() + )) } } @@ -739,7 +740,7 @@ impl<'a, 'tcx> CrateMetadata { if id == CRATE_DEF_INDEX { for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { let res = Res::Def( - DefKind::Macro(ext.kind()), + DefKind::Macro(ext.macro_kind()), self.local_def_id(DefIndex::from_proc_macro_index(id)), ); let ident = Ident::with_empty_ctxt(name); diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index dd5e42684c427..16d484e2a98f2 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -4,9 +4,8 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension}; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; use syntax::ext::base::MacroExpanderFn; -use syntax::ext::hygiene::Transparency; use syntax::symbol::{Symbol, sym}; use syntax::ast; use syntax::feature_gate::AttributeType; @@ -89,8 +88,8 @@ impl<'a> Registry<'a> { if name == sym::macro_rules { panic!("user-defined macros may not be named `macro_rules`"); } - if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension { - *def_info = Some((ast::CRATE_NODE_ID, self.krate_span)); + if extension.def_info.is_none() { + extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span)); } self.syntax_exts.push((name, extension)); } @@ -98,19 +97,12 @@ impl<'a> Registry<'a> { /// Register a macro of the usual kind. /// /// This is a convenience wrapper for `register_syntax_extension`. - /// It builds for you a `SyntaxExtension::LegacyBang` that calls `expander`, + /// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`, /// and also takes care of interning the macro's name. pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) { - self.register_syntax_extension(Symbol::intern(name), SyntaxExtension::LegacyBang { - expander: Box::new(expander), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition: self.sess.edition(), - }); + let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander)); + let ext = SyntaxExtension::default(kind, self.sess.edition()); + self.register_syntax_extension(Symbol::intern(name), ext); } /// Register a compiler lint pass. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e3cd2948d7af5..bb4edf355f8b5 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -29,7 +29,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -772,9 +772,12 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, res: Res) -> Lrc { let def_id = match res { Res::Def(DefKind::Macro(..), def_id) => def_id, - Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool, - }), + Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::default( + SyntaxExtensionKind::NonMacroAttr { + mark_used: attr_kind == NonMacroAttrKind::Tool + }, + self.session.edition(), + )), _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"), }; if let Some(ext) = self.macro_map.get(&def_id) { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2369bddf4f75f..89e28330be7e3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -174,7 +174,7 @@ impl<'a> base::Resolver for Resolver<'a> { krate: CrateNum::BuiltinMacros, index: DefIndex::from(self.macro_map.len()), }; - let kind = ext.kind(); + let kind = ext.macro_kind(); self.macro_map.insert(def_id, ext); let binding = self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false), @@ -211,7 +211,8 @@ impl<'a> base::Resolver for Resolver<'a> { Ok((res, ext)) => (res, ext), Err(Determinacy::Determined) if kind == MacroKind::Attr => { // Replace unresolved attributes with used inert attributes for better recovery. - return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true }))); + let kind = SyntaxExtensionKind::NonMacroAttr { mark_used: true }; + return Ok(Some(Lrc::new(SyntaxExtension::default(kind, self.session.edition())))); } Err(determinacy) => return Err(determinacy), }; @@ -226,7 +227,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); + invoc.expansion_data.mark.set_default_transparency(ext.default_transparency); } Ok(Some(ext)) @@ -241,11 +242,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn check_unused_macros(&self) { for did in self.unused_macros.iter() { - let id_span = match *self.macro_map[did] { - SyntaxExtension::LegacyBang { def_info, .. } => def_info, - _ => None, - }; - if let Some((id, span)) = id_span { + if let Some((id, span)) = self.macro_map[did].def_info { let lint = lint::builtin::UNUSED_MACROS; let msg = "unused macro definition"; self.session.buffer_lint(lint, id, span, msg); @@ -585,17 +582,12 @@ impl<'a> Resolver<'a> { let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; match self.resolve_macro_to_res(derive, MacroKind::Derive, &parent_scope, true, force) { - Ok((_, ext)) => { - if let SyntaxExtension::Derive(_, helpers, _) = &*ext { - if helpers.contains(&ident.name) { - let binding = - (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - ty::Visibility::Public, derive.span, Mark::root()) - .to_name_binding(self.arenas); - result = Ok((binding, Flags::empty())); - break; - } - } + Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) { + let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, derive.span, Mark::root()) + .to_name_binding(self.arenas); + result = Ok((binding, Flags::empty())); + break; } Err(Determinacy::Determined) => {} Err(Determinacy::Undetermined) => diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c14ae5932af47..9259b3b5d3abb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use syntax::ast; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::MacroKind; use syntax::symbol::sym; use syntax_pos::Span; @@ -470,18 +470,12 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE }) } LoadedMacro::ProcMacro(ext) => { - let helpers = match &*ext { - &SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) } - _ => Vec::new(), - }; - clean::ProcMacroItem(clean::ProcMacro { - kind: ext.kind(), - helpers, + kind: ext.macro_kind(), + helpers: ext.helper_attrs.clean(cx), }) } } - } /// A trait's generics clause actually contains all of the predicates for all of diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7fbfc3e1fc0f4..68b96a408294b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { /// Resolves a string as a macro. fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { - use syntax::ext::base::{MacroKind, SyntaxExtension}; + use syntax::ext::base::{MacroKind, SyntaxExtensionKind}; let segment = ast::PathSegment::from_ident(Ident::from_str(path_str)); let path = ast::Path { segments: vec![segment], span: DUMMY_SP }; cx.enter_resolver(|resolver| { @@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res { // skip proc-macro stubs, they'll cause `get_macro` to crash } else { - if let SyntaxExtension::LegacyBang { .. } = *resolver.get_macro(res) { + if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind { return Some(res.map_id(|_| panic!("unexpected id"))); } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 38b7dee40c447..04cef0bba24bf 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -15,6 +15,7 @@ use crate::tokenstream::{self, TokenStream}; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; +use syntax_pos::hygiene::{ExpnInfo, ExpnFormat}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -548,37 +549,19 @@ impl MacroKind { } } -/// An enum representing the different kinds of syntax extensions. -pub enum SyntaxExtension { +/// A syntax extension kind. +pub enum SyntaxExtensionKind { /// A token-based function-like macro. - Bang { + Bang( /// An expander with signature TokenStream -> TokenStream. - expander: Box, - /// Whitelist of unstable features that are treated as stable inside this macro. - allow_internal_unstable: Option>, - /// Edition of the crate in which this macro is defined. - edition: Edition, - }, + Box, + ), /// An AST-based function-like macro. - LegacyBang { + LegacyBang( /// An expander with signature TokenStream -> AST. - expander: Box, - /// Some info about the macro's definition point. - def_info: Option<(ast::NodeId, Span)>, - /// Hygienic properties of identifiers produced by this macro. - transparency: Transparency, - /// Whitelist of unstable features that are treated as stable inside this macro. - allow_internal_unstable: Option>, - /// Suppresses the `unsafe_code` lint for code produced by this macro. - allow_internal_unsafe: bool, - /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. - local_inner_macros: bool, - /// The macro's feature name and tracking issue number if it is unstable. - unstable_feature: Option<(Symbol, u32)>, - /// Edition of the crate in which this macro is defined. - edition: Edition, - }, + Box, + ), /// A token-based attribute macro. Attr( @@ -586,8 +569,6 @@ pub enum SyntaxExtension { /// The first TokenSteam is the attribute itself, the second is the annotated item. /// The produced TokenSteam replaces the input TokenSteam. Box, - /// Edition of the crate in which this macro is defined. - Edition, ), /// An AST-based attribute macro. @@ -599,7 +580,8 @@ pub enum SyntaxExtension { ), /// A trivial attribute "macro" that does nothing, - /// only keeps the attribute and marks it as known. + /// only keeps the attribute and marks it as inert, + /// thus making it ineligible for further expansion. NonMacroAttr { /// Suppresses the `unused_attributes` lint for this attribute. mark_used: bool, @@ -610,10 +592,6 @@ pub enum SyntaxExtension { /// An expander with signature TokenStream -> TokenStream (not yet). /// The produced TokenSteam is appended to the input TokenSteam. Box, - /// Names of helper attributes registered by this macro. - Vec, - /// Edition of the crate in which this macro is defined. - Edition, ), /// An AST-based derive macro. @@ -624,42 +602,90 @@ pub enum SyntaxExtension { ), } +/// A struct representing a macro definition in "lowered" form ready for expansion. +pub struct SyntaxExtension { + /// A syntax extension kind. + pub kind: SyntaxExtensionKind, + /// Some info about the macro's definition point. + pub def_info: Option<(ast::NodeId, Span)>, + /// Hygienic properties of spans produced by this macro by default. + pub default_transparency: Transparency, + /// Whitelist of unstable features that are treated as stable inside this macro. + pub allow_internal_unstable: Option>, + /// Suppresses the `unsafe_code` lint for code produced by this macro. + pub allow_internal_unsafe: bool, + /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. + pub local_inner_macros: bool, + /// The macro's feature name and tracking issue number if it is unstable. + pub unstable_feature: Option<(Symbol, u32)>, + /// Names of helper attributes registered by this macro. + pub helper_attrs: Vec, + /// Edition of the crate in which this macro is defined. + pub edition: Edition, +} + +impl SyntaxExtensionKind { + /// When a syntax extension is constructed, + /// its transparency can often be inferred from its kind. + fn default_transparency(&self) -> Transparency { + match self { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::Derive(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque, + SyntaxExtensionKind::LegacyBang(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent, + } + } +} + impl SyntaxExtension { /// Returns which kind of macro calls this syntax extension. - pub fn kind(&self) -> MacroKind { - match *self { - SyntaxExtension::Bang { .. } | - SyntaxExtension::LegacyBang { .. } => MacroKind::Bang, - SyntaxExtension::Attr(..) | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr, - SyntaxExtension::Derive(..) | - SyntaxExtension::LegacyDerive(..) => MacroKind::Derive, + pub fn macro_kind(&self) -> MacroKind { + match self.kind { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang, + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr, + SyntaxExtensionKind::Derive(..) | + SyntaxExtensionKind::LegacyDerive(..) => MacroKind::Derive, } } - pub fn default_transparency(&self) -> Transparency { - match *self { - SyntaxExtension::LegacyBang { transparency, .. } => transparency, - SyntaxExtension::Bang { .. } | - SyntaxExtension::Attr(..) | - SyntaxExtension::Derive(..) | - SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque, - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent, + /// Constructs a syntax extension with default properties. + pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { + SyntaxExtension { + def_info: None, + default_transparency: kind.default_transparency(), + allow_internal_unstable: None, + allow_internal_unsafe: false, + local_inner_macros: false, + unstable_feature: None, + helper_attrs: Vec::new(), + edition, + kind, } } - pub fn edition(&self, default_edition: Edition) -> Edition { - match *self { - SyntaxExtension::Bang { edition, .. } | - SyntaxExtension::LegacyBang { edition, .. } | - SyntaxExtension::Attr(.., edition) | - SyntaxExtension::Derive(.., edition) => edition, - // Unstable legacy stuff - SyntaxExtension::NonMacroAttr { .. } | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::LegacyDerive(..) => default_edition, + fn expn_format(&self, symbol: Symbol) -> ExpnFormat { + match self.kind { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol), + _ => ExpnFormat::MacroAttribute(symbol), + } + } + + crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { + ExpnInfo { + call_site, + def_site: self.def_info.map(|(_, span)| span), + format: self.expn_format(Symbol::intern(format)), + allow_internal_unstable: self.allow_internal_unstable.clone(), + allow_internal_unsafe: self.allow_internal_unsafe, + local_inner_macros: self.local_inner_macros, + edition: self.edition, } } } diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index a2cf4a2a82d8d..33620cb80f940 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -64,7 +64,7 @@ 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: Some(vec![sym::rustc_attrs, sym::structural_match].into()), + allow_internal_unstable: Some([sym::rustc_attrs, sym::structural_match][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3fa96c60bff67..4e759c5e52865 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1,7 +1,7 @@ use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; use crate::attr::{self, HasAttrs}; -use crate::source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan}; +use crate::source_map::{dummy_spanned, respan}; use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::derive::{add_derived_markers, collect_derives}; @@ -22,7 +22,6 @@ use crate::util::map_in_place::MapInPlace; use errors::{Applicability, FatalError}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, DUMMY_SP, FileName}; -use syntax_pos::hygiene::ExpnFormat; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -189,10 +188,10 @@ impl AstFragmentKind { } } -fn macro_bang_format(path: &ast::Path) -> ExpnFormat { - // We don't want to format a path using pretty-printing, - // `format!("{}", path)`, because that tries to insert - // line-breaks and is slow. +// We don't want to format a path using pretty-printing, +// `format!("{}", path)`, because that tries to insert +// line-breaks and is slow. +fn fast_print_path(path: &ast::Path) -> String { let mut path_str = String::with_capacity(64); for (i, segment) in path.segments.iter().enumerate() { if i != 0 { @@ -202,8 +201,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { path_str.push_str(&segment.ident.as_str()) } } - - MacroBang(Symbol::intern(&path_str)) + path_str } pub struct Invocation { @@ -388,8 +386,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { derives.push(mark); let item = match self.cx.resolver.resolve_macro_path( path, MacroKind::Derive, Mark::root(), Vec::new(), false) { - Ok(ext) => match *ext { - SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(), + Ok(ext) => match ext.kind { + SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(), _ => item.clone(), }, _ => item.clone(), @@ -509,7 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option { if invoc.fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern_enabled() { - if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else { + if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else { emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern, invoc.span(), GateIssue::Language, "macro invocations in `extern {}` blocks are experimental"); @@ -548,34 +546,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - if let SyntaxExtension::NonMacroAttr { mark_used: false } = *ext {} else { - // Macro attrs are always used when expanded, - // non-macro attrs are considered used when the field says so. - attr::mark_used(&attr); - } - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: attr.span, - def_site: None, - format: MacroAttribute(Symbol::intern(&attr.path.to_string())), - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ext.edition(self.cx.parse_sess.edition), - }); + let expn_info = ext.expn_info(attr.span, &fast_print_path(&attr.path)); + invoc.expansion_data.mark.set_expn_info(expn_info); - match *ext { - SyntaxExtension::NonMacroAttr { .. } => { + match &ext.kind { + SyntaxExtensionKind::NonMacroAttr { mark_used } => { attr::mark_known(&attr); + if *mark_used { + attr::mark_used(&attr); + } item.visit_attrs(|attrs| attrs.push(attr)); Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item))) } - SyntaxExtension::LegacyAttr(ref mac) => { + SyntaxExtensionKind::LegacyAttr(expander) => { let meta = attr.parse_meta(self.cx.parse_sess) .map_err(|mut e| { e.emit(); }).ok()?; - let item = mac.expand(self.cx, attr.span, &meta, item); + let item = expander.expand(self.cx, attr.span, &meta, item); Some(invoc.fragment_kind.expect_from_annotatables(item)) } - SyntaxExtension::Attr(ref mac, ..) => { + SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_attr_item(attr.span, &item); let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item { Annotatable::Item(item) => token::NtItem(item), @@ -586,13 +575,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Expr(expr) => token::NtExpr(expr), })), DUMMY_SP).into(); let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span); - let tok_result = mac.expand(self.cx, attr.span, input, item_tok); + let tok_result = expander.expand(self.cx, attr.span, input, item_tok); let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind, &attr.path, attr.span); self.gate_proc_macro_expansion(attr.span, &res); res } - SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => { + SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path)); self.cx.trace_macros_diag(); invoc.fragment_kind.dummy(attr.span) @@ -701,21 +690,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| Ident::invalid()); - let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture - def_site_span: Option, - allow_internal_unstable, - allow_internal_unsafe, - local_inner_macros, - // can't infer this type - unstable_feature: Option<(Symbol, u32)>, - edition| { - + let validate_and_set_expn_info = |this: &mut Self| { // feature-gate the macro invocation - if let Some((feature, issue)) = unstable_feature { + if let Some((feature, issue)) = ext.unstable_feature { let crate_span = this.cx.current_expansion.crate_span.unwrap(); // 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)) + if ext.def_info.map_or(false, |(_, def_span)| !crate_span.contains(def_span)) && !span.allows_unstable(feature) && this.cx.ecfg.features.map_or(true, |feats| { // macro features will count as lib features @@ -734,62 +715,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> { this.cx.trace_macros_diag(); return Err(kind.dummy(span)); } - mark.set_expn_info(ExpnInfo { - call_site: span, - def_site: def_site_span, - format: macro_bang_format(path), - allow_internal_unstable, - allow_internal_unsafe, - local_inner_macros, - edition, - }); + mark.set_expn_info(ext.expn_info(span, &fast_print_path(path))); Ok(()) }; - let opt_expanded = match *ext { - SyntaxExtension::LegacyBang { - ref expander, - def_info, - 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.clone(), - allow_internal_unsafe, - local_inner_macros, - unstable_feature, - edition) { + let opt_expanded = match &ext.kind { + SyntaxExtensionKind::LegacyBang(expander) => { + if let Err(dummy_span) = validate_and_set_expn_info(self) { dummy_span } else { kind.make_from(expander.expand( self.cx, span, mac.node.stream(), - def_info.map(|(_, s)| s), + ext.def_info.map(|(_, s)| s), )) } } - SyntaxExtension::Attr(..) | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::NonMacroAttr { .. } => { + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => { self.cx.span_err(path.span, &format!("`{}` can only be used in attributes", path)); self.cx.trace_macros_diag(); kind.dummy(span) } - SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => { + SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive macro", path)); self.cx.trace_macros_diag(); kind.dummy(span) } - SyntaxExtension::Bang { ref expander, ref allow_internal_unstable, edition } => { + SyntaxExtensionKind::Bang(expander) => { if ident.name != kw::Invalid { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); @@ -798,19 +757,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } else { self.gate_proc_macro_expansion_kind(span, kind); - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: span, - // FIXME procedural macros do not have proper span info - // yet, when they do, we should use it here. - def_site: None, - format: macro_bang_format(path), - // FIXME probably want to follow macro_rules macros here. - allow_internal_unstable: allow_internal_unstable.clone(), - allow_internal_unsafe: false, - local_inner_macros: false, - edition, - }); - + let expn_info = ext.expn_info(span, &fast_print_path(path)); + invoc.expansion_data.mark.set_expn_info(expn_info); let tok_result = expander.expand(self.cx, span, mac.node.stream()); let result = self.parse_ast_fragment(tok_result, kind, path, span); self.gate_proc_macro_expansion(span, &result); @@ -867,55 +815,23 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return None; } - let pretty_name = Symbol::intern(&format!("derive({})", path)); - let span = path.span; - let attr = ast::Attribute { - path, span, - tokens: TokenStream::empty(), - // irrelevant: - id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false, - }; - - let mut expn_info = ExpnInfo { - call_site: span, - def_site: None, - format: MacroAttribute(pretty_name), - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ext.edition(self.cx.parse_sess.edition), - }; - - match ext { - SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => { - let meta = match ext { - SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this - path: Path::from_ident(Ident::invalid()), - span: DUMMY_SP, - node: ast::MetaItemKind::Word, - }, - _ => { - expn_info.allow_internal_unstable = Some(vec![ - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - // RustcDeserialize and RustcSerialize - Symbol::intern("libstd_sys_internals"), - ].into()); - attr.meta()? - } - }; - + match &ext.kind { + SyntaxExtensionKind::Derive(expander) | + SyntaxExtensionKind::LegacyDerive(expander) => { + let expn_info = + ext.expn_info(path.span, &format!("derive({})", fast_print_path(&path))); invoc.expansion_data.mark.set_expn_info(expn_info); - let span = span.with_ctxt(self.cx.backtrace()); + + let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path }; + let span = meta.span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item); Some(invoc.fragment_kind.expect_from_annotatables(items)) } _ => { - let msg = &format!("macro `{}` may not be used for derive attributes", attr.path); - self.cx.span_err(span, msg); + let msg = &format!("macro `{}` may not be used for derive attributes", path); + self.cx.span_err(path.span, msg); self.cx.trace_macros_diag(); - invoc.fragment_kind.dummy(span) + invoc.fragment_kind.dummy(path.span) } } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 22745a1a76d53..7f051c260ec82 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1,6 +1,7 @@ use crate::{ast, attr}; use crate::edition::Edition; -use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander}; +use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::expand::{AstFragment, AstFragmentKind}; use crate::ext::hygiene::Transparency; use crate::ext::tt::macro_parser::{Success, Error, Failure}; @@ -376,7 +377,7 @@ pub fn compile( valid, }); - let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) { + let default_transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) { Transparency::Transparent } else if body.legacy { Transparency::SemiTransparent @@ -426,14 +427,15 @@ pub fn compile( } }); - SyntaxExtension::LegacyBang { - expander, + SyntaxExtension { + kind: SyntaxExtensionKind::LegacyBang(expander), def_info: Some((def.id, def.span)), - transparency, + default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, unstable_feature, + helper_attrs: Vec::new(), edition, } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index eea94f0d19458..9072ad7b30fdf 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,7 +20,7 @@ fn ignored_span(sp: Span, edition: Edition) -> Span { call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: Some(vec![sym::prelude_import].into()), + allow_internal_unstable: Some([sym::prelude_import][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index cbaf12529c101..0e1b10c14f17e 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -284,7 +284,7 @@ fn generate_test_harness(sess: &ParseSess, call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some(vec![sym::main, sym::test, sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::main, sym::test, sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: sess.edition, diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index cf54eacc3d46c..e4a413dda09c6 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -2,7 +2,9 @@ use rustc_data_structures::sync::Lrc; use syntax::ast::{self, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier}; +use syntax::edition::Edition; +use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::build::AstBuilder; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; @@ -67,11 +69,24 @@ macro_rules! derive_traits { } } - pub fn register_builtin_derives(resolver: &mut dyn Resolver) { + pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { + let allow_internal_unstable = Some([ + sym::rustc_attrs, + Symbol::intern("derive_clone_copy"), + Symbol::intern("derive_eq"), + Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize + ][..].into()); + $( resolver.add_builtin( ast::Ident::with_empty_ctxt(Symbol::intern($name)), - Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func)))) + Lrc::new(SyntaxExtension { + allow_internal_unstable: allow_internal_unstable.clone(), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))), + edition, + ) + }), ); )* } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 3dd17207cb8e9..d29d93a8678fb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -43,32 +43,31 @@ pub mod proc_macro_impl; use rustc_data_structures::sync::Lrc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NamedSyntaxExtension, SyntaxExtension}; -use syntax::ext::hygiene::Transparency; +use syntax::ext::base::MacroExpanderFn; +use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind}; use syntax::edition::Edition; use syntax::symbol::{sym, Symbol}; pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, user_exts: Vec, edition: Edition) { - deriving::register_builtin_derives(resolver); + deriving::register_builtin_derives(resolver, edition); let mut register = |name, ext| { resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); }; macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( - register(Symbol::intern(stringify!($name)), - SyntaxExtension::LegacyBang { - expander: Box::new($f as MacroExpanderFn), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); + register(Symbol::intern(stringify!($name)), SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition + )); + )* } + } + macro_rules! register_attr { + ($( $name:ident: $f:expr, )*) => { $( + register(Symbol::intern(stringify!($name)), SyntaxExtension::default( + SyntaxExtensionKind::LegacyAttr(Box::new($f)), edition + )); )* } } @@ -97,33 +96,25 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, assert: assert::expand_assert, } - register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand))); - register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test))); - register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench))); + register_attr! { + test_case: test_case::expand, + test: test::expand_test, + bench: test::expand_bench, + } // format_args uses `unstable` things internally. - register(Symbol::intern("format_args"), - SyntaxExtension::LegacyBang { - expander: Box::new(format::expand_format_args), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: Some(vec![sym::fmt_internals].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); - register(sym::format_args_nl, - SyntaxExtension::LegacyBang { - expander: Box::new(format::expand_format_args_nl), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: Some(vec![sym::fmt_internals].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); + register(Symbol::intern("format_args"), SyntaxExtension { + allow_internal_unstable: Some([sym::fmt_internals][..].into()), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition + ) + }); + register(sym::format_args_nl, SyntaxExtension { + allow_internal_unstable: Some([sym::fmt_internals][..].into()), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition + ) + }); for (name, ext) in user_exts { register(name, ext); diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 29297aa913ed4..cdef5c6a9f48b 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -351,10 +351,9 @@ fn mk_decls( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::proc_macro), - allow_internal_unstable: Some(vec![ - sym::rustc_attrs, - Symbol::intern("proc_macro_internals"), - ].into()), + allow_internal_unstable: Some([ + sym::rustc_attrs, Symbol::intern("proc_macro_internals") + ][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index c20dc6cb2d7cd..a8c8456a3bcf8 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -66,7 +66,7 @@ pub fn expand_test_or_bench( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test), - allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::test].into()), + allow_internal_unstable: Some([sym::rustc_attrs, sym::test][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index cffecdd0f18e7..ce17cf2a6e789 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -41,7 +41,7 @@ pub fn expand( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some(vec![sym::test, sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::test, sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: ecx.parse_sess.edition, diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs index 330459fc08f55..4cf8a4e33c526 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs @@ -11,8 +11,8 @@ extern crate rustc_plugin; use std::borrow::ToOwned; use syntax::ast; use syntax::ext::build::AstBuilder; -use syntax::ext::base::{SyntaxExtension, TTMacroExpander, ExtCtxt, MacResult, MacEager}; -use syntax::ext::hygiene::Transparency; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager}; use syntax::print::pprust; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -38,15 +38,7 @@ impl TTMacroExpander for Expander { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { let args = reg.args().to_owned(); - reg.register_syntax_extension(Symbol::intern("plugin_args"), - SyntaxExtension::LegacyBang { - expander: Box::new(Expander { args: args, }), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition: reg.sess.edition(), - }); + reg.register_syntax_extension(Symbol::intern("plugin_args"), SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(Expander { args })), reg.sess.edition() + )); } From 679000cc0e98b2810a2d1c76ae77ce2574a4ab91 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 00:31:46 +0300 Subject: [PATCH 08/19] allow_internal_unstable: Avoid some more allocations --- src/librustc/hir/lowering.rs | 15 ++++++++++----- src/libsyntax_ext/deriving/mod.rs | 19 +++---------------- src/libsyntax_ext/lib.rs | 5 +++-- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5a548ce8d9ff4..a491b1a099b8a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -142,6 +142,9 @@ pub struct LoweringContext<'a> { current_hir_id_owner: Vec<(DefIndex, u32)>, item_local_id_counters: NodeMap, node_id_to_hir_id: IndexVec, + + allow_try_trait: Option>, + allow_gen_future: Option>, } pub trait Resolver { @@ -267,6 +270,8 @@ pub fn lower_crate( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), + allow_try_trait: Some([sym::try_trait][..].into()), + allow_gen_future: Some([sym::gen_future][..].into()), }.lower_crate(krate) } @@ -1156,7 +1161,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, - Some(vec![sym::gen_future].into()), + self.allow_gen_future.clone(), ); let gen_future = self.expr_std_path( unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new()); @@ -4382,7 +4387,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = this.mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, - Some(vec![sym::try_trait].into()), + this.allow_try_trait.clone(), ); let mut block = this.lower_block(body, true).into_inner(); let tail = block.expr.take().map_or_else( @@ -4968,13 +4973,13 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, - Some(vec![sym::try_trait].into()), + self.allow_try_trait.clone(), ); let try_span = self.sess.source_map().end_point(e.span); let try_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, - Some(vec![sym::try_trait].into()), + self.allow_try_trait.clone(), ); // `Try::into_result()` @@ -5776,7 +5781,7 @@ impl<'a> LoweringContext<'a> { let gen_future_span = self.mark_span_with_reason( CompilerDesugaringKind::Await, await_span, - Some(vec![sym::gen_future].into()), + self.allow_gen_future.clone(), ); // let mut pinned = ; diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index e4a413dda09c6..1fe6094fca686 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -6,7 +6,6 @@ use syntax::edition::Edition; use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; @@ -71,6 +70,7 @@ macro_rules! derive_traits { pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { let allow_internal_unstable = Some([ + sym::core_intrinsics, sym::rustc_attrs, Symbol::intern("derive_clone_copy"), Symbol::intern("derive_eq"), @@ -163,24 +163,11 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { /// Constructs an expression that calls an intrinsic fn call_intrinsic(cx: &ExtCtxt<'_>, - mut span: Span, + span: Span, intrinsic: &str, args: Vec>) -> P { - let intrinsic_allowed_via_allow_internal_unstable = cx - .current_expansion.mark.expn_info().unwrap() - .allow_internal_unstable.map_or(false, |features| features.iter().any(|&s| - s == sym::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 = Some(vec![sym::core_intrinsics].into()); - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(info); - span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); - } + let span = span.with_ctxt(cx.backtrace()); let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]); let call = cx.expr_call_global(span, path, args); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index d29d93a8678fb..b868f5b273c4e 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -103,14 +103,15 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, } // format_args uses `unstable` things internally. + let allow_internal_unstable = Some([sym::fmt_internals][..].into()); register(Symbol::intern("format_args"), SyntaxExtension { - allow_internal_unstable: Some([sym::fmt_internals][..].into()), + allow_internal_unstable: allow_internal_unstable.clone(), ..SyntaxExtension::default( SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition ) }); register(sym::format_args_nl, SyntaxExtension { - allow_internal_unstable: Some([sym::fmt_internals][..].into()), + allow_internal_unstable, ..SyntaxExtension::default( SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition ) From 085a8d03750b524a34bf14adc0c9a36a2503e016 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 11:10:48 +0300 Subject: [PATCH 09/19] syntax: Remove `DummyResolver` --- src/libsyntax/ext/base.rs | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 04cef0bba24bf..cc5a91465ae48 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -725,31 +725,6 @@ impl Determinacy { } } -pub struct DummyResolver; - -impl Resolver for DummyResolver { - fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } - - fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - - fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {} - fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, - _derives: &[Mark]) {} - fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} - - fn resolve_imports(&mut self) {} - fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool) - -> Result>, Determinacy> { - Err(Determinacy::Determined) - } - fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _invoc_id: Mark, - _derives_in_scope: Vec, _force: bool) - -> Result, Determinacy> { - Err(Determinacy::Determined) - } - fn check_unused_macros(&self) {} -} - #[derive(Clone)] pub struct ModuleData { pub mod_path: Vec, From 68e1141c45c71c56cc4904b72f2212701b5912d4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 12:29:56 +0300 Subject: [PATCH 10/19] resolve: Avoid creating fresh syntax extensions for all non-macro attributes --- src/librustc_resolve/build_reduced_graph.rs | 10 +++------- src/librustc_resolve/lib.rs | 12 +++++++++++- src/librustc_resolve/macros.rs | 5 ++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index bb4edf355f8b5..60ffb0782f005 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -29,7 +29,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; -use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -772,12 +772,8 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, res: Res) -> Lrc { let def_id = match res { Res::Def(DefKind::Macro(..), def_id) => def_id, - Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::default( - SyntaxExtensionKind::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool - }, - self.session.edition(), - )), + Res::NonMacroAttr(attr_kind) => + return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool), _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"), }; if let Some(ext) = self.macro_map.get(&def_id) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7f05e0f477c2d..dcc2a228b4a77 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,7 +41,7 @@ use rustc_metadata::cstore::CStore; use syntax::source_map::SourceMap; use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; -use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; use syntax::symbol::{Symbol, kw, sym}; @@ -1668,6 +1668,7 @@ pub struct Resolver<'a> { macro_use_prelude: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, + non_macro_attrs: [Lrc; 2], macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, @@ -1941,6 +1942,10 @@ impl<'a> Resolver<'a> { let mut macro_defs = FxHashMap::default(); macro_defs.insert(Mark::root(), root_def_id); + let non_macro_attr = |mark_used| Lrc::new(SyntaxExtension::default( + SyntaxExtensionKind::NonMacroAttr { mark_used }, session.edition() + )); + Resolver { session, @@ -2014,6 +2019,7 @@ impl<'a> Resolver<'a> { macro_use_prelude: FxHashMap::default(), all_macros: FxHashMap::default(), macro_map: FxHashMap::default(), + non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], invocations, macro_defs, local_macro_def_scopes: FxHashMap::default(), @@ -2030,6 +2036,10 @@ impl<'a> Resolver<'a> { Default::default() } + fn non_macro_attr(&self, mark_used: bool) -> Lrc { + self.non_macro_attrs[mark_used as usize].clone() + } + /// Runs the function on each namespace. fn per_ns(&mut self, mut f: F) { f(self, TypeNS); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 89e28330be7e3..02342d212ebbd 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -211,8 +211,7 @@ impl<'a> base::Resolver for Resolver<'a> { Ok((res, ext)) => (res, ext), Err(Determinacy::Determined) if kind == MacroKind::Attr => { // Replace unresolved attributes with used inert attributes for better recovery. - let kind = SyntaxExtensionKind::NonMacroAttr { mark_used: true }; - return Ok(Some(Lrc::new(SyntaxExtension::default(kind, self.session.edition())))); + return Ok(Some(self.non_macro_attr(true))); } Err(determinacy) => return Err(determinacy), }; From 8ec502eecdccec643ae6631a323dc6f38b490269 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 22:18:56 +0300 Subject: [PATCH 11/19] syntax: Introduce `default`/`with_unstable` constructors for `ExpnInfo` --- src/librustc/hir/lowering.rs | 12 ++++-------- src/librustc_allocator/expand.rs | 21 +++++++-------------- src/libsyntax/ext/derive.rs | 13 ++++--------- src/libsyntax/std_inject.rs | 12 +++--------- src/libsyntax/test.rs | 13 ++++--------- src/libsyntax_ext/proc_macro_decls.rs | 15 ++++----------- src/libsyntax_ext/test.rs | 15 +++++---------- src/libsyntax_ext/test_case.rs | 15 +++++---------- src/libsyntax_pos/hygiene.rs | 23 +++++++++++++++++++++++ 9 files changed, 59 insertions(+), 80 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a491b1a099b8a..0edf407f7c9e3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -62,14 +62,14 @@ use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::print::pprust; use syntax::ptr::P; -use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned}; use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Token}; use syntax::visit::{self, Visitor}; -use syntax_pos::{DUMMY_SP, edition, Span}; +use syntax_pos::{DUMMY_SP, Span}; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; @@ -853,14 +853,10 @@ impl<'a> LoweringContext<'a> { allow_internal_unstable: Option>, ) -> Span { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(source_map::ExpnInfo { - call_site: span, + mark.set_expn_info(ExpnInfo { def_site: Some(span), - format: source_map::CompilerDesugaring(reason), allow_internal_unstable, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: edition::Edition::from_session(), + ..ExpnInfo::default(source_map::CompilerDesugaring(reason), span, self.sess.edition()) }); span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index ecc165ca5ea9f..d402b0ddf6e85 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -19,7 +19,7 @@ use syntax::{ mut_visit::{self, MutVisitor}, parse::ParseSess, ptr::P, - symbol::{kw, sym, Symbol} + symbol::{kw, sym} }; use syntax_pos::Span; @@ -58,11 +58,10 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { debug!("in submodule {}", self.in_submod); - let name = if attr::contains_name(&item.attrs, sym::global_allocator) { - "global_allocator" - } else { + if !attr::contains_name(&item.attrs, sym::global_allocator) { return mut_visit::noop_flat_map_item(item, self); - }; + } + match item.node { ItemKind::Static(..) => {} _ => { @@ -87,15 +86,9 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { // Create a fresh Mark for the new macro expansion we are about to do let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: item.span, // use the call site of the static - def_site: None, - format: MacroAttribute(Symbol::intern(name)), - allow_internal_unstable: Some([sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: self.sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::global_allocator), item.span, self.sess.edition, &[sym::rustc_attrs] + )); // Tie the span to the macro expansion info we just created let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 33620cb80f940..abc451c96ae0e 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -60,15 +60,10 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P } pretty_name.push(')'); - cx.current_expansion.mark.set_expn_info(ExpnInfo { - call_site: span, - def_site: None, - format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: Some([sym::rustc_attrs, sym::structural_match][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + cx.current_expansion.mark.set_expn_info(ExpnInfo::with_unstable( + ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), span, cx.parse_sess.edition, + &[sym::rustc_attrs, sym::structural_match], + )); let span = span.with_ctxt(cx.backtrace()); item.visit_attrs(|attrs| { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 9072ad7b30fdf..6630bf9081546 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -16,15 +16,9 @@ use syntax_pos::{DUMMY_SP, Span}; /// The expanded code uses the unstable `#[prelude_import]` attribute. fn ignored_span(sp: Span, edition: Edition) -> Span { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: Some([sym::prelude_import][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(Symbol::intern("std_inject")), sp, edition, &[sym::prelude_import] + )); sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 0e1b10c14f17e..f90b76721ee16 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -280,15 +280,10 @@ fn generate_test_harness(sess: &ParseSess, test_runner }; - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some([sym::main, sym::test, sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test_case), DUMMY_SP, sess.edition, + &[sym::main, sym::test, sym::rustc_attrs], + )); TestHarnessGenerator { cx, diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index cdef5c6a9f48b..45e65288a24ee 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -347,17 +347,10 @@ fn mk_decls( custom_macros: &[ProcMacroDef], ) -> P { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::proc_macro), - allow_internal_unstable: Some([ - sym::rustc_attrs, Symbol::intern("proc_macro_internals") - ][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, + &[sym::rustc_attrs, Symbol::intern("proc_macro_internals")], + )); let span = DUMMY_SP.apply_mark(mark); let hidden = cx.meta_list_item_word(span, sym::hidden); diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index a8c8456a3bcf8..24d3055e71140 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -8,7 +8,7 @@ use syntax::attr; use syntax::ast; use syntax::print::pprust; use syntax::symbol::{Symbol, sym}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; use syntax::source_map::{ExpnInfo, MacroAttribute}; use std::iter; @@ -62,15 +62,10 @@ pub fn expand_test_or_bench( let (sp, attr_sp) = { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test), - allow_internal_unstable: Some([sym::rustc_attrs, sym::test][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test), attr_sp, cx.parse_sess.edition, + &[sym::rustc_attrs, sym::test], + )); (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)), attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))) }; diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index ce17cf2a6e789..6e3bc05b65e4e 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -15,7 +15,7 @@ use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast; use syntax::source_map::respan; use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; use syntax::source_map::{ExpnInfo, MacroAttribute}; use syntax::feature_gate; @@ -37,15 +37,10 @@ pub fn expand( let sp = { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some([sym::test, sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ecx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test_case), attr_sp, ecx.parse_sess.edition, + &[sym::test, sym::rustc_attrs], + )); attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) }; diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index b827416ab53c2..e9a912ddbc237 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -682,6 +682,29 @@ pub struct ExpnInfo { pub edition: Edition, } +impl ExpnInfo { + /// Constructs an expansion info with default properties. + pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo { + ExpnInfo { + call_site, + def_site: None, + format, + allow_internal_unstable: None, + allow_internal_unsafe: false, + local_inner_macros: false, + edition, + } + } + + pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition, + allow_internal_unstable: &[Symbol]) -> ExpnInfo { + ExpnInfo { + allow_internal_unstable: Some(allow_internal_unstable.into()), + ..ExpnInfo::default(format, call_site, edition) + } + } +} + /// The source of expansion. #[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum ExpnFormat { From 2de2278f1a356cba63300cee0bca49ad8f4905ab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 23:55:22 +0300 Subject: [PATCH 12/19] syntax: Move `default_transparency` into `ExpnInfo` --- src/librustc/ich/impls_syntax.rs | 9 ++++++- src/librustc_resolve/macros.rs | 1 - src/libsyntax/ext/base.rs | 3 ++- src/libsyntax_pos/hygiene.rs | 42 +++++++++++++------------------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 4f618457d6c6a..9430661f75ab7 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -391,10 +391,17 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { NameValue(lit) }); +impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency { + Transparent, + SemiTransparent, + Opaque, +}); + impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { call_site, - def_site, format, + def_site, + default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 02342d212ebbd..a7c98842fa3e3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -226,7 +226,6 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency); } Ok(Some(ext)) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cc5a91465ae48..e0fbdedd24bd7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -680,8 +680,9 @@ impl SyntaxExtension { crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { ExpnInfo { call_site, - def_site: self.def_info.map(|(_, span)| span), format: self.expn_format(Symbol::intern(format)), + def_site: self.def_info.map(|(_, span)| span), + default_transparency: self.default_transparency, allow_internal_unstable: self.allow_internal_unstable.clone(), allow_internal_unsafe: self.allow_internal_unsafe, local_inner_macros: self.local_inner_macros, diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index e9a912ddbc237..67b6e9da477f5 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -59,13 +59,12 @@ pub struct Mark(u32); #[derive(Clone, Debug)] struct MarkData { parent: Mark, - default_transparency: Transparency, expn_info: Option, } /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. @@ -85,12 +84,7 @@ pub enum Transparency { impl Mark { pub fn fresh(parent: Mark) -> Self { HygieneData::with(|data| { - data.marks.push(MarkData { - parent, - // By default expansions behave like `macro_rules`. - default_transparency: Transparency::SemiTransparent, - expn_info: None, - }); + data.marks.push(MarkData { parent, expn_info: None }); Mark(data.marks.len() as u32 - 1) }) } @@ -126,12 +120,6 @@ impl Mark { HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info)) } - #[inline] - pub fn set_default_transparency(self, transparency: Transparency) { - assert_ne!(self, Mark::root()); - HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency) - } - pub fn is_descendant_of(self, ancestor: Mark) -> bool { HygieneData::with(|data| data.is_descendant_of(self, ancestor)) } @@ -172,9 +160,8 @@ impl Mark { #[inline] pub fn looks_like_proc_macro_derive(self) -> bool { HygieneData::with(|data| { - let mark_data = &data.marks[self.0 as usize]; - if mark_data.default_transparency == Transparency::Opaque { - if let Some(expn_info) = &mark_data.expn_info { + if data.default_transparency(self) == Transparency::Opaque { + if let Some(expn_info) = &data.marks[self.0 as usize].expn_info { if let ExpnFormat::MacroAttribute(name) = expn_info.format { if name.as_str().starts_with("derive(") { return true; @@ -199,9 +186,6 @@ impl HygieneData { HygieneData { marks: vec![MarkData { parent: Mark::root(), - // If the root is opaque, then loops searching for an opaque mark - // will automatically stop after reaching it. - default_transparency: Transparency::Opaque, expn_info: None, }], syntax_contexts: vec![SyntaxContextData { @@ -235,7 +219,9 @@ impl HygieneData { } fn default_transparency(&self, mark: Mark) -> Transparency { - self.marks[mark.0 as usize].default_transparency + self.marks[mark.0 as usize].expn_info.as_ref().map_or( + Transparency::SemiTransparent, |einfo| einfo.default_transparency + ) } fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { @@ -427,7 +413,6 @@ impl SyntaxContext { HygieneData::with(|data| { data.marks.push(MarkData { parent: Mark::root(), - default_transparency: Transparency::SemiTransparent, expn_info: Some(expansion_info), }); @@ -651,6 +636,7 @@ impl fmt::Debug for SyntaxContext { /// Extra information for tracking spans of macro and syntax sugar expansion #[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExpnInfo { + // --- The part unique to each expansion. /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` /// @@ -661,13 +647,18 @@ pub struct ExpnInfo { /// call_site span would have its own ExpnInfo, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, + /// The format with which the macro was invoked. + pub format: ExpnFormat, + + // --- The part specific to the macro/desugaring definition. + // --- FIXME: Share it between expansions with the same definition. /// The span of the macro definition itself. The macro may not /// have a sensible definition span (e.g., something defined /// completely inside libsyntax) in which case this is None. /// This span serves only informational purpose and is not used for resolution. pub def_site: Option, - /// The format with which the macro was invoked. - pub format: ExpnFormat, + /// Transparency used by `apply_mark` for mark with this expansion info by default. + pub default_transparency: Transparency, /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. @@ -687,8 +678,9 @@ impl ExpnInfo { pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo { ExpnInfo { call_site, - def_site: None, format, + def_site: None, + default_transparency: Transparency::SemiTransparent, allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, From 1ff3bce5bbcf3f23ad90266f8f3de1ac13d23623 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 18 Jun 2019 01:36:44 +0300 Subject: [PATCH 13/19] hygiene: Avoid some unnecessary `ExpnInfo` clones --- src/libsyntax_pos/hygiene.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 67b6e9da477f5..4dbd4ccda910a 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -112,7 +112,7 @@ impl Mark { #[inline] pub fn expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(self)) + HygieneData::with(|data| data.expn_info(self).cloned()) } #[inline] @@ -204,8 +204,8 @@ impl HygieneData { GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) } - fn expn_info(&self, mark: Mark) -> Option { - self.marks[mark.0 as usize].expn_info.clone() + fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> { + self.marks[mark.0 as usize].expn_info.as_ref() } fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool { @@ -598,7 +598,7 @@ impl SyntaxContext { /// `ctxt.outer().expn_info()`. #[inline] pub fn outer_expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(data.outer(self))) + HygieneData::with(|data| data.expn_info(data.outer(self)).cloned()) } /// `ctxt.outer_and_expn_info()` is equivalent to but faster than @@ -607,7 +607,7 @@ impl SyntaxContext { pub fn outer_and_expn_info(self) -> (Mark, Option) { HygieneData::with(|data| { let outer = data.outer(self); - (outer, data.expn_info(outer)) + (outer, data.expn_info(outer).cloned()) }) } From e152554e11ff44b1a08e21a8416e1fc18504764e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 18 Jun 2019 10:48:44 +0300 Subject: [PATCH 14/19] resolve/expand: Move expansion info setting to a single earlier point --- src/librustc_resolve/macros.rs | 31 ++++++++++++++++++++++++++----- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/expand.rs | 32 +++----------------------------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a7c98842fa3e3..d2fec0ed622d1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -114,6 +114,22 @@ fn sub_namespace_match(candidate: Option, requirement: Option String { + let mut path_str = String::with_capacity(64); + for (i, segment) in path.segments.iter().enumerate() { + if i != 0 { + path_str.push_str("::"); + } + if segment.ident.name != kw::PathRoot { + path_str.push_str(&segment.ident.as_str()) + } + } + path_str +} + impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() @@ -209,14 +225,19 @@ impl<'a> base::Resolver for Resolver<'a> { let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); let (res, ext) = match self.resolve_macro_to_res(path, kind, &parent_scope, true, force) { Ok((res, ext)) => (res, ext), - Err(Determinacy::Determined) if kind == MacroKind::Attr => { - // Replace unresolved attributes with used inert attributes for better recovery. - return Ok(Some(self.non_macro_attr(true))); - } + // Replace unresolved attributes with used inert attributes for better recovery. + Err(Determinacy::Determined) if kind == MacroKind::Attr => + (Res::Err, self.non_macro_attr(true)), Err(determinacy) => return Err(determinacy), }; - if let Res::Def(DefKind::Macro(_), def_id) = res { + let format = match kind { + MacroKind::Derive => format!("derive({})", fast_print_path(path)), + _ => fast_print_path(path), + }; + invoc.expansion_data.mark.set_expn_info(ext.expn_info(invoc.span(), &format)); + + if let Res::Def(_, def_id) = res { if after_derive { self.session.span_err(invoc.span(), "macro attributes must be placed before `#[derive]`"); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e0fbdedd24bd7..318a5a3a82a2e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -677,7 +677,7 @@ impl SyntaxExtension { } } - crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { + pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { ExpnInfo { call_site, format: self.expn_format(Symbol::intern(format)), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4e759c5e52865..7154cc409f268 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -188,22 +188,6 @@ impl AstFragmentKind { } } -// We don't want to format a path using pretty-printing, -// `format!("{}", path)`, because that tries to insert -// line-breaks and is slow. -fn fast_print_path(path: &ast::Path) -> String { - let mut path_str = String::with_capacity(64); - for (i, segment) in path.segments.iter().enumerate() { - if i != 0 { - path_str.push_str("::"); - } - if segment.ident.name != kw::PathRoot { - path_str.push_str(&segment.ident.as_str()) - } - } - path_str -} - pub struct Invocation { pub kind: InvocationKind, fragment_kind: AstFragmentKind, @@ -546,9 +530,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - let expn_info = ext.expn_info(attr.span, &fast_print_path(&attr.path)); - invoc.expansion_data.mark.set_expn_info(expn_info); - match &ext.kind { SyntaxExtensionKind::NonMacroAttr { mark_used } => { attr::mark_known(&attr); @@ -682,7 +663,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invoc: Invocation, ext: &SyntaxExtension) -> Option { - let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind); + let kind = invoc.fragment_kind; let (mac, ident, span) = match invoc.kind { InvocationKind::Bang { mac, ident, span } => (mac, ident, span), _ => unreachable!(), @@ -690,7 +671,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| Ident::invalid()); - let validate_and_set_expn_info = |this: &mut Self| { + let validate = |this: &mut Self| { // feature-gate the macro invocation if let Some((feature, issue)) = ext.unstable_feature { let crate_span = this.cx.current_expansion.crate_span.unwrap(); @@ -715,13 +696,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { this.cx.trace_macros_diag(); return Err(kind.dummy(span)); } - mark.set_expn_info(ext.expn_info(span, &fast_print_path(path))); Ok(()) }; let opt_expanded = match &ext.kind { SyntaxExtensionKind::LegacyBang(expander) => { - if let Err(dummy_span) = validate_and_set_expn_info(self) { + if let Err(dummy_span) = validate(self) { dummy_span } else { kind.make_from(expander.expand( @@ -757,8 +737,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } else { self.gate_proc_macro_expansion_kind(span, kind); - let expn_info = ext.expn_info(span, &fast_print_path(path)); - invoc.expansion_data.mark.set_expn_info(expn_info); let tok_result = expander.expand(self.cx, span, mac.node.stream()); let result = self.parse_ast_fragment(tok_result, kind, path, span); self.gate_proc_macro_expansion(span, &result); @@ -818,10 +796,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match &ext.kind { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { - let expn_info = - ext.expn_info(path.span, &format!("derive({})", fast_print_path(&path))); - invoc.expansion_data.mark.set_expn_info(expn_info); - let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path }; let span = meta.span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item); From 0f9dc6c48e51637a5d54fc791df94d104c1e0aee Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Tue, 11 Jun 2019 19:04:02 -0700 Subject: [PATCH 15/19] Make MaybeUninit #[repr(transparent)] Tracking issue: #60405 --- src/libcore/lib.rs | 1 + src/libcore/mem/maybe_uninit.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 030f4f1d12cc8..1bfb852424d63 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -100,6 +100,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] +#![cfg_attr(not(bootstrap), feature(transparent_unions))] #![feature(unboxed_closures)] #![feature(unsized_locals)] #![feature(untagged_unions)] diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index eeff9d0303a3b..28e1e22ba7ff2 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -172,7 +172,7 @@ use crate::mem::ManuallyDrop; /// /// # Layout /// -/// `MaybeUninit` is guaranteed to have the same size and alignment as `T`: +/// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as `T`: /// /// ```rust /// use std::mem::{MaybeUninit, size_of, align_of}; @@ -191,9 +191,23 @@ use crate::mem::ManuallyDrop; /// assert_eq!(size_of::>(), 1); /// assert_eq!(size_of::>>(), 2); /// ``` +/// +/// If `T` is FFI-safe, then so is `MaybeUninit`. +/// +/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, +/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option` and +/// `Option>` may still have different sizes, and types containing a field of type +/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit`. +/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the +/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact +/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not +/// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has +/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that +/// guarantee may evolve. #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] #[derive(Copy)] +#[cfg_attr(not(bootstrap), repr(transparent))] pub union MaybeUninit { uninit: (), value: ManuallyDrop, From dedf2eda8f6d062da91c80a8980b3b794f5c876e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 16 Jun 2019 17:23:41 +0300 Subject: [PATCH 16/19] rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`. --- src/librustc_typeck/check/mod.rs | 96 +++++++++---------- .../{run-pass => ui}/issues/issue-57924.rs | 1 + src/test/ui/issues/issue-57924.stderr | 9 ++ src/test/ui/issues/issue-61882-2.rs | 11 +++ src/test/ui/issues/issue-61882-2.stderr | 15 +++ src/test/ui/issues/issue-61882.rs | 9 ++ src/test/ui/issues/issue-61882.stderr | 21 ++++ 7 files changed, 109 insertions(+), 53 deletions(-) rename src/test/{run-pass => ui}/issues/issue-57924.rs (64%) create mode 100644 src/test/ui/issues/issue-57924.stderr create mode 100644 src/test/ui/issues/issue-61882-2.rs create mode 100644 src/test/ui/issues/issue-61882-2.stderr create mode 100644 src/test/ui/issues/issue-61882.rs create mode 100644 src/test/ui/issues/issue-61882.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 22f17097fcbe3..a5d9284a6fed8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5300,52 +5300,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(original_span.with_lo(original_span.hi() - BytePos(1))) } - // Rewrite `SelfCtor` to `Ctor` - pub fn rewrite_self_ctor( - &self, - res: Res, - span: Span, - ) -> Result { - let tcx = self.tcx; - if let Res::SelfCtor(impl_def_id) = res { - let ty = self.impl_self_ty(span, impl_def_id).ty; - let adt_def = ty.ty_adt_def(); - - match adt_def { - Some(adt_def) if adt_def.has_ctor() => { - let variant = adt_def.non_enum_variant(); - let ctor_def_id = variant.ctor_def_id.unwrap(); - Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id)) - } - _ => { - let mut err = tcx.sess.struct_span_err(span, - "the `Self` constructor can only be used with tuple or unit structs"); - if let Some(adt_def) = adt_def { - match adt_def.adt_kind() { - AdtKind::Enum => { - err.help("did you mean to use one of the enum's variants?"); - }, - AdtKind::Struct | - AdtKind::Union => { - err.span_suggestion( - span, - "use curly brackets", - String::from("Self { /* fields */ }"), - Applicability::HasPlaceholders, - ); - } - } - } - err.emit(); - - Err(ErrorReported) - } - } - } else { - Ok(res) - } - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, @@ -5365,12 +5319,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; - let res = match self.rewrite_self_ctor(res, span) { - Ok(res) => res, - Err(ErrorReported) => return (tcx.types.err, res), - }; let path_segs = match res { - Res::Local(_) => vec![], + Res::Local(_) | Res::SelfCtor(_) => vec![], Res::Def(kind, def_id) => AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id), _ => bug!("instantiate_value_path on {:?}", res), @@ -5475,13 +5425,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.generics_of(*def_id).has_self }).unwrap_or(false); + let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res { + let ty = self.impl_self_ty(span, impl_def_id).ty; + let adt_def = ty.ty_adt_def(); + + match ty.sty { + ty::Adt(adt_def, substs) if adt_def.has_ctor() => { + let variant = adt_def.non_enum_variant(); + let ctor_def_id = variant.ctor_def_id.unwrap(); + ( + Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id), + Some(substs), + ) + } + _ => { + let mut err = tcx.sess.struct_span_err(span, + "the `Self` constructor can only be used with tuple or unit structs"); + if let Some(adt_def) = adt_def { + match adt_def.adt_kind() { + AdtKind::Enum => { + err.help("did you mean to use one of the enum's variants?"); + }, + AdtKind::Struct | + AdtKind::Union => { + err.span_suggestion( + span, + "use curly brackets", + String::from("Self { /* fields */ }"), + Applicability::HasPlaceholders, + ); + } + } + } + err.emit(); + + return (tcx.types.err, res) + } + } + } else { + (res, None) + }; let def_id = res.def_id(); // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. let ty = tcx.type_of(def_id); - let substs = AstConv::create_substs_for_generic_args( + let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args( tcx, def_id, &[][..], @@ -5551,7 +5541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }, - ); + )); assert!(!substs.has_escaping_bound_vars()); assert!(!ty.has_escaping_bound_vars()); diff --git a/src/test/run-pass/issues/issue-57924.rs b/src/test/ui/issues/issue-57924.rs similarity index 64% rename from src/test/run-pass/issues/issue-57924.rs rename to src/test/ui/issues/issue-57924.rs index 232596334b0ed..dc2942225e3de 100644 --- a/src/test/run-pass/issues/issue-57924.rs +++ b/src/test/ui/issues/issue-57924.rs @@ -3,6 +3,7 @@ pub struct Gcm(E); impl Gcm { pub fn crash(e: E) -> Self { Self::(e) + //~^ ERROR type arguments are not allowed for this type } } diff --git a/src/test/ui/issues/issue-57924.stderr b/src/test/ui/issues/issue-57924.stderr new file mode 100644 index 0000000000000..2f184b1aae171 --- /dev/null +++ b/src/test/ui/issues/issue-57924.stderr @@ -0,0 +1,9 @@ +error[E0109]: type arguments are not allowed for this type + --> $DIR/issue-57924.rs:5:16 + | +LL | Self::(e) + | ^ type argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/issues/issue-61882-2.rs b/src/test/ui/issues/issue-61882-2.rs new file mode 100644 index 0000000000000..1209b54bc410e --- /dev/null +++ b/src/test/ui/issues/issue-61882-2.rs @@ -0,0 +1,11 @@ +struct A(T); + +impl A<&'static u8> { + fn f() { + let x = 0; + Self(&x); + //~^ ERROR `x` does not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr new file mode 100644 index 0000000000000..03a65540ced04 --- /dev/null +++ b/src/test/ui/issues/issue-61882-2.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-61882-2.rs:6:14 + | +LL | Self(&x); + | ^^ + | | + | borrowed value does not live long enough + | requires that `x` is borrowed for `'static` +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issues/issue-61882.rs b/src/test/ui/issues/issue-61882.rs new file mode 100644 index 0000000000000..013398b4598a8 --- /dev/null +++ b/src/test/ui/issues/issue-61882.rs @@ -0,0 +1,9 @@ +struct A(T); + +impl A { + const B: A = Self(0); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/issues/issue-61882.stderr b/src/test/ui/issues/issue-61882.stderr new file mode 100644 index 0000000000000..a14e1a4dd4d44 --- /dev/null +++ b/src/test/ui/issues/issue-61882.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:27 + | +LL | const B: A = Self(0); + | ^ expected bool, found integer + | + = note: expected type `bool` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:22 + | +LL | const B: A = Self(0); + | ^^^^^^^ expected u8, found bool + | + = note: expected type `A` + found type `A` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 831ddf700d91b50ac8e3beffe35d7ee5f5dd5218 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 14 Jun 2019 08:31:43 -0700 Subject: [PATCH 17/19] ci: Add a script for generating CPU usage graphs This commit checks in a script which generates CPU usage graphs over time, expanding on the previous comment that was include in the collection file. --- src/ci/cpu-usage-over-time.py | 19 ++--------- src/etc/cpu-usage-over-time-plot.sh | 49 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 17 deletions(-) create mode 100755 src/etc/cpu-usage-over-time-plot.sh diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py index 78427a6360a9f..daf21670b3339 100644 --- a/src/ci/cpu-usage-over-time.py +++ b/src/ci/cpu-usage-over-time.py @@ -30,23 +30,8 @@ # the second column is always zero. # # Once you've downloaded a file there's various ways to plot it and visualize -# it. For command line usage you can use a script like so: -# -# set timefmt '%Y-%m-%dT%H:%M:%S' -# set xdata time -# set ylabel "Idle CPU %" -# set xlabel "Time" -# set datafile sep ',' -# set term png -# set output "printme.png" -# set grid -# builder = "i686-apple" -# plot "cpu-".builder.".csv" using 1:2 with lines title builder -# -# Executed as `gnuplot < ./foo.plot` it will generate a graph called -# `printme.png` which you can then open up. If you know how to improve this -# script or the viewing process that would be much appreciated :) (or even if -# you know how to automate it!) +# it. For command line usage you use the `src/etc/cpu-usage-over-time-plot.sh` +# script in this repository. import datetime import sys diff --git a/src/etc/cpu-usage-over-time-plot.sh b/src/etc/cpu-usage-over-time-plot.sh new file mode 100755 index 0000000000000..724a21c3fc269 --- /dev/null +++ b/src/etc/cpu-usage-over-time-plot.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# A small script to help visualizing CPU usage over time data collected on CI +# using `gnuplot`. +# +# This script is expected to be called with two arguments. The first is the full +# commit SHA of the build you're interested in, and the second is the name of +# the builder. For example: +# +# ./src/etc/cpu-usage-over-time-plot.sh e699ea096fcc2fc9ce8e8bcf884e11496a31cc9f i686-mingw-1 +# +# That will generate `$builder.png` in the current directory which you can open +# up to see a hopefully pretty graph. +# +# Improvements to this script are greatly appreciated! + +set -ex + +bucket=rust-lang-ci-evalazure +commit=$1 +builder=$2 + +curl -O https://$bucket.s3.amazonaws.com/rustc-builds/$commit/cpu-$builder.csv + +gnuplot <<-EOF +reset +set timefmt '%Y-%m-%dT%H:%M:%S' +set xdata time +set ylabel "CPU Usage %" +set xlabel "Time" +set datafile sep ',' +set term png size 3000,1000 +set output "$builder.png" +set grid + +f(x) = mean_y +fit f(x) 'cpu-$builder.csv' using 1:(100-\$2) via mean_y + +set label 1 gprintf("Average = %g%%", mean_y) center font ",18" +set label 1 at graph 0.50, 0.25 +set xtics rotate by 45 offset -2,-2.4 300 +set ytics 10 +set boxwidth 0.5 + +plot \\ + mean_y with lines linetype 1 linecolor rgb "#ff0000" title "average", \\ + "cpu-$builder.csv" using 1:(100-\$2) with points pointtype 7 pointsize 0.4 title "$builder", \\ + "" using 1:(100-\$2) smooth bezier linewidth 3 title "bezier" +EOF From d8eea9258acfad331226ddc746f220216bf5dde4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 18 Jun 2019 21:57:31 +0200 Subject: [PATCH 18/19] create an issue for miri even in status test-fail --- src/tools/publish_toolstate.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index a777279bd16c9..9e7c18b7f566b 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -64,6 +64,7 @@ def maybe_delink(message): def issue( tool, + status, maintainers, relevant_pr_number, relevant_pr_user, @@ -72,12 +73,16 @@ def issue( # Open an issue about the toolstate failure. assignees = [x.strip() for x in maintainers.split('@') if x != ''] assignees.append(relevant_pr_user) + if status == 'test-fail': + status_description = 'has failing tests' + else: + status_description = 'no longer builds' response = urllib2.urlopen(urllib2.Request( gh_url(), json.dumps({ 'body': maybe_delink(textwrap.dedent('''\ Hello, this is your friendly neighborhood mergebot. - After merging PR {}, I observed that the tool {} no longer builds. + After merging PR {}, I observed that the tool {} {}. A follow-up PR to the repository {} is needed to fix the fallout. cc @{}, do you think you would have time to do the follow-up work? @@ -85,7 +90,10 @@ def issue( cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization. - ''').format(relevant_pr_number, tool, REPOS.get(tool), relevant_pr_user, pr_reviewer)), + ''').format( + relevant_pr_number, tool, status_description, + REPOS.get(tool), relevant_pr_user, pr_reviewer + )), 'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number), 'assignees': assignees, 'labels': ['T-compiler', 'I-nominated'], @@ -127,7 +135,7 @@ def update_latest( for status in latest: tool = status['tool'] changed = False - build_failed = False + create_issue = False for os, s in current_status.items(): old = status[os] @@ -145,14 +153,15 @@ def update_latest( .format(tool, os, old, new) message += '{} (cc {}, @rust-lang/infra).\n' \ .format(title, MAINTAINERS.get(tool)) - # only create issues for build failures. Other failures can be spurious - if new == 'build-fail': - build_failed = True + # Most tools only create issues for build failures. + # Other failures can be spurious. + if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'): + create_issue = True - if build_failed: + if create_issue: try: issue( - tool, MAINTAINERS.get(tool, ''), + tool, new, MAINTAINERS.get(tool, ''), relevant_pr_number, relevant_pr_user, pr_reviewer, ) except IOError as e: From d67db0042c1f4e163292ea59bdfac546c67f7001 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Jun 2019 14:34:51 -0700 Subject: [PATCH 19/19] Preserve generator and yield source for error messages Previously, error messages after HIR lowering all referred to generators and yield, regardless of whether the original source was a generator or an async/await body. This change tracks the kind of each generator and yield source in order to provide appropriately tailored error messages. --- src/librustc/cfg/construct.rs | 2 +- src/librustc/hir/intravisit.rs | 2 +- src/librustc/hir/lowering.rs | 148 ++++++++++-------- src/librustc/hir/mod.rs | 72 +++++++-- src/librustc/hir/print.rs | 2 +- src/librustc/ich/impls_hir.rs | 10 +- .../infer/error_reporting/need_type_info.rs | 9 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/liveness.rs | 2 +- src/librustc/middle/region.rs | 29 +++- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_passes/rvalue_promotion.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- .../check/generator_interior.rs | 43 +++-- src/librustc_typeck/check/mod.rs | 12 +- .../ui/async-await/unresolved_type_param.rs | 4 +- .../async-await/unresolved_type_param.stderr | 4 +- 18 files changed, 222 insertions(+), 129 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 139c144fbcf4e..ffbdc0373f80c 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -330,7 +330,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Field(ref e, _) | - hir::ExprKind::Yield(ref e) | + hir::ExprKind::Yield(ref e, _) | hir::ExprKind::Repeat(ref e, _) => { self.straightline(expr, pred, Some(&**e).into_iter()) } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f4f9d6261de48..0ab6f7bc46a84 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1089,7 +1089,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(expr) } } - ExprKind::Yield(ref subexpression) => { + ExprKind::Yield(ref subexpression, _) => { visitor.visit_expr(subexpression); } ExprKind::Lit(_) | ExprKind::Err => {} diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5a548ce8d9ff4..d25f3ed5c89a6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -95,8 +95,7 @@ pub struct LoweringContext<'a> { modules: BTreeMap, - is_generator: bool, - is_async_body: bool, + generator_kind: Option, /// Used to get the current `fn`'s def span to point to when using `await` /// outside of an `async fn`. @@ -261,8 +260,7 @@ pub fn lower_crate( current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), - is_generator: false, - is_async_body: false, + generator_kind: None, current_item: None, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, @@ -790,18 +788,49 @@ impl<'a> LoweringContext<'a> { }) } - fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { - if self.is_generator && self.is_async_body { - span_err!( - self.sess, - value.span, - E0727, - "`async` generators are not yet supported", - ); - self.sess.abort_if_errors(); + fn generator_movability_for_fn( + &mut self, + decl: &ast::FnDecl, + fn_decl_span: Span, + generator_kind: Option, + movability: Movability, + ) -> Option { + match generator_kind { + Some(hir::GeneratorKind::Gen) => { + if !decl.inputs.is_empty() { + span_err!( + self.sess, + fn_decl_span, + E0628, + "generators cannot have explicit arguments" + ); + self.sess.abort_if_errors(); + } + Some(match movability { + Movability::Movable => hir::GeneratorMovability::Movable, + Movability::Static => hir::GeneratorMovability::Static, + }) + }, + Some(hir::GeneratorKind::Async) => { + bug!("non-`async` closure body turned `async` during lowering"); + }, + None => { + if movability == Movability::Static { + span_err!( + self.sess, + fn_decl_span, + E0697, + "closures cannot be static" + ); + } + None + }, } + } + + fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { let body = hir::Body { - is_generator: self.is_generator || self.is_async_body, + generator_kind: self.generator_kind, arguments, value, }; @@ -1142,7 +1171,7 @@ impl<'a> LoweringContext<'a> { }; let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); let body_id = self.lower_fn_body(&ast_decl, |this| { - this.is_async_body = true; + this.generator_kind = Some(hir::GeneratorKind::Async); body(this) }); let generator = hir::Expr { @@ -1167,12 +1196,10 @@ impl<'a> LoweringContext<'a> { &mut self, f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), ) -> hir::BodyId { - let prev_is_generator = mem::replace(&mut self.is_generator, false); - let prev_is_async_body = mem::replace(&mut self.is_async_body, false); + let prev_gen_kind = self.generator_kind.take(); let (arguments, result) = f(self); let body_id = self.record_body(arguments, result); - self.is_generator = prev_is_generator; - self.is_async_body = prev_is_async_body; + self.generator_kind = prev_gen_kind; body_id } @@ -4475,37 +4502,18 @@ impl<'a> LoweringContext<'a> { self.with_new_scopes(|this| { this.current_item = Some(fn_decl_span); - let mut is_generator = false; + let mut generator_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr(body); - is_generator = this.is_generator; + generator_kind = this.generator_kind; e }); - let generator_option = if is_generator { - if !decl.inputs.is_empty() { - span_err!( - this.sess, - fn_decl_span, - E0628, - "generators cannot have explicit arguments" - ); - this.sess.abort_if_errors(); - } - Some(match movability { - Movability::Movable => hir::GeneratorMovability::Movable, - Movability::Static => hir::GeneratorMovability::Static, - }) - } else { - if movability == Movability::Static { - span_err!( - this.sess, - fn_decl_span, - E0697, - "closures cannot be static" - ); - } - None - }; + let generator_option = this.generator_movability_for_fn( + &decl, + fn_decl_span, + generator_kind, + movability, + ); hir::ExprKind::Closure( this.lower_capture_clause(capture_clause), fn_decl, @@ -4677,12 +4685,26 @@ impl<'a> LoweringContext<'a> { } ExprKind::Yield(ref opt_expr) => { - self.is_generator = true; + match self.generator_kind { + Some(hir::GeneratorKind::Gen) => {}, + Some(hir::GeneratorKind::Async) => { + span_err!( + self.sess, + e.span, + E0727, + "`async` generators are not yet supported", + ); + self.sess.abort_if_errors(); + }, + None => { + self.generator_kind = Some(hir::GeneratorKind::Gen); + } + } let expr = opt_expr .as_ref() .map(|x| self.lower_expr(x)) .unwrap_or_else(|| self.expr_unit(e.span)); - hir::ExprKind::Yield(P(expr)) + hir::ExprKind::Yield(P(expr), hir::YieldSource::Yield) } ExprKind::Err => hir::ExprKind::Err, @@ -5754,19 +5776,23 @@ impl<'a> LoweringContext<'a> { // yield (); // } // } - if !self.is_async_body { - let mut err = struct_span_err!( - self.sess, - await_span, - E0728, - "`await` is only allowed inside `async` functions and blocks" - ); - err.span_label(await_span, "only allowed inside `async` functions and blocks"); - if let Some(item_sp) = self.current_item { - err.span_label(item_sp, "this is not `async`"); + match self.generator_kind { + Some(hir::GeneratorKind::Async) => {}, + Some(hir::GeneratorKind::Gen) | + None => { + let mut err = struct_span_err!( + self.sess, + await_span, + E0728, + "`await` is only allowed inside `async` functions and blocks" + ); + err.span_label(await_span, "only allowed inside `async` functions and blocks"); + if let Some(item_sp) = self.current_item { + err.span_label(item_sp, "this is not `async`"); + } + err.emit(); + return hir::ExprKind::Err; } - err.emit(); - return hir::ExprKind::Err; } let span = self.mark_span_with_reason( CompilerDesugaringKind::Await, @@ -5864,7 +5890,7 @@ impl<'a> LoweringContext<'a> { let unit = self.expr_unit(span); let yield_expr = P(self.expr( span, - hir::ExprKind::Yield(P(unit)), + hir::ExprKind::Yield(P(unit), hir::YieldSource::Await), ThinVec::new(), )); self.stmt(span, hir::StmtKind::Expr(yield_expr)) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6ace4c4174b56..d570d34ec4e01 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1306,7 +1306,7 @@ pub struct BodyId { /// /// - an `arguments` array containing the `(x, y)` pattern /// - a `value` containing the `x + y` expression (maybe wrapped in a block) -/// - `is_generator` would be false +/// - `generator_kind` would be `None` /// /// All bodies have an **owner**, which can be accessed via the HIR /// map using `body_owner_def_id()`. @@ -1314,7 +1314,7 @@ pub struct BodyId { pub struct Body { pub arguments: HirVec, pub value: Expr, - pub is_generator: bool, + pub generator_kind: Option, } impl Body { @@ -1325,6 +1325,26 @@ impl Body { } } +/// The type of source expression that caused this generator to be created. +// Not `IsAsync` because we want to eventually add support for `AsyncGen` +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, + RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +pub enum GeneratorKind { + /// An `async` block or function. + Async, + /// A generator literal created via a `yield` inside a closure. + Gen, +} + +impl fmt::Display for GeneratorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + GeneratorKind::Async => "`async` object", + GeneratorKind::Gen => "generator", + }) + } +} + #[derive(Copy, Clone, Debug)] pub enum BodyOwnerKind { /// Functions and methods. @@ -1531,8 +1551,8 @@ pub enum ExprKind { /// /// The final span is the span of the argument block `|...|`. /// - /// This may also be a generator literal, indicated by the final boolean, - /// in that case there is an `GeneratorClause`. + /// This may also be a generator literal or an `async block` as indicated by the + /// `Option`. Closure(CaptureClause, P, BodyId, Span, Option), /// A block (e.g., `'label: { ... }`). Block(P, Option