Skip to content

Commit 09ca362

Browse files
committed
---
yaml --- r: 224866 b: refs/heads/tmp c: 68f7928 h: refs/heads/master v: v3
1 parent 3ddfc6a commit 09ca362

25 files changed

+277
-35
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ refs/tags/0.11.0: e1247cb1d0d681be034adb4b558b5a0c0d5720f9
2525
refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
2626
refs/heads/beta: 83dee3dfbb452a7558193f3ce171b3c60bf4a499
2727
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
28-
refs/heads/tmp: d3e089f08bd55fc5e663400f513f77e567636628
28+
refs/heads/tmp: 68f79288bf1ac2b014277750cbf59416c91f7d04
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3030
refs/tags/homu-tmp: e58601ab085591c71a27ae82137fc313222c2270
3131
refs/tags/1.0.0-beta: 8cbb92b53468ee2b0c2d3eeb8567005953d40828

branches/tmp/src/doc/nomicon/exotic-sizes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ support values.
8585
Safe code need not worry about ZSTs, but *unsafe* code must be careful about the
8686
consequence of types with no size. In particular, pointer offsets are no-ops,
8787
and standard allocators (including jemalloc, the one used by default in Rust)
88-
generally consider passing in `0` for the size of an allocation as Undefined
89-
Behaviour.
88+
may return `nullptr` when a zero-sized allocation is requested, which is
89+
indistinguishable from out of memory.
9090

9191

9292

branches/tmp/src/doc/nomicon/repr-rust.md

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ struct A {
3636
}
3737
```
3838

39-
will be 32-bit aligned assuming these primitives are aligned to their size.
40-
It will therefore have a size that is a multiple of 32-bits. It will potentially
41-
*really* become:
39+
will be 32-bit aligned on an architecture that aligns these primitives to their
40+
respective sizes. The whole struct will therefore have a size that is a multiple
41+
of 32-bits. It will potentially become:
4242

4343
```rust
4444
struct A {
@@ -50,10 +50,10 @@ struct A {
5050
}
5151
```
5252

53-
There is *no indirection* for these types; all data is stored contiguously as
54-
you would expect in C. However with the exception of arrays (which are densely
55-
packed and in-order), the layout of data is not by default specified in Rust.
56-
Given the two following struct definitions:
53+
There is *no indirection* for these types; all data is stored within the struct,
54+
as you would expect in C. However with the exception of arrays (which are
55+
densely packed and in-order), the layout of data is not by default specified in
56+
Rust. Given the two following struct definitions:
5757

5858
```rust
5959
struct A {
@@ -62,18 +62,17 @@ struct A {
6262
}
6363

6464
struct B {
65-
x: i32,
65+
a: i32,
6666
b: u64,
6767
}
6868
```
6969

7070
Rust *does* guarantee that two instances of A have their data laid out in
71-
exactly the same way. However Rust *does not* guarantee that an instance of A
72-
has the same field ordering or padding as an instance of B (in practice there's
73-
no particular reason why they wouldn't, other than that its not currently
74-
guaranteed).
71+
exactly the same way. However Rust *does not* currently guarantee that an
72+
instance of A has the same field ordering or padding as an instance of B, though
73+
in practice there's no reason why they wouldn't.
7574

76-
With A and B as written, this is basically nonsensical, but several other
75+
With A and B as written, this point would seem to be pedantic, but several other
7776
features of Rust make it desirable for the language to play with data layout in
7877
complex ways.
7978

@@ -133,18 +132,21 @@ struct FooRepr {
133132
}
134133
```
135134

136-
And indeed this is approximately how it would be laid out in general
137-
(modulo the size and position of `tag`). However there are several cases where
138-
such a representation is inefficient. The classic case of this is Rust's
139-
"null pointer optimization". Given a pointer that is known to not be null
140-
(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer
141-
by using null as a special value. The net result is that
142-
`size_of::<Option<&T>>() == size_of::<&T>()`
135+
And indeed this is approximately how it would be laid out in general (modulo the
136+
size and position of `tag`).
137+
138+
However there are several cases where such a representation is inefficient. The
139+
classic case of this is Rust's "null pointer optimization": an enum consisting
140+
of a single outer unit variant (e.g. `None`) and a (potentially nested) non-
141+
nullable pointer variant (e.g. `&T`) makes the tag unnecessary, because a null
142+
pointer value can safely be interpreted to mean that the unit variant is chosen
143+
instead. The net result is that, for example, `size_of::<Option<&T>>() ==
144+
size_of::<&T>()`.
143145

144-
There are many types in Rust that are, or contain, "not null" pointers such as
146+
There are many types in Rust that are, or contain, non-nullable pointers such as
145147
`Box<T>`, `Vec<T>`, `String`, `&T`, and `&mut T`. Similarly, one can imagine
146148
nested enums pooling their tags into a single discriminant, as they are by
147-
definition known to have a limited range of valid values. In principle enums can
149+
definition known to have a limited range of valid values. In principle enums could
148150
use fairly elaborate algorithms to cache bits throughout nested types with
149151
special constrained representations. As such it is *especially* desirable that
150152
we leave enum layout unspecified today.

branches/tmp/src/librustc_typeck/astconv.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,9 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
16621662
// handled specially and will not descend into this routine.
16631663
this.ty_infer(None, None, None, ast_ty.span)
16641664
}
1665+
ast::TyMac(_) => {
1666+
tcx.sess.span_bug(ast_ty.span, "unexpanded type macro found conversion")
1667+
}
16651668
};
16661669

16671670
tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, typ);

branches/tmp/src/librustdoc/clean/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,9 @@ impl Clean<Type> for ast::Ty {
16111611
TyTypeof(..) => {
16121612
panic!("Unimplemented type {:?}", self.node)
16131613
},
1614+
TyMac(ref m) => {
1615+
cx.tcx().sess.span_bug(m.span, "unexpanded type macro found during cleaning")
1616+
}
16141617
}
16151618
}
16161619
}

branches/tmp/src/libsyntax/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,8 @@ pub enum Ty_ {
14711471
/// TyInfer means the type should be inferred instead of it having been
14721472
/// specified. This can appear anywhere in a type.
14731473
TyInfer,
1474+
// A macro in the type position.
1475+
TyMac(Mac)
14741476
}
14751477

14761478
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]

branches/tmp/src/libsyntax/ext/base.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ pub trait MacResult {
290290
fn make_stmts(self: Box<Self>) -> Option<SmallVector<P<ast::Stmt>>> {
291291
make_stmts_default!(self)
292292
}
293+
294+
fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
295+
None
296+
}
293297
}
294298

295299
macro_rules! make_MacEager {
@@ -322,6 +326,7 @@ make_MacEager! {
322326
items: SmallVector<P<ast::Item>>,
323327
impl_items: SmallVector<P<ast::ImplItem>>,
324328
stmts: SmallVector<P<ast::Stmt>>,
329+
ty: P<ast::Ty>,
325330
}
326331

327332
impl MacResult for MacEager {
@@ -359,6 +364,10 @@ impl MacResult for MacEager {
359364
}
360365
None
361366
}
367+
368+
fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
369+
self.ty
370+
}
362371
}
363372

364373
/// Fill-in macro expansion result, to allow compilation to continue
@@ -405,15 +414,24 @@ impl DummyResult {
405414
}
406415
}
407416

417+
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
418+
P(ast::Ty {
419+
id: ast::DUMMY_NODE_ID,
420+
node: ast::TyInfer,
421+
span: sp
422+
})
423+
}
408424
}
409425

410426
impl MacResult for DummyResult {
411427
fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
412428
Some(DummyResult::raw_expr(self.span))
413429
}
430+
414431
fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
415432
Some(P(DummyResult::raw_pat(self.span)))
416433
}
434+
417435
fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
418436
// this code needs a comment... why not always just return the Some() ?
419437
if self.expr_only {
@@ -422,13 +440,15 @@ impl MacResult for DummyResult {
422440
Some(SmallVector::zero())
423441
}
424442
}
443+
425444
fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::ImplItem>>> {
426445
if self.expr_only {
427446
None
428447
} else {
429448
Some(SmallVector::zero())
430449
}
431450
}
451+
432452
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Stmt>>> {
433453
Some(SmallVector::one(P(
434454
codemap::respan(self.span,

branches/tmp/src/libsyntax/ext/expand.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,45 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
15421542
}, rewritten_body)
15431543
}
15441544

1545+
pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
1546+
let t = match t.node.clone() {
1547+
ast::Ty_::TyMac(mac) => {
1548+
if fld.cx.ecfg.features.unwrap().type_macros {
1549+
let expanded_ty = match expand_mac_invoc(mac, t.span,
1550+
|r| r.make_ty(),
1551+
mark_ty,
1552+
fld) {
1553+
Some(ty) => ty,
1554+
None => {
1555+
return DummyResult::raw_ty(t.span);
1556+
}
1557+
};
1558+
1559+
// Keep going, outside-in.
1560+
let fully_expanded = fld.fold_ty(expanded_ty);
1561+
fld.cx.bt_pop();
1562+
1563+
fully_expanded.map(|t| ast::Ty {
1564+
id: ast::DUMMY_NODE_ID,
1565+
node: t.node,
1566+
span: t.span,
1567+
})
1568+
} else {
1569+
feature_gate::emit_feature_err(
1570+
&fld.cx.parse_sess.span_diagnostic,
1571+
"type_macros",
1572+
t.span,
1573+
"type macros are experimental (see issue: #27336)");
1574+
1575+
DummyResult::raw_ty(t.span)
1576+
}
1577+
}
1578+
_ => t
1579+
};
1580+
1581+
fold::noop_fold_ty(t, fld)
1582+
}
1583+
15451584
/// A tree-folder that performs macro expansion
15461585
pub struct MacroExpander<'a, 'b:'a> {
15471586
pub cx: &'a mut ExtCtxt<'b>,
@@ -1592,6 +1631,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
15921631
.into_iter().map(|i| i.expect_impl_item()).collect()
15931632
}
15941633

1634+
fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1635+
expand_type(ty, self)
1636+
}
1637+
15951638
fn new_span(&mut self, span: Span) -> Span {
15961639
new_span(self.cx, span)
15971640
}
@@ -1744,6 +1787,10 @@ fn mark_impl_item(ii: P<ast::ImplItem>, m: Mrk) -> P<ast::ImplItem> {
17441787
.expect_one("marking an impl item didn't return exactly one impl item")
17451788
}
17461789

1790+
fn mark_ty(ty: P<ast::Ty>, m: Mrk) -> P<ast::Ty> {
1791+
Marker { mark: m }.fold_ty(ty)
1792+
}
1793+
17471794
/// Check that there are no macro invocations left in the AST:
17481795
pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) {
17491796
visit::walk_crate(&mut MacroExterminator{sess:sess}, krate);

branches/tmp/src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
117117
self.ensure_complete_parse(false);
118118
Some(ret)
119119
}
120+
121+
fn make_ty(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Ty>> {
122+
let ret = self.parser.borrow_mut().parse_ty();
123+
self.ensure_complete_parse(true);
124+
Some(ret)
125+
}
120126
}
121127

122128
struct MacroRulesMacroExpander {

branches/tmp/src/libsyntax/feature_gate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
172172

173173
// Allows associated type defaults
174174
("associated_type_defaults", "1.2.0", Active),
175+
// Allows macros to appear in the type position.
176+
177+
("type_macros", "1.3.0", Active),
175178
];
176179
// (changing above list without updating src/doc/reference.md makes @cmr sad)
177180

@@ -354,6 +357,7 @@ pub struct Features {
354357
pub const_fn: bool,
355358
pub static_recursion: bool,
356359
pub default_type_parameter_fallback: bool,
360+
pub type_macros: bool,
357361
}
358362

359363
impl Features {
@@ -380,6 +384,7 @@ impl Features {
380384
const_fn: false,
381385
static_recursion: false,
382386
default_type_parameter_fallback: false,
387+
type_macros: false,
383388
}
384389
}
385390
}
@@ -883,6 +888,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
883888
const_fn: cx.has_feature("const_fn"),
884889
static_recursion: cx.has_feature("static_recursion"),
885890
default_type_parameter_fallback: cx.has_feature("default_type_parameter_fallback"),
891+
type_macros: cx.has_feature("type_macros"),
886892
}
887893
}
888894

branches/tmp/src/libsyntax/fold.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
429429
TyPolyTraitRef(bounds) => {
430430
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
431431
}
432+
TyMac(mac) => {
433+
TyMac(fld.fold_mac(mac))
434+
}
432435
},
433436
span: fld.new_span(span)
434437
})

branches/tmp/src/libsyntax/parse/parser.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
5151
use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
5252
use ast::{TtDelimited, TtSequence, TtToken};
5353
use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
54+
use ast::{TyMac};
5455
use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer};
5556
use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
5657
use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
@@ -1369,8 +1370,20 @@ impl<'a> Parser<'a> {
13691370
} else if self.check(&token::ModSep) ||
13701371
self.token.is_ident() ||
13711372
self.token.is_path() {
1372-
// NAMED TYPE
1373-
try!(self.parse_ty_path())
1373+
let path = try!(self.parse_path(LifetimeAndTypesWithoutColons));
1374+
if self.check(&token::Not) {
1375+
// MACRO INVOCATION
1376+
try!(self.bump());
1377+
let delim = try!(self.expect_open_delim());
1378+
let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
1379+
seq_sep_none(),
1380+
|p| p.parse_token_tree()));
1381+
let hi = self.span.hi;
1382+
TyMac(spanned(lo, hi, MacInvocTT(path, tts, EMPTY_CTXT)))
1383+
} else {
1384+
// NAMED TYPE
1385+
TyPath(None, path)
1386+
}
13741387
} else if try!(self.eat(&token::Underscore) ){
13751388
// TYPE TO BE INFERRED
13761389
TyInfer

branches/tmp/src/libsyntax/print/pprust.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,9 @@ impl<'a> State<'a> {
734734
ast::TyInfer => {
735735
try!(word(&mut self.s, "_"));
736736
}
737+
ast::TyMac(ref m) => {
738+
try!(self.print_mac(m, token::Paren));
739+
}
737740
}
738741
self.end()
739742
}

branches/tmp/src/libsyntax/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
405405
visitor.visit_expr(&**expression)
406406
}
407407
TyInfer => {}
408+
TyMac(ref mac) => {
409+
visitor.visit_mac(mac)
410+
}
408411
}
409412
}
410413

0 commit comments

Comments
 (0)