Skip to content

Commit 19311b6

Browse files
committed
auto merge of #13316 : eddyb/rust/ast-ptr, r=brson
Replaces Gc<T> in the AST with a custom owned smart pointer, P<T>. Fixes #7929. ## Benefits * **Identity** (affinity?): sharing AST nodes is bad for the various analysis passes (e.g. one could bypass borrowck with a shared `ExprAddrOf` node taking a mutable borrow), the only reason we haven't hit any serious issues with it is because of inefficient folding passes which will always deduplicate any such shared nodes. Even if we were to switch to an arena, this would still hold, i.e. we wouldn't just use `&'a T` in the AST, but rather an wrapper (`P<'a, T>`?). * **Immutability**: `P<T>` disallows mutating its inner `T` (unless that contains an `Unsafe` interior, which won't happen in the AST), unlike `~T`. * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`, the latter even when the input and output types differ (as it would be the case with arenas or an AST with type parameters to toggle macro support). Also, various algorithms have been changed from copying `Gc<T>` to using `&T` and iterators. * **Maintainability**: there is another reason I didn't just replace `Gc<T>` with `~T`: `P<T>` provides a fixed interface (`Deref`, `and_then` and `map`) which can remain fully functional even if the implementation changes (using a special thread-local heap, for example). Moreover, switching to, e.g. `P<'a, T>` (for a contextual arena) is easy and mostly automated.
2 parents 931b115 + 8577343 commit 19311b6

File tree

126 files changed

+4912
-5037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+4912
-5037
lines changed

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ DEPS_graphviz := std
7070
DEPS_green := std native:context_switch
7171
DEPS_rustuv := std native:uv native:uv_support
7272
DEPS_native := std
73-
DEPS_syntax := std term serialize log fmt_macros debug
73+
DEPS_syntax := std term serialize log fmt_macros debug arena
7474
DEPS_rustc := syntax flate arena serialize getopts rbml \
7575
time log graphviz debug rustc_llvm rustc_back
7676
DEPS_rustc_llvm := native:rustllvm libc std

src/libfourcc/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,9 @@ use syntax::ext::base::{ExtCtxt, MacExpr};
6363
use syntax::ext::build::AstBuilder;
6464
use syntax::parse::token;
6565
use syntax::parse::token::InternedString;
66+
use syntax::ptr::P;
6667
use rustc::plugin::Registry;
6768

68-
use std::gc::Gc;
69-
7069
#[plugin_registrar]
7170
pub fn plugin_registrar(reg: &mut Registry) {
7271
reg.register_macro("fourcc", expand_syntax_ext);
@@ -135,7 +134,7 @@ struct Ident {
135134
}
136135

137136
fn parse_tts(cx: &ExtCtxt,
138-
tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
137+
tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
139138
let p = &mut cx.new_parser_from_tts(tts);
140139
let ex = p.parse_expr();
141140
let id = if p.token == token::EOF {
@@ -156,7 +155,7 @@ fn parse_tts(cx: &ExtCtxt,
156155
fn target_endian_little(cx: &ExtCtxt, sp: Span) -> bool {
157156
let meta = cx.meta_name_value(sp, InternedString::new("target_endian"),
158157
ast::LitStr(InternedString::new("little"), ast::CookedStr));
159-
contains(cx.cfg().as_slice(), meta)
158+
contains(cx.cfg().as_slice(), &*meta)
160159
}
161160

162161
// FIXME (10872): This is required to prevent an LLVM assert on Windows

src/libhexfloat/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,9 @@ use syntax::ext::base;
5757
use syntax::ext::base::{ExtCtxt, MacExpr};
5858
use syntax::ext::build::AstBuilder;
5959
use syntax::parse::token;
60+
use syntax::ptr::P;
6061
use rustc::plugin::Registry;
6162

62-
use std::gc::Gc;
63-
6463
#[plugin_registrar]
6564
pub fn plugin_registrar(reg: &mut Registry) {
6665
reg.register_macro("hexfloat", expand_syntax_ext);
@@ -122,7 +121,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
122121

123122
let s = match expr.node {
124123
// expression is a literal
125-
ast::ExprLit(lit) => match lit.node {
124+
ast::ExprLit(ref lit) => match lit.node {
126125
// string literal
127126
ast::LitStr(ref s, _) => {
128127
s.clone()
@@ -167,7 +166,7 @@ struct Ident {
167166
}
168167

169168
fn parse_tts(cx: &ExtCtxt,
170-
tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
169+
tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
171170
let p = &mut cx.new_parser_from_tts(tts);
172171
let ex = p.parse_expr();
173172
let id = if p.token == token::EOF {

src/libregex_macros/lib.rs

+17-19
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ extern crate syntax;
2626
extern crate rustc;
2727

2828
use std::rc::Rc;
29-
use std::gc::{Gc, GC};
3029

3130
use syntax::ast;
3231
use syntax::codemap;
@@ -35,6 +34,7 @@ use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
3534
use syntax::parse::token;
3635
use syntax::print::pprust;
3736
use syntax::fold::Folder;
37+
use syntax::ptr::P;
3838

3939
use rustc::plugin::Registry;
4040

@@ -111,7 +111,7 @@ struct NfaGen<'a> {
111111
}
112112

113113
impl<'a> NfaGen<'a> {
114-
fn code(&mut self) -> Gc<ast::Expr> {
114+
fn code(&mut self) -> P<ast::Expr> {
115115
// Most or all of the following things are used in the quasiquoted
116116
// expression returned.
117117
let num_cap_locs = 2 * self.prog.num_captures();
@@ -332,7 +332,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
332332

333333
// Generates code for the `add` method, which is responsible for adding
334334
// zero-width states to the next queue of states to visit.
335-
fn add_insts(&self) -> Gc<ast::Expr> {
335+
fn add_insts(&self) -> P<ast::Expr> {
336336
let arms = self.prog.insts.iter().enumerate().map(|(pc, inst)| {
337337
let nextpc = pc + 1;
338338
let body = match *inst {
@@ -433,7 +433,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
433433

434434
// Generates the code for the `step` method, which processes all states
435435
// in the current queue that consume a single character.
436-
fn step_insts(&self) -> Gc<ast::Expr> {
436+
fn step_insts(&self) -> P<ast::Expr> {
437437
let arms = self.prog.insts.iter().enumerate().map(|(pc, inst)| {
438438
let nextpc = pc + 1;
439439
let body = match *inst {
@@ -524,17 +524,15 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
524524
// Translates a character class into a match expression.
525525
// This avoids a binary search (and is hopefully replaced by a jump
526526
// table).
527-
fn match_class(&self, casei: bool, ranges: &[(char, char)]) -> Gc<ast::Expr> {
528-
let expr_true = quote_expr!(self.cx, true);
529-
527+
fn match_class(&self, casei: bool, ranges: &[(char, char)]) -> P<ast::Expr> {
530528
let mut arms = ranges.iter().map(|&(mut start, mut end)| {
531529
if casei {
532530
start = start.to_uppercase();
533531
end = end.to_uppercase();
534532
}
535533
let pat = self.cx.pat(self.sp, ast::PatRange(quote_expr!(self.cx, $start),
536534
quote_expr!(self.cx, $end)));
537-
self.cx.arm(self.sp, vec!(pat), expr_true)
535+
self.cx.arm(self.sp, vec!(pat), quote_expr!(self.cx, true))
538536
}).collect::<Vec<ast::Arm>>();
539537

540538
arms.push(self.wild_arm_expr(quote_expr!(self.cx, false)));
@@ -546,7 +544,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
546544
// Generates code for checking a literal prefix of the search string.
547545
// The code is only generated if the regex *has* a literal prefix.
548546
// Otherwise, a no-op is returned.
549-
fn check_prefix(&self) -> Gc<ast::Expr> {
547+
fn check_prefix(&self) -> P<ast::Expr> {
550548
if self.prog.prefix.len() == 0 {
551549
self.empty_block()
552550
} else {
@@ -570,32 +568,32 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
570568
// A wild-card arm is automatically added that executes a no-op. It will
571569
// never be used, but is added to satisfy the compiler complaining about
572570
// non-exhaustive patterns.
573-
fn match_insts(&self, mut arms: Vec<ast::Arm>) -> Gc<ast::Expr> {
571+
fn match_insts(&self, mut arms: Vec<ast::Arm>) -> P<ast::Expr> {
574572
arms.push(self.wild_arm_expr(self.empty_block()));
575573
self.cx.expr_match(self.sp, quote_expr!(self.cx, pc), arms)
576574
}
577575

578-
fn empty_block(&self) -> Gc<ast::Expr> {
576+
fn empty_block(&self) -> P<ast::Expr> {
579577
quote_expr!(self.cx, {})
580578
}
581579

582580
// Creates a match arm for the instruction at `pc` with the expression
583581
// `body`.
584-
fn arm_inst(&self, pc: uint, body: Gc<ast::Expr>) -> ast::Arm {
582+
fn arm_inst(&self, pc: uint, body: P<ast::Expr>) -> ast::Arm {
585583
let pc_pat = self.cx.pat_lit(self.sp, quote_expr!(self.cx, $pc));
586584

587585
self.cx.arm(self.sp, vec!(pc_pat), body)
588586
}
589587

590588
// Creates a wild-card match arm with the expression `body`.
591-
fn wild_arm_expr(&self, body: Gc<ast::Expr>) -> ast::Arm {
589+
fn wild_arm_expr(&self, body: P<ast::Expr>) -> ast::Arm {
592590
ast::Arm {
593591
attrs: vec!(),
594-
pats: vec!(box(GC) ast::Pat{
592+
pats: vec!(P(ast::Pat{
595593
id: ast::DUMMY_NODE_ID,
596594
span: self.sp,
597595
node: ast::PatWild(ast::PatWildSingle),
598-
}),
596+
})),
599597
guard: None,
600598
body: body,
601599
}
@@ -605,8 +603,8 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
605603
// Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
606604
// on each element in `xs`.
607605
fn vec_expr<T, It: Iterator<T>>(&self, xs: It,
608-
to_expr: |&ExtCtxt, T| -> Gc<ast::Expr>)
609-
-> Gc<ast::Expr> {
606+
to_expr: |&ExtCtxt, T| -> P<ast::Expr>)
607+
-> P<ast::Expr> {
610608
let exprs = xs.map(|x| to_expr(self.cx, x)).collect();
611609
self.cx.expr_vec(self.sp, exprs)
612610
}
@@ -618,13 +616,13 @@ fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> {
618616
let mut parser = cx.new_parser_from_tts(tts);
619617
let entry = cx.expander().fold_expr(parser.parse_expr());
620618
let regex = match entry.node {
621-
ast::ExprLit(lit) => {
619+
ast::ExprLit(ref lit) => {
622620
match lit.node {
623621
ast::LitStr(ref s, _) => s.to_string(),
624622
_ => {
625623
cx.span_err(entry.span, format!(
626624
"expected string literal but got `{}`",
627-
pprust::lit_to_string(&*lit)).as_slice());
625+
pprust::lit_to_string(&**lit)).as_slice());
628626
return None
629627
}
630628
}

0 commit comments

Comments
 (0)