Skip to content

Commit b285ebc

Browse files
committed
Update expression span when transcribing macro args
closes #29084 closes #28308 closes #25385 closes #28288 closes #31011 closes #26480 closes #26093 closes #26094 closes #25386 closes #26237 closes #25793
1 parent faf6d1e commit b285ebc

11 files changed

+292
-2
lines changed

src/libsyntax/ext/tt/transcribe.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
use self::LockstepIterSize::*;
1111

1212
use ast;
13+
use ptr;
1314
use ast::{TokenTree, Ident, Name};
1415
use codemap::{Span, DUMMY_SP};
1516
use errors::Handler;
1617
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
1718
use parse::token::{DocComment, MatchNt, SubstNt};
18-
use parse::token::{Token, NtIdent, SpecialMacroVar};
19+
use parse::token::{Token, NtIdent, NtExpr, SpecialMacroVar};
1920
use parse::token;
2021
use parse::lexer::TokenAndSpan;
2122

@@ -173,6 +174,11 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
173174
}
174175
}
175176

177+
fn update_span(base: Span, expr: &mut ast::Expr) {
178+
expr.span.lo = base.lo;
179+
expr.span.hi = base.hi;
180+
}
181+
176182
/// Return the next token from the TtReader.
177183
/// EFFECT: advances the reader's token field
178184
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
@@ -279,6 +285,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
279285
}
280286
// FIXME #2887: think about span stuff here
281287
TokenTree::Token(sp, SubstNt(ident, namep)) => {
288+
//println!("SubstNt {:?} {:?}", ident, sp);
282289
r.stack.last_mut().unwrap().idx += 1;
283290
match lookup_cur_matched(r, ident) {
284291
None => {
@@ -293,10 +300,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
293300
// (a) idents can be in lots of places, so it'd be a pain
294301
// (b) we actually can, since it's a token.
295302
MatchedNonterminal(NtIdent(ref sn, b)) => {
296-
r.cur_span = sn.span;
303+
r.cur_span = sp;
297304
r.cur_tok = token::Ident(sn.node, b);
298305
return ret_val;
299306
}
307+
MatchedNonterminal(NtExpr(ref expr)) => {
308+
let mut expr = (**expr).clone();
309+
update_span(sp, &mut expr);
310+
// FIXME(pcwalton): Bad copy.
311+
r.cur_span = sp;
312+
r.cur_tok = token::Interpolated(NtExpr(ptr::P(expr)));
313+
return ret_val;
314+
}
300315
MatchedNonterminal(ref other_whole_nt) => {
301316
// FIXME(pcwalton): Bad copy.
302317
r.cur_span = sp;

src/test/compile-fail/issue-25385.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
macro_rules! foo {
13+
($e:expr) => { $e.foo() }
14+
//~^ ERROR no method named `foo` found for type `i32` in the current scope
15+
}
16+
17+
fn main() {
18+
let a = 1i32;
19+
foo!(a);
20+
21+
foo!(1.i32.foo());
22+
//~^ ERROR attempted access of field `i32` on type `_`, but no field with that name was found
23+
}

src/test/compile-fail/issue-25386.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
mod stuff {
12+
pub struct Item {
13+
c_object: Box<CObj>,
14+
}
15+
pub struct CObj {
16+
name: Option<String>,
17+
}
18+
impl Item {
19+
pub fn new() -> Item {
20+
Item {
21+
c_object: Box::new(CObj { name: None }),
22+
}
23+
}
24+
}
25+
}
26+
27+
macro_rules! check_ptr_exist {
28+
($var:expr, $member:ident) => (
29+
(*$var.c_object).$member.is_some()
30+
//~^ ERROR field `name` of struct `stuff::CObj` is private
31+
//~^^ ERROR field `c_object` of struct `stuff::Item` is private
32+
);
33+
}
34+
35+
fn main() {
36+
let item = stuff::Item::new();
37+
println!("{}", check_ptr_exist!(item, name));
38+
}

src/test/compile-fail/issue-25793.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! width(
12+
($this:expr) => {
13+
$this.width.unwrap()
14+
//~^ ERROR cannot use `self.width` because it was mutably borrowed
15+
}
16+
);
17+
18+
struct HasInfo {
19+
width: Option<usize>
20+
}
21+
22+
impl HasInfo {
23+
fn get_size(&mut self, n: usize) -> usize {
24+
n
25+
}
26+
27+
fn get_other(&mut self) -> usize {
28+
self.get_size(width!(self))
29+
}
30+
}
31+
32+
fn main() {
33+
println!("hello?");
34+
}

src/test/compile-fail/issue-26093.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! not_an_lvalue {
12+
($thing:expr) => {
13+
$thing = 42;
14+
//~^ ERROR invalid left-hand side expression
15+
}
16+
}
17+
18+
fn main() {
19+
not_an_lvalue!(99);
20+
}

src/test/compile-fail/issue-26094.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! some_macro {
12+
($other: expr) => ({
13+
$other(None)
14+
//~^ this function takes 0 parameters but 1 parameter was supplied
15+
})
16+
}
17+
18+
fn some_function() {
19+
}
20+
21+
fn main() {
22+
some_macro!(some_function);
23+
}

src/test/compile-fail/issue-26237.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! macro_panic {
12+
($not_a_function:expr, $some_argument:ident) => {
13+
$not_a_function($some_argument)
14+
//~^ ERROR expected function, found `_`
15+
}
16+
}
17+
18+
fn main() {
19+
let mut value_a = 0;
20+
let mut value_b = 0;
21+
macro_panic!(value_a, value_b);
22+
}

src/test/compile-fail/issue-26480.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern {
12+
fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
13+
}
14+
15+
#[inline(always)]
16+
fn size_of<T>(_: T) -> usize {
17+
::std::mem::size_of::<T>()
18+
}
19+
20+
macro_rules! write {
21+
($arr:expr) => {{
22+
#[allow(non_upper_case_globals)]
23+
const stdout: i32 = 1;
24+
unsafe {
25+
write(stdout, $arr.as_ptr() as *const i8,
26+
$arr.len() * size_of($arr[0]));
27+
//~^ ERROR mismatched types: expected `u64`, found `usize`
28+
}
29+
}}
30+
}
31+
32+
macro_rules! cast {
33+
($x:expr) => ($x as ())
34+
//~^ ERROR non-scalar cast: `i32` as `()`
35+
}
36+
37+
fn main() {
38+
let hello = ['H', 'e', 'y'];
39+
write!(hello);
40+
41+
cast!(2);
42+
}

src/test/compile-fail/issue-28308.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
assert!("foo");
13+
//~^ ERROR cannot apply unary operator `!` to type `&'static str`'`
14+
}

src/test/compile-fail/issue-29084.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! foo {
12+
($d:expr) => {{
13+
fn bar(d: u8) { }
14+
bar(&mut $d);
15+
//~^ ERROR mismatched types: expected `u8`, found `&mut u8`
16+
}}
17+
}
18+
19+
fn main() {
20+
foo!(0u8);
21+
}

src/test/compile-fail/issue-31011.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! log {
12+
( $ctx:expr, $( $args:expr),* ) => {
13+
if $ctx.trace {
14+
//~^ attempted access of field `trace` on type `&T`, but no field with that name was found
15+
println!( $( $args, )* );
16+
}
17+
}
18+
}
19+
20+
// Create a structure.
21+
struct Foo {
22+
trace: bool,
23+
}
24+
25+
// Generic wrapper calls log! with a structure.
26+
fn wrap<T>(context: &T) -> ()
27+
{
28+
log!(context, "entered wrapper");
29+
}
30+
31+
fn main() {
32+
// Create a structure.
33+
let x = Foo { trace: true };
34+
log!(x, "run started");
35+
// Apply a closure which accesses internal fields.
36+
wrap(&x);
37+
log!(x, "run finished");
38+
}

0 commit comments

Comments
 (0)