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/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/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 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, diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 153397f11b5a0..d2b8c4729a42a 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; @@ -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) } @@ -848,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)) } @@ -1156,7 +1157,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 +4383,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 +4969,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 +5777,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/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/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 383048b5fe72a..3d57a89493e1e 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 c164f5446fd8c..60554a30060bb 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 192e72383acee..c0f56a33eec8f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -817,10 +817,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 04364cd631193..0f4b7aff82bce 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 a45213b06d3a0..5dd1b9e3d53f3 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_allocator/expand.rs b/src/librustc_allocator/expand.rs index 3ec06b17aff22..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(vec![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/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 6a01d7454bee5..df0957254cc09 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 f78cc2f38a93a..6a5f62aec1537 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -509,8 +509,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() + )) } } @@ -737,7 +738,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_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index afdc9f5c02ae1..ed56d351e90d0 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 ac5efa4640661..90ab8eead3fc1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1864,7 +1864,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 @@ -2650,7 +2650,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 fe54e2a0f183f..4e197f1ed4ecf 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -190,12 +190,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 1fcdf71337251..764ff0e15d5a4 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1310,7 +1310,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>( /// 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_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 18ed91689ec18..616728d541848 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -772,9 +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::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool, - }), + 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 a127c96068549..0fbd0666ad1c1 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 47ed3d684b2b6..5623016c2e5e7 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() @@ -174,7 +190,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), @@ -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(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: 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]`"); @@ -226,7 +247,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)) @@ -241,11 +261,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 +601,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/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), } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 864f19933a5f1..519081732033d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1788,32 +1788,71 @@ 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() { 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))); - } - 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; @@ -1841,28 +1880,24 @@ 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 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))); - } - 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 { - 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(); } } } @@ -3922,52 +3957,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, @@ -3987,12 +3976,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), @@ -4097,13 +4082,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, &[][..], @@ -4173,7 +4198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }, - ); + )); assert!(!substs.has_escaping_bound_vars()); assert!(!ty.has_escaping_bound_vars()); 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/html/render.rs b/src/librustdoc/html/render.rs index 362706820593e..b42a78f1e226a 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, "")?; 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..318a5a3a82a2e 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,91 @@ 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), + } + } + + pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { + ExpnInfo { + call_site, + 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, + edition: self.edition, } } } @@ -699,31 +726,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, diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index a2cf4a2a82d8d..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(vec![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/ext/expand.rs b/src/libsyntax/ext/expand.rs index d433e6c5a896f..be90def0bdd2a 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,23 +188,6 @@ 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. - 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()) - } - } - - MacroBang(Symbol::intern(&path_str)) -} - pub struct Invocation { pub kind: InvocationKind, fragment_kind: AstFragmentKind, @@ -388,8 +370,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 +491,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 +530,22 @@ 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), - }); - - 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 +556,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) @@ -693,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!(), @@ -701,21 +671,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 = |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 +696,39 @@ 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, - }); 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(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 +737,6 @@ 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 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 +793,19 @@ 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()? - } - }; - - invoc.expansion_data.mark.set_expn_info(expn_info); - let span = span.with_ctxt(self.cx.backtrace()); + match &ext.kind { + SyntaxExtensionKind::Derive(expander) | + SyntaxExtensionKind::LegacyDerive(expander) => { + 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..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(vec![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 cbaf12529c101..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(vec![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/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index cf54eacc3d46c..1fe6094fca686 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -2,9 +2,10 @@ 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; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; @@ -67,11 +68,25 @@ 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::core_intrinsics, + 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, + ) + }), ); )* } @@ -148,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 3dd17207cb8e9..b868f5b273c4e 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,26 @@ 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, - }); + let allow_internal_unstable = Some([sym::fmt_internals][..].into()); + register(Symbol::intern("format_args"), SyntaxExtension { + 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, + ..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..45e65288a24ee 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -347,18 +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(vec![ - 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 c20dc6cb2d7cd..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(vec![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 cffecdd0f18e7..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(vec![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..4dbd4ccda910a 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) }) } @@ -118,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] @@ -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 { @@ -220,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 { @@ -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), }); @@ -613,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 @@ -622,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()) }) } @@ -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. @@ -682,6 +673,30 @@ 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, + format, + def_site: None, + default_transparency: Transparency::SemiTransparent, + 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 { 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() + )); } 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); } 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 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/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`. 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 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: