Skip to content

Commit

Permalink
Update expression span when transcribing macro args
Browse files Browse the repository at this point in the history
closes #29084
closes #28308
closes #25385
closes #28288
closes #31011
closes #26480
closes #26093
closes #26094
closes #25386
closes #26237
closes #25793
  • Loading branch information
fhahn committed Jan 26, 2016
1 parent faf6d1e commit b285ebc
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/libsyntax/ext/tt/transcribe.rs
Expand Up @@ -10,12 +10,13 @@
use self::LockstepIterSize::*;

use ast;
use ptr;
use ast::{TokenTree, Ident, Name};
use codemap::{Span, DUMMY_SP};
use errors::Handler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use parse::token::{DocComment, MatchNt, SubstNt};
use parse::token::{Token, NtIdent, SpecialMacroVar};
use parse::token::{Token, NtIdent, NtExpr, SpecialMacroVar};
use parse::token;
use parse::lexer::TokenAndSpan;

Expand Down Expand Up @@ -173,6 +174,11 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
}
}

fn update_span(base: Span, expr: &mut ast::Expr) {
expr.span.lo = base.lo;
expr.span.hi = base.hi;
}

/// Return the next token from the TtReader.
/// EFFECT: advances the reader's token field
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
Expand Down Expand Up @@ -279,6 +285,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
}
// FIXME #2887: think about span stuff here
TokenTree::Token(sp, SubstNt(ident, namep)) => {
//println!("SubstNt {:?} {:?}", ident, sp);
r.stack.last_mut().unwrap().idx += 1;
match lookup_cur_matched(r, ident) {
None => {
Expand All @@ -293,10 +300,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
// (a) idents can be in lots of places, so it'd be a pain
// (b) we actually can, since it's a token.
MatchedNonterminal(NtIdent(ref sn, b)) => {
r.cur_span = sn.span;
r.cur_span = sp;
r.cur_tok = token::Ident(sn.node, b);
return ret_val;
}
MatchedNonterminal(NtExpr(ref expr)) => {
let mut expr = (**expr).clone();
update_span(sp, &mut expr);
// FIXME(pcwalton): Bad copy.
r.cur_span = sp;
r.cur_tok = token::Interpolated(NtExpr(ptr::P(expr)));
return ret_val;
}
MatchedNonterminal(ref other_whole_nt) => {
// FIXME(pcwalton): Bad copy.
r.cur_span = sp;
Expand Down
23 changes: 23 additions & 0 deletions src/test/compile-fail/issue-25385.rs
@@ -0,0 +1,23 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.


macro_rules! foo {
($e:expr) => { $e.foo() }
//~^ ERROR no method named `foo` found for type `i32` in the current scope
}

fn main() {
let a = 1i32;
foo!(a);

foo!(1.i32.foo());
//~^ ERROR attempted access of field `i32` on type `_`, but no field with that name was found
}
38 changes: 38 additions & 0 deletions src/test/compile-fail/issue-25386.rs
@@ -0,0 +1,38 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod stuff {
pub struct Item {
c_object: Box<CObj>,
}
pub struct CObj {
name: Option<String>,
}
impl Item {
pub fn new() -> Item {
Item {
c_object: Box::new(CObj { name: None }),
}
}
}
}

macro_rules! check_ptr_exist {
($var:expr, $member:ident) => (
(*$var.c_object).$member.is_some()
//~^ ERROR field `name` of struct `stuff::CObj` is private
//~^^ ERROR field `c_object` of struct `stuff::Item` is private
);
}

fn main() {
let item = stuff::Item::new();
println!("{}", check_ptr_exist!(item, name));
}
34 changes: 34 additions & 0 deletions src/test/compile-fail/issue-25793.rs
@@ -0,0 +1,34 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! width(
($this:expr) => {
$this.width.unwrap()
//~^ ERROR cannot use `self.width` because it was mutably borrowed
}
);

struct HasInfo {
width: Option<usize>
}

impl HasInfo {
fn get_size(&mut self, n: usize) -> usize {
n
}

fn get_other(&mut self) -> usize {
self.get_size(width!(self))
}
}

fn main() {
println!("hello?");
}
20 changes: 20 additions & 0 deletions src/test/compile-fail/issue-26093.rs
@@ -0,0 +1,20 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! not_an_lvalue {
($thing:expr) => {
$thing = 42;
//~^ ERROR invalid left-hand side expression
}
}

fn main() {
not_an_lvalue!(99);
}
23 changes: 23 additions & 0 deletions src/test/compile-fail/issue-26094.rs
@@ -0,0 +1,23 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! some_macro {
($other: expr) => ({
$other(None)
//~^ this function takes 0 parameters but 1 parameter was supplied
})
}

fn some_function() {
}

fn main() {
some_macro!(some_function);
}
22 changes: 22 additions & 0 deletions src/test/compile-fail/issue-26237.rs
@@ -0,0 +1,22 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! macro_panic {
($not_a_function:expr, $some_argument:ident) => {
$not_a_function($some_argument)
//~^ ERROR expected function, found `_`
}
}

fn main() {
let mut value_a = 0;
let mut value_b = 0;
macro_panic!(value_a, value_b);
}
42 changes: 42 additions & 0 deletions src/test/compile-fail/issue-26480.rs
@@ -0,0 +1,42 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern {
fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
}

#[inline(always)]
fn size_of<T>(_: T) -> usize {
::std::mem::size_of::<T>()
}

macro_rules! write {
($arr:expr) => {{
#[allow(non_upper_case_globals)]
const stdout: i32 = 1;
unsafe {
write(stdout, $arr.as_ptr() as *const i8,
$arr.len() * size_of($arr[0]));
//~^ ERROR mismatched types: expected `u64`, found `usize`
}
}}
}

macro_rules! cast {
($x:expr) => ($x as ())
//~^ ERROR non-scalar cast: `i32` as `()`
}

fn main() {
let hello = ['H', 'e', 'y'];
write!(hello);

cast!(2);
}
14 changes: 14 additions & 0 deletions src/test/compile-fail/issue-28308.rs
@@ -0,0 +1,14 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
assert!("foo");
//~^ ERROR cannot apply unary operator `!` to type `&'static str`'`
}
21 changes: 21 additions & 0 deletions src/test/compile-fail/issue-29084.rs
@@ -0,0 +1,21 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! foo {
($d:expr) => {{
fn bar(d: u8) { }
bar(&mut $d);
//~^ ERROR mismatched types: expected `u8`, found `&mut u8`
}}
}

fn main() {
foo!(0u8);
}
38 changes: 38 additions & 0 deletions src/test/compile-fail/issue-31011.rs
@@ -0,0 +1,38 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! log {
( $ctx:expr, $( $args:expr),* ) => {
if $ctx.trace {
//~^ attempted access of field `trace` on type `&T`, but no field with that name was found
println!( $( $args, )* );
}
}
}

// Create a structure.
struct Foo {
trace: bool,
}

// Generic wrapper calls log! with a structure.
fn wrap<T>(context: &T) -> ()
{
log!(context, "entered wrapper");
}

fn main() {
// Create a structure.
let x = Foo { trace: true };
log!(x, "run started");
// Apply a closure which accesses internal fields.
wrap(&x);
log!(x, "run finished");
}

0 comments on commit b285ebc

Please sign in to comment.