Skip to content
Closed
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
45bb409
Only show methods that appear in the impl block for types in the Impl…
ebarnard Jun 3, 2019
5fa8b52
move stray run-pass const tests into const/ folder
RalfJung Jun 9, 2019
ea1bec3
Turn down the myriad-closures test
alexcrichton Jun 14, 2019
007aaba
Remove unnecessary lift calls
Zoxc Jun 14, 2019
56e30e1
Tweak transparent enums and unions diagnostic spans
estebank Jun 11, 2019
f06b761
review comments: move diagnostic code out of happy path
estebank Jun 12, 2019
961ba8f
syntax: Factor out common fields from `SyntaxExtension` variants
petrochenkov Jun 16, 2019
679000c
allow_internal_unstable: Avoid some more allocations
petrochenkov Jun 16, 2019
085a8d0
syntax: Remove `DummyResolver`
petrochenkov Jun 17, 2019
68e1141
resolve: Avoid creating fresh syntax extensions for all non-macro att…
petrochenkov Jun 17, 2019
8ec502e
syntax: Introduce `default`/`with_unstable` constructors for `ExpnInfo`
petrochenkov Jun 17, 2019
2de2278
syntax: Move `default_transparency` into `ExpnInfo`
petrochenkov Jun 17, 2019
1ff3bce
hygiene: Avoid some unnecessary `ExpnInfo` clones
petrochenkov Jun 17, 2019
e152554
resolve/expand: Move expansion info setting to a single earlier point
petrochenkov Jun 18, 2019
0f9dc6c
Make MaybeUninit #[repr(transparent)]
mjbshaw Jun 12, 2019
dedf2ed
rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`.
eddyb Jun 16, 2019
831ddf7
ci: Add a script for generating CPU usage graphs
alexcrichton Jun 14, 2019
d8eea92
create an issue for miri even in status test-fail
RalfJung Jun 18, 2019
830d15d
Rollup merge of #61505 - ebarnard:doc-shrink, r=GuillaumeGomez
Centril Jun 18, 2019
26880f6
Rollup merge of #61701 - RalfJung:const-tests, r=cramertj
Centril Jun 18, 2019
43ebb35
Rollup merge of #61748 - estebank:transparent-span, r=Centril
Centril Jun 18, 2019
32254ac
Rollup merge of #61802 - mjbshaw:maybe-uninit-transparent, r=cramertj
Centril Jun 18, 2019
4301ebd
Rollup merge of #61839 - alexcrichton:pr-and-master-builds, r=pietroa…
Centril Jun 18, 2019
78f9399
Rollup merge of #61842 - Zoxc:trim-lift, r=eddyb
Centril Jun 18, 2019
ebf9696
Rollup merge of #61843 - alexcrichton:disable-myriad-closures, r=piet…
Centril Jun 18, 2019
f755231
Rollup merge of #61896 - eddyb:correct-self-ctor, r=petrochenkov
Centril Jun 18, 2019
0bb197c
Rollup merge of #61898 - petrochenkov:sekind, r=eddyb
Centril Jun 18, 2019
0b8da29
Rollup merge of #61938 - RalfJung:miri-toolstate, r=kennytm
Centril Jun 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions src/ci/cpu-usage-over-time.py
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/doc/unstable-book/src/language-features/plugin.md
Original file line number Diff line number Diff line change
@@ -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).


49 changes: 49 additions & 0 deletions src/etc/cpu-usage-over-time-plot.sh
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
16 changes: 15 additions & 1 deletion src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ use crate::mem::ManuallyDrop;
///
/// # Layout
///
/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
/// `MaybeUninit<T>` 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::<Option<bool>>(), 1);
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
/// ```
///
/// If `T` is FFI-safe, then so is `MaybeUninit<T>`.
///
/// 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<T>` and
/// `Option<MaybeUninit<T>>` 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<T>`.
/// `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<T>` 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<T> {
uninit: (),
value: ManuallyDrop<T>,
27 changes: 14 additions & 13 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -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<u32>,
node_id_to_hir_id: IndexVec<NodeId, hir::HirId>,

allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>,
}

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<Lrc<[Symbol]>>,
) -> 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(<expr>)`
@@ -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 = <expr>;
9 changes: 8 additions & 1 deletion src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
@@ -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,
30 changes: 8 additions & 22 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
@@ -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<V>(&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<V>(&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);

4 changes: 2 additions & 2 deletions src/librustc/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
@@ -194,10 +194,10 @@ pub struct QueryResponse<'tcx, R> {
pub value: R,
}

pub type Canonicalized<'tcx, V> = Canonical<'tcx, <V as Lift<'tcx>>::Lifted>;
pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;

pub type CanonicalizedQueryResponse<'tcx, T> =
&'tcx Canonical<'tcx, QueryResponse<'tcx, <T as Lift<'tcx>>::Lifted>>;
&'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;

/// Indicates whether or not we were able to prove the query to be
/// true.
16 changes: 8 additions & 8 deletions src/librustc/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
@@ -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<CanonicalizedQueryResponse<'tcx, R>>
where
K: TypeFoldable<'tcx>,
R: Debug + Lift<'tcx> + TypeFoldable<'tcx>,
Canonical<'tcx, <QueryResponse<'tcx, R> 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<CanonicalizedQueryResponse<'tcx, T>>
where
T: Debug + Lift<'tcx> + TypeFoldable<'tcx>,
Canonical<'tcx, <QueryResponse<'tcx, T> 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, <T as Lift<'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<QueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<'tcx> + Lift<'tcx>,
T: Debug + TypeFoldable<'tcx>,
{
let tcx = self.tcx;

5 changes: 0 additions & 5 deletions src/librustc/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
5 changes: 1 addition & 4 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
@@ -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),
10 changes: 3 additions & 7 deletions src/librustc/traits/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
}
}
1 change: 0 additions & 1 deletion src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 0 additions & 1 deletion src/librustc/traits/query/normalize.rs
Original file line number Diff line number Diff line change
@@ -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;
}
6 changes: 3 additions & 3 deletions src/librustc/traits/query/type_op/mod.rs
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/librustc/traits/query/type_op/normalize.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ where

impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
where
T: Normalizable<'tcx>,
T: Normalizable<'tcx> + 'tcx,
{
type QueryResponse = T;

7 changes: 1 addition & 6 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
@@ -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)
}
9 changes: 6 additions & 3 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
@@ -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(),
13 changes: 5 additions & 8 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -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<u128> {
pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option<u128> {
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<bool> {
pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
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<u64> {
pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
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))
}
21 changes: 7 additions & 14 deletions src/librustc_allocator/expand.rs
Original file line number Diff line number Diff line change
@@ -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<Item>) -> SmallVec<[P<Item>; 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));
50 changes: 24 additions & 26 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>();
(trait_name, SyntaxExtension::Derive(
Box::new(ProcMacroDerive {
client,
attrs: attrs.clone(),
}),
attrs,
root.edition,
))
let helper_attrs =
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(
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.
13 changes: 6 additions & 7 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -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));
}
7 changes: 4 additions & 3 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
@@ -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: {:?}",
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Original file line number Diff line number Diff line change
@@ -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))
}
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -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<T>(&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;
4 changes: 2 additions & 2 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion src/librustc_mir/dataflow/drop_flag_effects.rs
Original file line number Diff line number Diff line change
@@ -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 {
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/constant.rs
Original file line number Diff line number Diff line change
@@ -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);
7 changes: 1 addition & 6 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
@@ -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> {
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<Constructor<'tcx>>>
{
match *pat.kind {
22 changes: 7 additions & 15 deletions src/librustc_plugin/registry.rs
Original file line number Diff line number Diff line change
@@ -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,28 +88,21 @@ 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));
}

/// 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.
5 changes: 2 additions & 3 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -772,9 +772,8 @@ impl<'a> Resolver<'a> {
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
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) {
12 changes: 11 additions & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -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<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Res>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,

@@ -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<SyntaxExtension> {
self.non_macro_attrs[mark_used as usize].clone()
}

/// Runs the function on each namespace.
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
f(self, TypeNS);
57 changes: 34 additions & 23 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -114,6 +114,22 @@ fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKi
candidate.is_none() || requirement.is_none() || candidate == requirement
}

// We don't want to format a path using pretty-printing,
// `format!("{}", path)`, because that tries to insert
// line-breaks and is slow.
fn fast_print_path(path: &ast::Path) -> String {
let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() {
if i != 0 {
path_str.push_str("::");
}
if segment.ident.name != kw::PathRoot {
path_str.push_str(&segment.ident.as_str())
}
}
path_str
}

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) =>
3 changes: 1 addition & 2 deletions src/librustc_traits/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
@@ -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),
}
197 changes: 111 additions & 86 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -1788,32 +1788,71 @@ fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec<De
false
}

/// Emit an error when encountering more or less than one variant in a transparent enum.
fn bad_variant_count<'tcx>(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<Item = Span>,
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<Res, ErrorReported> {
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());

12 changes: 3 additions & 9 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
@@ -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
21 changes: 13 additions & 8 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
@@ -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<String, fmt::Error> {

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<bool>, is_on_foreign_type: bool) -> fmt::Result {
use_absolute: Option<bool>, 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, "</div>")?;

4 changes: 2 additions & 2 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
@@ -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<Res> {
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<Res> {
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")));
}
}
174 changes: 88 additions & 86 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
@@ -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,46 +549,26 @@ 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<dyn ProcMacro + sync::Sync + sync::Send>,
/// Whitelist of unstable features that are treated as stable inside this macro.
allow_internal_unstable: Option<Lrc<[Symbol]>>,
/// Edition of the crate in which this macro is defined.
edition: Edition,
},
Box<dyn ProcMacro + sync::Sync + sync::Send>,
),

/// An AST-based function-like macro.
LegacyBang {
LegacyBang(
/// An expander with signature TokenStream -> AST.
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
/// 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<Lrc<[Symbol]>>,
/// 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<dyn TTMacroExpander + sync::Sync + sync::Send>,
),

/// A token-based attribute macro.
Attr(
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
/// The first TokenSteam is the attribute itself, the second is the annotated item.
/// The produced TokenSteam replaces the input TokenSteam.
Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
/// 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<dyn MultiItemModifier + sync::Sync + sync::Send>,
/// Names of helper attributes registered by this macro.
Vec<Symbol>,
/// 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<Lrc<[Symbol]>>,
/// 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<Symbol>,
/// 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<SyntaxExtension>) {}

fn resolve_imports(&mut self) {}
fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
Err(Determinacy::Determined)
}
fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _invoc_id: Mark,
_derives_in_scope: Vec<ast::Path>, _force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy> {
Err(Determinacy::Determined)
}
fn check_unused_macros(&self) {}
}

#[derive(Clone)]
pub struct ModuleData {
pub mod_path: Vec<ast::Ident>,
13 changes: 4 additions & 9 deletions src/libsyntax/ext/derive.rs
Original file line number Diff line number Diff line change
@@ -60,15 +60,10 @@ pub fn add_derived_markers<T>(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| {
180 changes: 35 additions & 145 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
@@ -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<AstFragment> {
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,29 +663,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
invoc: Invocation,
ext: &SyntaxExtension)
-> Option<AstFragment> {
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!(),
};
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<Span>,
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)
}
}
}
12 changes: 7 additions & 5 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}
12 changes: 3 additions & 9 deletions src/libsyntax/std_inject.rs
Original file line number Diff line number Diff line change
@@ -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))
}

13 changes: 4 additions & 9 deletions src/libsyntax/test.rs
Original file line number Diff line number Diff line change
@@ -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,
40 changes: 21 additions & 19 deletions src/libsyntax_ext/deriving/mod.rs
Original file line number Diff line number Diff line change
@@ -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<ast::Expr>>)
-> P<ast::Expr> {
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);

70 changes: 31 additions & 39 deletions src/libsyntax_ext/lib.rs
Original file line number Diff line number Diff line change
@@ -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<NamedSyntaxExtension>,
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);
16 changes: 4 additions & 12 deletions src/libsyntax_ext/proc_macro_decls.rs
Original file line number Diff line number Diff line change
@@ -347,18 +347,10 @@ fn mk_decls(
custom_macros: &[ProcMacroDef],
) -> P<ast::Item> {
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);
15 changes: 5 additions & 10 deletions src/libsyntax_ext/test.rs
Original file line number Diff line number Diff line change
@@ -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)))
};
15 changes: 5 additions & 10 deletions src/libsyntax_ext/test_case.rs
Original file line number Diff line number Diff line change
@@ -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))
};

73 changes: 44 additions & 29 deletions src/libsyntax_pos/hygiene.rs
Original file line number Diff line number Diff line change
@@ -59,13 +59,12 @@ pub struct Mark(u32);
#[derive(Clone, Debug)]
struct MarkData {
parent: Mark,
default_transparency: Transparency,
expn_info: Option<ExpnInfo>,
}

/// 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,20 +112,14 @@ impl Mark {

#[inline]
pub fn expn_info(self) -> Option<ExpnInfo> {
HygieneData::with(|data| data.expn_info(self))
HygieneData::with(|data| data.expn_info(self).cloned())
}

#[inline]
pub fn set_expn_info(self, info: ExpnInfo) {
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<ExpnInfo> {
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<ExpnInfo> {
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<ExpnInfo>) {
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<Span>,
/// 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 {
18 changes: 5 additions & 13 deletions src/test/run-pass-fulldeps/auxiliary/plugin-args.rs
Original file line number Diff line number Diff line change
@@ -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()
));
}
6 changes: 3 additions & 3 deletions src/test/run-pass-fulldeps/myriad-closures.rs
Original file line number Diff line number Diff line change
@@ -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);
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ pub struct Gcm<E>(E);
impl<E> Gcm<E> {
pub fn crash(e: E) -> Self {
Self::<E>(e)
//~^ ERROR type arguments are not allowed for this type
}
}

9 changes: 9 additions & 0 deletions src/test/ui/issues/issue-57924.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0109]: type arguments are not allowed for this type
--> $DIR/issue-57924.rs:5:16
|
LL | Self::<E>(e)
| ^ type argument not allowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0109`.
11 changes: 11 additions & 0 deletions src/test/ui/issues/issue-61882-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
struct A<T>(T);

impl A<&'static u8> {
fn f() {
let x = 0;
Self(&x);
//~^ ERROR `x` does not live long enough
}
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-61882-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
9 changes: 9 additions & 0 deletions src/test/ui/issues/issue-61882.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
struct A<T>(T);

impl A<bool> {
const B: A<u8> = Self(0);
//~^ ERROR mismatched types
//~| ERROR mismatched types
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/issues/issue-61882.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/issue-61882.rs:4:27
|
LL | const B: A<u8> = 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<u8> = Self(0);
| ^^^^^^^ expected u8, found bool
|
= note: expected type `A<u8>`
found type `A<bool>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
Loading