Auto merge of #31089 - fhahn:macro-ice, r=pnkfelix
This is a work in progress PR that potentially should fix #29084, #28308, #25385, #28288, #31011. I think this may also adresse parts of #2887. The problem in this issues seems to be that when transcribing macro arguments, we just clone the argument Nonterminal, which still has to original spans. This leads to the unprintable spans. One solution would be to update the spans of the inserted argument to match the argument in the macro definition. So for [this testcase](https://github.com/rust-lang/rust/compare/master...fhahn:macro-ice?expand=1#diff-f7def7420c51621640707b6337726876R2) the error message would be displayed in the macro definition: src/test/compile-fail/issue-31011.rs:4:12: 4:22 error: attempted access of field `trace` on type `&T`, but no field with that name was found src/test/compile-fail/issue-31011.rs:4 if $ctx.trace { Currently I've added a very simple `update_span` function, which updates the span of the outer-most expression of a `NtExpr`, but this `update_span` function should be updated to handle all Nonterminals. But I'm pretty new to the macro system and would like to check if this approach makes sense, before doing that.
This commit is contained in:
commit
8256c470a5
12 changed files with 354 additions and 30 deletions
|
@ -233,7 +233,6 @@ macro_rules! maybe_whole {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
|
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
|
||||||
-> Vec<Attribute> {
|
-> Vec<Attribute> {
|
||||||
if let Some(ref attrs) = rhs {
|
if let Some(ref attrs) = rhs {
|
||||||
|
@ -255,6 +254,7 @@ pub struct Parser<'a> {
|
||||||
pub cfg: CrateConfig,
|
pub cfg: CrateConfig,
|
||||||
/// the previous token or None (only stashed sometimes).
|
/// the previous token or None (only stashed sometimes).
|
||||||
pub last_token: Option<Box<token::Token>>,
|
pub last_token: Option<Box<token::Token>>,
|
||||||
|
last_token_interpolated: bool,
|
||||||
pub buffer: [TokenAndSpan; 4],
|
pub buffer: [TokenAndSpan; 4],
|
||||||
pub buffer_start: isize,
|
pub buffer_start: isize,
|
||||||
pub buffer_end: isize,
|
pub buffer_end: isize,
|
||||||
|
@ -362,6 +362,7 @@ impl<'a> Parser<'a> {
|
||||||
span: span,
|
span: span,
|
||||||
last_span: span,
|
last_span: span,
|
||||||
last_token: None,
|
last_token: None,
|
||||||
|
last_token_interpolated: false,
|
||||||
buffer: [
|
buffer: [
|
||||||
placeholder.clone(),
|
placeholder.clone(),
|
||||||
placeholder.clone(),
|
placeholder.clone(),
|
||||||
|
@ -542,6 +543,19 @@ impl<'a> Parser<'a> {
|
||||||
self.commit_stmt(&[edible], &[])
|
self.commit_stmt(&[edible], &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns the span of expr, if it was not interpolated or the span of the interpolated token
|
||||||
|
fn interpolated_or_expr_span(&self,
|
||||||
|
expr: PResult<'a, P<Expr>>)
|
||||||
|
-> PResult<'a, (Span, P<Expr>)> {
|
||||||
|
expr.map(|e| {
|
||||||
|
if self.last_token_interpolated {
|
||||||
|
(self.last_span, e)
|
||||||
|
} else {
|
||||||
|
(e.span, e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
|
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
|
||||||
self.check_strict_keywords();
|
self.check_strict_keywords();
|
||||||
self.check_reserved_keywords();
|
self.check_reserved_keywords();
|
||||||
|
@ -933,6 +947,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
self.last_token_interpolated = self.token.is_interpolated();
|
||||||
let next = if self.buffer_start == self.buffer_end {
|
let next = if self.buffer_start == self.buffer_end {
|
||||||
self.reader.real_token()
|
self.reader.real_token()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2328,18 +2343,20 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
|
let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
|
||||||
|
|
||||||
let b = try!(self.parse_bottom_expr());
|
let b = self.parse_bottom_expr();
|
||||||
self.parse_dot_or_call_expr_with(b, attrs)
|
let (span, b) = try!(self.interpolated_or_expr_span(b));
|
||||||
|
self.parse_dot_or_call_expr_with(b, span.lo, attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_dot_or_call_expr_with(&mut self,
|
pub fn parse_dot_or_call_expr_with(&mut self,
|
||||||
e0: P<Expr>,
|
e0: P<Expr>,
|
||||||
|
lo: BytePos,
|
||||||
attrs: ThinAttributes)
|
attrs: ThinAttributes)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
// Stitch the list of outer attributes onto the return value.
|
// Stitch the list of outer attributes onto the return value.
|
||||||
// A little bit ugly, but the best way given the current code
|
// A little bit ugly, but the best way given the current code
|
||||||
// structure
|
// structure
|
||||||
self.parse_dot_or_call_expr_with_(e0)
|
self.parse_dot_or_call_expr_with_(e0, lo)
|
||||||
.map(|expr|
|
.map(|expr|
|
||||||
expr.map(|mut expr| {
|
expr.map(|mut expr| {
|
||||||
expr.attrs.update(|a| a.prepend(attrs));
|
expr.attrs.update(|a| a.prepend(attrs));
|
||||||
|
@ -2366,7 +2383,8 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_dot_suffix(&mut self,
|
fn parse_dot_suffix(&mut self,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
ident_span: Span,
|
ident_span: Span,
|
||||||
self_value: P<Expr>)
|
self_value: P<Expr>,
|
||||||
|
lo: BytePos)
|
||||||
-> PResult<'a, P<Expr>> {
|
-> PResult<'a, P<Expr>> {
|
||||||
let (_, tys, bindings) = if self.eat(&token::ModSep) {
|
let (_, tys, bindings) = if self.eat(&token::ModSep) {
|
||||||
try!(self.expect_lt());
|
try!(self.expect_lt());
|
||||||
|
@ -2380,8 +2398,6 @@ impl<'a> Parser<'a> {
|
||||||
self.span_err(last_span, "type bindings are only permitted on trait paths");
|
self.span_err(last_span, "type bindings are only permitted on trait paths");
|
||||||
}
|
}
|
||||||
|
|
||||||
let lo = self_value.span.lo;
|
|
||||||
|
|
||||||
Ok(match self.token {
|
Ok(match self.token {
|
||||||
// expr.f() method call.
|
// expr.f() method call.
|
||||||
token::OpenDelim(token::Paren) => {
|
token::OpenDelim(token::Paren) => {
|
||||||
|
@ -2414,9 +2430,8 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
|
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: BytePos) -> PResult<'a, P<Expr>> {
|
||||||
let mut e = e0;
|
let mut e = e0;
|
||||||
let lo = e.span.lo;
|
|
||||||
let mut hi;
|
let mut hi;
|
||||||
loop {
|
loop {
|
||||||
// expr.f
|
// expr.f
|
||||||
|
@ -2427,7 +2442,7 @@ impl<'a> Parser<'a> {
|
||||||
hi = self.span.hi;
|
hi = self.span.hi;
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e));
|
e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e, lo));
|
||||||
}
|
}
|
||||||
token::Literal(token::Integer(n), suf) => {
|
token::Literal(token::Integer(n), suf) => {
|
||||||
let sp = self.span;
|
let sp = self.span;
|
||||||
|
@ -2480,7 +2495,7 @@ impl<'a> Parser<'a> {
|
||||||
let dot_pos = self.last_span.hi;
|
let dot_pos = self.last_span.hi;
|
||||||
e = try!(self.parse_dot_suffix(special_idents::invalid,
|
e = try!(self.parse_dot_suffix(special_idents::invalid,
|
||||||
mk_sp(dot_pos, dot_pos),
|
mk_sp(dot_pos, dot_pos),
|
||||||
e));
|
e, lo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -2715,27 +2730,31 @@ impl<'a> Parser<'a> {
|
||||||
let ex = match self.token {
|
let ex = match self.token {
|
||||||
token::Not => {
|
token::Not => {
|
||||||
self.bump();
|
self.bump();
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = self.parse_prefix_expr(None);
|
||||||
hi = e.span.hi;
|
let (span, e) = try!(self.interpolated_or_expr_span(e));
|
||||||
|
hi = span.hi;
|
||||||
self.mk_unary(UnNot, e)
|
self.mk_unary(UnNot, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::Minus) => {
|
token::BinOp(token::Minus) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = self.parse_prefix_expr(None);
|
||||||
hi = e.span.hi;
|
let (span, e) = try!(self.interpolated_or_expr_span(e));
|
||||||
|
hi = span.hi;
|
||||||
self.mk_unary(UnNeg, e)
|
self.mk_unary(UnNeg, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::Star) => {
|
token::BinOp(token::Star) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = self.parse_prefix_expr(None);
|
||||||
hi = e.span.hi;
|
let (span, e) = try!(self.interpolated_or_expr_span(e));
|
||||||
|
hi = span.hi;
|
||||||
self.mk_unary(UnDeref, e)
|
self.mk_unary(UnDeref, e)
|
||||||
}
|
}
|
||||||
token::BinOp(token::And) | token::AndAnd => {
|
token::BinOp(token::And) | token::AndAnd => {
|
||||||
try!(self.expect_and());
|
try!(self.expect_and());
|
||||||
let m = try!(self.parse_mutability());
|
let m = try!(self.parse_mutability());
|
||||||
let e = try!(self.parse_prefix_expr(None));
|
let e = self.parse_prefix_expr(None);
|
||||||
hi = e.span.hi;
|
let (span, e) = try!(self.interpolated_or_expr_span(e));
|
||||||
|
hi = span.hi;
|
||||||
ExprAddrOf(m, e)
|
ExprAddrOf(m, e)
|
||||||
}
|
}
|
||||||
token::Ident(..) if self.token.is_keyword(keywords::In) => {
|
token::Ident(..) if self.token.is_keyword(keywords::In) => {
|
||||||
|
@ -2753,9 +2772,10 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
|
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
let subexpression = try!(self.parse_prefix_expr(None));
|
let e = self.parse_prefix_expr(None);
|
||||||
hi = subexpression.span.hi;
|
let (span, e) = try!(self.interpolated_or_expr_span(e));
|
||||||
ExprBox(subexpression)
|
hi = span.hi;
|
||||||
|
ExprBox(e)
|
||||||
}
|
}
|
||||||
_ => return self.parse_dot_or_call_expr(Some(attrs))
|
_ => return self.parse_dot_or_call_expr(Some(attrs))
|
||||||
};
|
};
|
||||||
|
@ -2790,12 +2810,21 @@ impl<'a> Parser<'a> {
|
||||||
try!(self.parse_prefix_expr(attrs))
|
try!(self.parse_prefix_expr(attrs))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if self.expr_is_complete(&*lhs) {
|
if self.expr_is_complete(&*lhs) {
|
||||||
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
|
// Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
|
||||||
return Ok(lhs);
|
return Ok(lhs);
|
||||||
}
|
}
|
||||||
self.expected_tokens.push(TokenType::Operator);
|
self.expected_tokens.push(TokenType::Operator);
|
||||||
while let Some(op) = AssocOp::from_token(&self.token) {
|
while let Some(op) = AssocOp::from_token(&self.token) {
|
||||||
|
|
||||||
|
let lhs_span = if self.last_token_interpolated {
|
||||||
|
self.last_span
|
||||||
|
} else {
|
||||||
|
lhs.span
|
||||||
|
};
|
||||||
|
|
||||||
let cur_op_span = self.span;
|
let cur_op_span = self.span;
|
||||||
let restrictions = if op.is_assign_like() {
|
let restrictions = if op.is_assign_like() {
|
||||||
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
|
self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
|
||||||
|
@ -2812,12 +2841,12 @@ impl<'a> Parser<'a> {
|
||||||
// Special cases:
|
// Special cases:
|
||||||
if op == AssocOp::As {
|
if op == AssocOp::As {
|
||||||
let rhs = try!(self.parse_ty());
|
let rhs = try!(self.parse_ty());
|
||||||
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
|
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
|
||||||
ExprCast(lhs, rhs), None);
|
ExprCast(lhs, rhs), None);
|
||||||
continue
|
continue
|
||||||
} else if op == AssocOp::Colon {
|
} else if op == AssocOp::Colon {
|
||||||
let rhs = try!(self.parse_ty());
|
let rhs = try!(self.parse_ty());
|
||||||
lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
|
lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
|
||||||
ExprType(lhs, rhs), None);
|
ExprType(lhs, rhs), None);
|
||||||
continue
|
continue
|
||||||
} else if op == AssocOp::DotDot {
|
} else if op == AssocOp::DotDot {
|
||||||
|
@ -2839,7 +2868,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs {
|
let (lhs_span, rhs_span) = (lhs_span, if let Some(ref x) = rhs {
|
||||||
x.span
|
x.span
|
||||||
} else {
|
} else {
|
||||||
cur_op_span
|
cur_op_span
|
||||||
|
@ -2879,14 +2908,14 @@ impl<'a> Parser<'a> {
|
||||||
AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
|
AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
|
||||||
AssocOp::Greater | AssocOp::GreaterEqual => {
|
AssocOp::Greater | AssocOp::GreaterEqual => {
|
||||||
let ast_op = op.to_ast_binop().unwrap();
|
let ast_op = op.to_ast_binop().unwrap();
|
||||||
let (lhs_span, rhs_span) = (lhs.span, rhs.span);
|
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
|
||||||
let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
|
let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
|
||||||
self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
|
self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
|
||||||
}
|
}
|
||||||
AssocOp::Assign =>
|
AssocOp::Assign =>
|
||||||
self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs), None),
|
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprAssign(lhs, rhs), None),
|
||||||
AssocOp::Inplace =>
|
AssocOp::Inplace =>
|
||||||
self.mk_expr(lhs.span.lo, rhs.span.hi, ExprInPlace(lhs, rhs), None),
|
self.mk_expr(lhs_span.lo, rhs.span.hi, ExprInPlace(lhs, rhs), None),
|
||||||
AssocOp::AssignOp(k) => {
|
AssocOp::AssignOp(k) => {
|
||||||
let aop = match k {
|
let aop = match k {
|
||||||
token::Plus => BiAdd,
|
token::Plus => BiAdd,
|
||||||
|
@ -2900,7 +2929,7 @@ impl<'a> Parser<'a> {
|
||||||
token::Shl => BiShl,
|
token::Shl => BiShl,
|
||||||
token::Shr => BiShr
|
token::Shr => BiShr
|
||||||
};
|
};
|
||||||
let (lhs_span, rhs_span) = (lhs.span, rhs.span);
|
let (lhs_span, rhs_span) = (lhs_span, rhs.span);
|
||||||
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
|
||||||
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
|
self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
|
||||||
}
|
}
|
||||||
|
@ -3834,7 +3863,8 @@ impl<'a> Parser<'a> {
|
||||||
let e = self.mk_mac_expr(span.lo, span.hi,
|
let e = self.mk_mac_expr(span.lo, span.hi,
|
||||||
mac.and_then(|m| m.node),
|
mac.and_then(|m| m.node),
|
||||||
None);
|
None);
|
||||||
let e = try!(self.parse_dot_or_call_expr_with(e, attrs));
|
let lo = e.span.lo;
|
||||||
|
let e = try!(self.parse_dot_or_call_expr_with(e, lo, attrs));
|
||||||
let e = try!(self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e)));
|
let e = try!(self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e)));
|
||||||
try!(self.handle_expression_like_statement(
|
try!(self.handle_expression_like_statement(
|
||||||
e,
|
e,
|
||||||
|
|
|
@ -223,6 +223,14 @@ impl Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the token is interpolated.
|
||||||
|
pub fn is_interpolated(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Interpolated(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the token is an interpolated path.
|
/// Returns `true` if the token is an interpolated path.
|
||||||
pub fn is_path(&self) -> bool {
|
pub fn is_path(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
24
src/test/compile-fail/issue-25385.rs
Normal file
24
src/test/compile-fail/issue-25385.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// 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);
|
||||||
|
//~^ NOTE in this expansion of foo!
|
||||||
|
|
||||||
|
foo!(1i32.foo());
|
||||||
|
//~^ ERROR no method named `foo` found for type `i32` in the current scope
|
||||||
|
}
|
40
src/test/compile-fail/issue-25386.rs
Normal file
40
src/test/compile-fail/issue-25386.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// 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));
|
||||||
|
//~^ NOTE in this expansion of check_ptr_exist!
|
||||||
|
//~^^ NOTE in this expansion of check_ptr_exist!
|
||||||
|
}
|
33
src/test/compile-fail/issue-25793.rs
Normal file
33
src/test/compile-fail/issue-25793.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// 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))
|
||||||
|
//~^ NOTE in this expansion of width!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
21
src/test/compile-fail/issue-26093.rs
Normal file
21
src/test/compile-fail/issue-26093.rs
Normal file
|
@ -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! not_an_lvalue {
|
||||||
|
($thing:expr) => {
|
||||||
|
$thing = 42;
|
||||||
|
//~^ ERROR invalid left-hand side expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
not_an_lvalue!(99);
|
||||||
|
//~^ NOTE in this expansion of not_an_lvalue!
|
||||||
|
}
|
23
src/test/compile-fail/issue-26094.rs
Normal file
23
src/test/compile-fail/issue-26094.rs
Normal file
|
@ -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);
|
||||||
|
//~^ in this expansion of some_macro!
|
||||||
|
}
|
23
src/test/compile-fail/issue-26237.rs
Normal file
23
src/test/compile-fail/issue-26237.rs
Normal file
|
@ -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! 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);
|
||||||
|
//~^ in this expansion of macro_panic!
|
||||||
|
}
|
44
src/test/compile-fail/issue-26480.rs
Normal file
44
src/test/compile-fail/issue-26480.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cast {
|
||||||
|
($x:expr) => ($x as ())
|
||||||
|
//~^ ERROR non-scalar cast: `i32` as `()`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let hello = ['H', 'e', 'y'];
|
||||||
|
write!(hello);
|
||||||
|
//~^ NOTE in this expansion of write!
|
||||||
|
|
||||||
|
cast!(2);
|
||||||
|
//~^ NOTE in this expansion of cast!
|
||||||
|
}
|
17
src/test/compile-fail/issue-28308.rs
Normal file
17
src/test/compile-fail/issue-28308.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// this error is dispayed in `<std macros>`
|
||||||
|
// error-pattern:cannot apply unary operator `!` to type `&'static str`
|
||||||
|
// error-pattern:in this expansion of assert!
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert!("foo");
|
||||||
|
}
|
22
src/test/compile-fail/issue-29084.rs
Normal file
22
src/test/compile-fail/issue-29084.rs
Normal file
|
@ -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! foo {
|
||||||
|
($d:expr) => {{
|
||||||
|
fn bar(d: u8) { }
|
||||||
|
bar(&mut $d);
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo!(0u8);
|
||||||
|
//~^ NOTE in this expansion of foo!
|
||||||
|
}
|
39
src/test/compile-fail/issue-31011.rs
Normal file
39
src/test/compile-fail/issue-31011.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// 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 {
|
||||||
|
//~^ ERROR attempted access of field `trace` on type `&T`, but no field with that name
|
||||||
|
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");
|
||||||
|
//~^ in this expansion of log!
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue