Skip to content

Commit 6619b83

Browse files
committed
---
yaml --- r: 193485 b: refs/heads/beta c: 9eb596c h: refs/heads/master i: 193483: b78bc17 v: v3
1 parent 979c9bb commit 6619b83

29 files changed

+424
-85
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ refs/heads/automation-fail: 1bf06495443584539b958873e04cc2f864ab10e4
3131
refs/heads/issue-18208-method-dispatch-3-quick-reject: 2009f85b9f99dedcec4404418eda9ddba90258a2
3232
refs/heads/batch: b7fd822592a4fb577552d93010c4a4e14f314346
3333
refs/heads/building: 126db549b038c84269a1e4fe46f051b2c15d6970
34-
refs/heads/beta: e80fc10af19b1c9c4507187ab1c059b445d8f057
34+
refs/heads/beta: 9eb596ce8f4b70ba73e8671f9b42147c91319842
3535
refs/heads/windistfix: 7608dbad651f02e837ed05eef3d74a6662a6e928
3636
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
3737
refs/heads/tmp: de8a23bbc3a7b9cbd7574b5b91a34af59bf030e6

branches/beta/src/doc/reference.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,6 +2555,14 @@ The currently implemented features of the reference compiler are:
25552555
types, e.g. as the return type of a public function.
25562556
This capability may be removed in the future.
25572557

2558+
* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the
2559+
`#[allow_internal_unstable]` attribute, designed
2560+
to allow `std` macros to call
2561+
`#[unstable]`/feature-gated functionality
2562+
internally without imposing on callers
2563+
(i.e. making them behave like function calls in
2564+
terms of encapsulation).
2565+
25582566
If a feature is promoted to a language feature, then all existing programs will
25592567
start to receive compilation warnings about #[feature] directives which enabled
25602568
the new feature (because the directive is no longer necessary). However, if a

branches/beta/src/libcore/num/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
12381238

12391239
macro_rules! impl_from_primitive {
12401240
($T:ty, $to_ty:ident) => (
1241+
#[allow(deprecated)]
12411242
impl FromPrimitive for $T {
12421243
#[inline] fn from_int(n: int) -> Option<$T> { n.$to_ty() }
12431244
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
@@ -1299,6 +1300,7 @@ macro_rules! impl_num_cast {
12991300
($T:ty, $conv:ident) => (
13001301
impl NumCast for $T {
13011302
#[inline]
1303+
#[allow(deprecated)]
13021304
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
13031305
// `$conv` could be generated using `concat_idents!`, but that
13041306
// macro seems to be broken at the moment

branches/beta/src/librustc/metadata/creader.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ impl<'a> CrateReader<'a> {
542542
// overridden in plugin/load.rs
543543
export: false,
544544
use_locally: false,
545+
allow_internal_unstable: false,
545546

546547
body: body,
547548
});

branches/beta/src/librustc/metadata/macro_import.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ impl<'a> MacroLoader<'a> {
166166
Some(sel) => sel.contains_key(&name),
167167
};
168168
def.export = reexport.contains_key(&name);
169+
def.allow_internal_unstable = attr::contains_name(&def.attrs,
170+
"allow_internal_unstable");
171+
debug!("load_macros: loaded: {:?}", def);
169172
self.macros.push(def);
170173
}
171174

branches/beta/src/librustc/middle/stability.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,6 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
362362
/// Helper for discovering nodes to check for stability
363363
pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
364364
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
365-
if is_internal(tcx, e.span) { return; }
366-
367365
let span;
368366
let id = match e.node {
369367
ast::ExprMethodCall(i, _, _) => {
@@ -527,12 +525,13 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
527525
fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
528526
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
529527
if !is_staged_api(tcx, id) { return }
528+
if is_internal(tcx, span) { return }
530529
let ref stability = lookup(tcx, id);
531530
cb(id, span, stability);
532531
}
533532

534533
fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
535-
tcx.sess.codemap().span_is_internal(span)
534+
tcx.sess.codemap().span_allows_unstable(span)
536535
}
537536

538537
fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {

branches/beta/src/librustc/plugin/registry.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ impl<'a> Registry<'a> {
8181
/// This is the most general hook into `libsyntax`'s expansion behavior.
8282
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
8383
self.syntax_exts.push((name, match extension {
84-
NormalTT(ext, _) => NormalTT(ext, Some(self.krate_span)),
85-
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
84+
NormalTT(ext, _, allow_internal_unstable) => {
85+
NormalTT(ext, Some(self.krate_span), allow_internal_unstable)
86+
}
87+
IdentTT(ext, _, allow_internal_unstable) => {
88+
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
89+
}
8690
Decorator(ext) => Decorator(ext),
8791
Modifier(ext) => Modifier(ext),
8892
MultiModifier(ext) => MultiModifier(ext),
@@ -99,7 +103,8 @@ impl<'a> Registry<'a> {
99103
/// It builds for you a `NormalTT` that calls `expander`,
100104
/// and also takes care of interning the macro's name.
101105
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
102-
self.register_syntax_extension(token::intern(name), NormalTT(Box::new(expander), None));
106+
self.register_syntax_extension(token::intern(name),
107+
NormalTT(Box::new(expander), None, false));
103108
}
104109

105110
/// Register a compiler lint pass.

branches/beta/src/librustc_driver/driver.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,12 +493,16 @@ pub fn phase_2_configure_and_expand(sess: &Session,
493493
}
494494
);
495495

496-
// Needs to go *after* expansion to be able to check the results of macro expansion.
497-
time(time_passes, "complete gated feature checking", (), |_| {
496+
// Needs to go *after* expansion to be able to check the results
497+
// of macro expansion. This runs before #[cfg] to try to catch as
498+
// much as possible (e.g. help the programmer avoid platform
499+
// specific differences)
500+
time(time_passes, "complete gated feature checking 1", (), |_| {
498501
let features =
499502
syntax::feature_gate::check_crate(sess.codemap(),
500-
&sess.parse_sess.span_diagnostic,
501-
&krate);
503+
&sess.parse_sess.span_diagnostic,
504+
&krate,
505+
true);
502506
*sess.features.borrow_mut() = features;
503507
sess.abort_if_errors();
504508
});
@@ -521,6 +525,19 @@ pub fn phase_2_configure_and_expand(sess: &Session,
521525
time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
522526
syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
523527

528+
// One final feature gating of the true AST that gets compiled
529+
// later, to make sure we've got everything (e.g. configuration
530+
// can insert new attributes via `cfg_attr`)
531+
time(time_passes, "complete gated feature checking 2", (), |_| {
532+
let features =
533+
syntax::feature_gate::check_crate(sess.codemap(),
534+
&sess.parse_sess.span_diagnostic,
535+
&krate,
536+
false);
537+
*sess.features.borrow_mut() = features;
538+
sess.abort_if_errors();
539+
});
540+
524541
Some(krate)
525542
}
526543

branches/beta/src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
#![feature(hash)]
126126
#![feature(int_uint)]
127127
#![feature(unique)]
128+
#![feature(allow_internal_unstable)]
128129
#![cfg_attr(test, feature(test, rustc_private))]
129130

130131
// Don't link to std. We are std.

branches/beta/src/libstd/sys/common/thread_local.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
//! ```
5656
5757
#![allow(non_camel_case_types)]
58+
#![unstable(feature = "thread_local_internals")]
5859

5960
use prelude::v1::*;
6061

@@ -84,17 +85,14 @@ use sys::thread_local as imp;
8485
/// KEY.set(1 as *mut u8);
8586
/// }
8687
/// ```
87-
#[stable(feature = "rust1", since = "1.0.0")]
8888
pub struct StaticKey {
8989
/// Inner static TLS key (internals), created with by `INIT_INNER` in this
9090
/// module.
91-
#[stable(feature = "rust1", since = "1.0.0")]
9291
pub inner: StaticKeyInner,
9392
/// Destructor for the TLS value.
9493
///
9594
/// See `Key::new` for information about when the destructor runs and how
9695
/// it runs.
97-
#[stable(feature = "rust1", since = "1.0.0")]
9896
pub dtor: Option<unsafe extern fn(*mut u8)>,
9997
}
10098

@@ -131,7 +129,6 @@ pub struct Key {
131129
/// Constant initialization value for static TLS keys.
132130
///
133131
/// This value specifies no destructor by default.
134-
#[stable(feature = "rust1", since = "1.0.0")]
135132
pub const INIT: StaticKey = StaticKey {
136133
inner: INIT_INNER,
137134
dtor: None,
@@ -140,7 +137,6 @@ pub const INIT: StaticKey = StaticKey {
140137
/// Constant initialization value for the inner part of static TLS keys.
141138
///
142139
/// This value allows specific configuration of the destructor for a TLS key.
143-
#[stable(feature = "rust1", since = "1.0.0")]
144140
pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
145141
key: atomic::ATOMIC_USIZE_INIT,
146142
};

branches/beta/src/libstd/thread_local/mod.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub mod scoped;
4545

4646
// Sure wish we had macro hygiene, no?
4747
#[doc(hidden)]
48-
#[stable(feature = "rust1", since = "1.0.0")]
48+
#[unstable(feature = "thread_local_internals")]
4949
pub mod __impl {
5050
pub use super::imp::Key as KeyInner;
5151
pub use super::imp::destroy_value;
@@ -117,6 +117,7 @@ pub struct Key<T> {
117117
/// Declare a new thread local storage key of type `std::thread_local::Key`.
118118
#[macro_export]
119119
#[stable(feature = "rust1", since = "1.0.0")]
120+
#[allow_internal_unstable]
120121
macro_rules! thread_local {
121122
(static $name:ident: $t:ty = $init:expr) => (
122123
static $name: ::std::thread_local::Key<$t> = {
@@ -176,6 +177,7 @@ macro_rules! thread_local {
176177

177178
#[macro_export]
178179
#[doc(hidden)]
180+
#[allow_internal_unstable]
179181
macro_rules! __thread_local_inner {
180182
(static $name:ident: $t:ty = $init:expr) => (
181183
#[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
@@ -337,22 +339,22 @@ mod imp {
337339
use ptr;
338340

339341
#[doc(hidden)]
340-
#[stable(since = "1.0.0", feature = "rust1")]
342+
#[unstable(feature = "thread_local_internals")]
341343
pub struct Key<T> {
342344
// Place the inner bits in an `UnsafeCell` to currently get around the
343345
// "only Sync statics" restriction. This allows any type to be placed in
344346
// the cell.
345347
//
346348
// Note that all access requires `T: 'static` so it can't be a type with
347349
// any borrowed pointers still.
348-
#[stable(since = "1.0.0", feature = "rust1")]
350+
#[unstable(feature = "thread_local_internals")]
349351
pub inner: UnsafeCell<T>,
350352

351353
// Metadata to keep track of the state of the destructor. Remember that
352354
// these variables are thread-local, not global.
353-
#[stable(since = "1.0.0", feature = "rust1")]
355+
#[unstable(feature = "thread_local_internals")]
354356
pub dtor_registered: UnsafeCell<bool>, // should be Cell
355-
#[stable(since = "1.0.0", feature = "rust1")]
357+
#[unstable(feature = "thread_local_internals")]
356358
pub dtor_running: UnsafeCell<bool>, // should be Cell
357359
}
358360

@@ -455,7 +457,7 @@ mod imp {
455457
}
456458

457459
#[doc(hidden)]
458-
#[stable(feature = "rust1", since = "1.0.0")]
460+
#[unstable(feature = "thread_local_internals")]
459461
pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
460462
let ptr = ptr as *mut Key<T>;
461463
// Right before we run the user destructor be sure to flag the
@@ -477,15 +479,15 @@ mod imp {
477479
use sys_common::thread_local::StaticKey as OsStaticKey;
478480

479481
#[doc(hidden)]
480-
#[stable(since = "1.0.0", feature = "rust1")]
482+
#[unstable(feature = "thread_local_internals")]
481483
pub struct Key<T> {
482484
// Statically allocated initialization expression, using an `UnsafeCell`
483485
// for the same reasons as above.
484-
#[stable(since = "1.0.0", feature = "rust1")]
486+
#[unstable(feature = "thread_local_internals")]
485487
pub inner: UnsafeCell<T>,
486488

487489
// OS-TLS key that we'll use to key off.
488-
#[stable(since = "1.0.0", feature = "rust1")]
490+
#[unstable(feature = "thread_local_internals")]
489491
pub os: OsStaticKey,
490492
}
491493

@@ -528,7 +530,7 @@ mod imp {
528530
}
529531

530532
#[doc(hidden)]
531-
#[stable(feature = "rust1", since = "1.0.0")]
533+
#[unstable(feature = "thread_local_internals")]
532534
pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
533535
// The OS TLS ensures that this key contains a NULL value when this
534536
// destructor starts to run. We set it back to a sentinel value of 1 to

branches/beta/src/libstd/thread_local/scoped.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub struct Key<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
6565
/// This macro declares a `static` item on which methods are used to get and
6666
/// set the value stored within.
6767
#[macro_export]
68+
#[allow_internal_unstable]
6869
macro_rules! scoped_thread_local {
6970
(static $name:ident: $t:ty) => (
7071
__scoped_thread_local_inner!(static $name: $t);
@@ -76,6 +77,7 @@ macro_rules! scoped_thread_local {
7677

7778
#[macro_export]
7879
#[doc(hidden)]
80+
#[allow_internal_unstable]
7981
macro_rules! __scoped_thread_local_inner {
8082
(static $name:ident: $t:ty) => (
8183
#[cfg_attr(not(any(windows,

branches/beta/src/libsyntax/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,7 @@ pub struct MacroDef {
17431743
pub imported_from: Option<Ident>,
17441744
pub export: bool,
17451745
pub use_locally: bool,
1746+
pub allow_internal_unstable: bool,
17461747
pub body: Vec<TokenTree>,
17471748
}
17481749

branches/beta/src/libsyntax/codemap.rs

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ pub struct NameAndSpan {
243243
pub name: String,
244244
/// The format with which the macro was invoked.
245245
pub format: MacroFormat,
246+
/// Whether the macro is allowed to use #[unstable]/feature-gated
247+
/// features internally without forcing the whole crate to opt-in
248+
/// to them.
249+
pub allow_internal_unstable: bool,
246250
/// The span of the macro definition itself. The macro may not
247251
/// have a sensible definition span (e.g. something defined
248252
/// completely inside libsyntax) in which case this is None.
@@ -830,41 +834,43 @@ impl CodeMap {
830834
}
831835
}
832836

833-
/// Check if a span is "internal" to a macro. This means that it is entirely generated by a
834-
/// macro expansion and contains no code that was passed in as an argument.
835-
pub fn span_is_internal(&self, span: Span) -> bool {
836-
// first, check if the given expression was generated by a macro or not
837-
// we need to go back the expn_info tree to check only the arguments
838-
// of the initial macro call, not the nested ones.
839-
let mut is_internal = false;
840-
let mut expnid = span.expn_id;
841-
while self.with_expn_info(expnid, |expninfo| {
842-
match expninfo {
843-
Some(ref info) => {
844-
// save the parent expn_id for next loop iteration
845-
expnid = info.call_site.expn_id;
846-
if info.callee.name == "format_args" {
847-
// This is a hack because the format_args builtin calls unstable APIs.
848-
// I spent like 6 hours trying to solve this more generally but am stupid.
849-
is_internal = true;
850-
false
851-
} else if info.callee.span.is_none() {
852-
// it's a compiler built-in, we *really* don't want to mess with it
853-
// so we skip it, unless it was called by a regular macro, in which case
854-
// we will handle the caller macro next turn
855-
is_internal = true;
856-
true // continue looping
837+
/// Check if a span is "internal" to a macro in which #[unstable]
838+
/// items can be used (that is, a macro marked with
839+
/// `#[allow_internal_unstable]`).
840+
pub fn span_allows_unstable(&self, span: Span) -> bool {
841+
debug!("span_allows_unstable(span = {:?})", span);
842+
let mut allows_unstable = false;
843+
let mut expn_id = span.expn_id;
844+
loop {
845+
let quit = self.with_expn_info(expn_id, |expninfo| {
846+
debug!("span_allows_unstable: expninfo = {:?}", expninfo);
847+
expninfo.map_or(/* hit the top level */ true, |info| {
848+
849+
let span_comes_from_this_expansion =
850+
info.callee.span.map_or(span == info.call_site, |mac_span| {
851+
mac_span.lo <= span.lo && span.hi < mac_span.hi
852+
});
853+
854+
debug!("span_allows_unstable: from this expansion? {}, allows unstable? {}",
855+
span_comes_from_this_expansion,
856+
info.callee.allow_internal_unstable);
857+
if span_comes_from_this_expansion {
858+
allows_unstable = info.callee.allow_internal_unstable;
859+
// we've found the right place, stop looking
860+
true
857861
} else {
858-
// was this expression from the current macro arguments ?
859-
is_internal = !( span.lo > info.call_site.lo &&
860-
span.hi < info.call_site.hi );
861-
true // continue looping
862+
// not the right place, keep looking
863+
expn_id = info.call_site.expn_id;
864+
false
862865
}
863-
},
864-
_ => false // stop looping
866+
})
867+
});
868+
if quit {
869+
break
865870
}
866-
}) { /* empty while loop body */ }
867-
return is_internal;
871+
}
872+
debug!("span_allows_unstable? {}", allows_unstable);
873+
allows_unstable
868874
}
869875
}
870876

0 commit comments

Comments
 (0)