Auto merge of #35747 - jonathandturner:rollup, r=jonathandturner

Rollup of 23 pull requests

- Successful merges: #34370, #35415, #35595, #35610, #35613, #35614, #35621, #35660, #35663, #35670, #35671, #35672, #35681, #35686, #35690, #35695, #35707, #35708, #35713, #35722, #35725, #35726, #35731
- Failed merges: #35395
This commit is contained in:
bors 2016-08-17 09:49:34 -07:00 committed by GitHub
commit 7ac11cad3f
66 changed files with 511 additions and 376 deletions

View File

@ -13,7 +13,7 @@
######################################################################
# The version number
CFG_RELEASE_NUM=1.12.0
CFG_RELEASE_NUM=1.13.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release

View File

@ -67,7 +67,7 @@ trait Graph {
Simple enough. Associated types use the `type` keyword, and go inside the body
of the trait, with the functions.
These `type` declarations can have all the same thing as functions do. For example,
These type declarations work the same way as those for functions. For example,
if we wanted our `N` type to implement `Display`, so we can print the nodes out,
we could do this:

View File

@ -262,7 +262,7 @@ the result:
```rust
fn call_with_one<F>(some_closure: F) -> i32
where F : Fn(i32) -> i32 {
where F: Fn(i32) -> i32 {
some_closure(1)
}
@ -279,7 +279,7 @@ Lets examine the signature of `call_with_one` in more depth:
```rust
fn call_with_one<F>(some_closure: F) -> i32
# where F : Fn(i32) -> i32 {
# where F: Fn(i32) -> i32 {
# some_closure(1) }
```
@ -288,7 +288,7 @@ isnt interesting. The next part is:
```rust
# fn call_with_one<F>(some_closure: F) -> i32
where F : Fn(i32) -> i32 {
where F: Fn(i32) -> i32 {
# some_closure(1) }
```

View File

@ -57,8 +57,8 @@ fn main(argc: isize, argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { loop {} }
# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
# #[no_mangle] pub extern fn rust_eh_register_frames () {}
# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
@ -73,8 +73,8 @@ Other features provided by lang items include:
`==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
marked with lang items; those specific four are `eq`, `ord`,
`deref`, and `add` respectively.
- stack unwinding and general failure; the `eh_personality`, `fail`
and `fail_bounds_checks` lang items.
- stack unwinding and general failure; the `eh_personality`,
`eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items.
- the traits in `std::marker` used to indicate types of
various kinds; lang items `send`, `sync` and `copy`.
- the marker types and variance indicators found in

View File

@ -55,7 +55,13 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
// provided by libstd.
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn eh_personality() {
pub extern fn rust_eh_personality() {
}
// This function may be needed based on the compilation target.
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
@ -87,12 +93,18 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
0
}
// These functions and traits are used by the compiler, but not
// These functions are used by the compiler, but not
// for a bare-bones hello world. These are normally
// provided by libstd.
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn eh_personality() {
pub extern fn rust_eh_personality() {
}
// This function may be needed based on the compilation target.
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {
}
#[lang = "panic_fmt"]
@ -104,7 +116,7 @@ pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
}
```
## More about the langauge items
## More about the language items
The compiler currently makes a few assumptions about symbols which are
available in the executable to call. Normally these functions are provided by
@ -112,15 +124,20 @@ the standard library, but without it you must define your own. These symbols
are called "language items", and they each have an internal name, and then a
signature that an implementation must conform to.
The first of these two functions, `eh_personality`, is used by the failure
The first of these functions, `rust_eh_personality`, is used by the failure
mechanisms of the compiler. This is often mapped to GCC's personality function
(see the [libstd implementation][unwind] for more information), but crates
which do not trigger a panic can be assured that this function is never
called. Both the language item and the symbol name are `eh_personality`.
called. The language item's name is `eh_personality`.
[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs
The second function, `panic_fmt`, is also used by the failure mechanisms of the
The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
compiler. When a panic happens, this controls the message that's displayed on
the screen. While the language item's name is `panic_fmt`, the symbol name is
`rust_begin_panic`.
A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
flag is set in the options of the compilation target. It allows customizing the
process of resuming unwind at the end of the landing pads. The language item's name
is `eh_unwind_resume`.

View File

@ -172,6 +172,11 @@ token : simple_token | ident | literal | symbol | whitespace token ;
Each of these keywords has special meaning in its grammar, and all of them are
excluded from the `ident` rule.
Not all of these keywords are used by the language. Some of them were used
before Rust 1.0, and were left reserved once their implementations were
removed. Some of them were reserved before 1.0 to make space for possible
future features.
### Literals
```antlr

View File

@ -1715,6 +1715,15 @@ pub struct IntoIter<T> {
end: *const T,
}
#[stable(feature = "vec_intoiter_debug", since = "")]
impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("IntoIter")
.field(&self.as_slice())
.finish()
}
}
impl<T> IntoIter<T> {
/// Returns the remaining items of this iterator as a slice.
///

View File

@ -501,6 +501,14 @@ fn test_into_iter_as_mut_slice() {
assert_eq!(into_iter.as_slice(), &['y', 'c']);
}
#[test]
fn test_into_iter_debug() {
let vec = vec!['a', 'b', 'c'];
let into_iter = vec.into_iter();
let debug = format!("{:?}", into_iter);
assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
}
#[test]
fn test_into_iter_count() {
assert_eq!(vec![1, 2, 3].into_iter().count(), 3);

View File

@ -295,20 +295,8 @@ impl<A: Step> ops::Range<A> {
///
/// ```
/// #![feature(step_by)]
///
/// for i in (0..10).step_by(2) {
/// println!("{}", i);
/// }
/// ```
///
/// This prints:
///
/// ```text
/// 0
/// 2
/// 4
/// 6
/// 8
/// let result: Vec<_> = (0..10).step_by(2).collect();
/// assert_eq!(result, vec![0, 2, 4, 6, 8]);
/// ```
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
@ -650,4 +638,3 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> where
n
}
}

View File

@ -42,6 +42,11 @@
//! line. It is up to consumers of this core library to define this panic
//! function; it is only required to never return. This requires a `lang`
//! attribute named `panic_fmt`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//! compiler. This is often mapped to GCC's personality function, but crates
//! which do not trigger a panic can be assured that this function is never
//! called. The `lang` attribute is called `eh_personality`.
// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.

View File

@ -10,11 +10,16 @@
//! Overloadable operators.
//!
//! Implementing these traits allows you to get an effect similar to
//! overloading operators.
//! Implementing these traits allows you to overload certain operators.
//!
//! Some of these traits are imported by the prelude, so they are available in
//! every Rust program.
//! every Rust program. Only operators backed by traits can be overloaded. For
//! example, the addition operator (`+`) can be overloaded through the `Add`
//! trait, but since the assignment operator (`=`) has no backing trait, there
//! is no way of overloading its semantics. Additionally, this module does not
//! provide any mechanism to create new operators. If traitless overloading or
//! custom operators are required, you should look toward macros or compiler
//! plugins to extend Rust's syntax.
//!
//! Many of the operators take their operands by value. In non-generic
//! contexts involving built-in types, this is usually not a problem.

View File

@ -1073,11 +1073,12 @@ fn check_irrefutable(cx: &MatchCheckCtxt, pat: &Pat, is_fn_arg: bool) {
};
is_refutable(cx, pat, |uncovered_pat| {
span_err!(cx.tcx.sess, pat.span, E0005,
let pattern_string = pat_to_string(uncovered_pat);
struct_span_err!(cx.tcx.sess, pat.span, E0005,
"refutable pattern in {}: `{}` not covered",
origin,
pat_to_string(uncovered_pat),
);
pattern_string,
).span_label(pat.span, &format!("pattern `{}` not covered", pattern_string)).emit();
});
}

View File

@ -277,7 +277,10 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
} else {
"cannot refer to statics by value, use a constant instead"
};
span_err!(self.tcx.sess, self.span, E0394, "{}", msg);
struct_span_err!(self.tcx.sess, self.span, E0394, "{}", msg)
.span_label(self.span, &format!("referring to another static by value"))
.note(&format!("use the address-of operator or a constant instead"))
.emit();
// Replace STATIC with NOT_CONST to avoid further errors.
self.qualif = self.qualif - Qualif::STATIC;

View File

@ -283,10 +283,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
Ok(Ordering::Less) |
Ok(Ordering::Equal) => {}
Ok(Ordering::Greater) => {
span_err!(self.tcx.sess,
start.span,
E0030,
"lower range bound must be less than or equal to upper");
struct_span_err!(self.tcx.sess, start.span, E0030,
"lower range bound must be less than or equal to upper")
.span_label(start.span, &format!("lower bound larger than upper bound"))
.emit();
}
Err(ErrorReported) => {}
}

View File

@ -116,7 +116,7 @@ enum ResolutionError<'a> {
/// error E0408: variable `{}` from pattern #{} is not bound in pattern #{}
VariableNotBoundInPattern(Name, usize, usize),
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
VariableBoundWithDifferentMode(Name, usize),
VariableBoundWithDifferentMode(Name, usize, Span),
/// error E0411: use of `Self` outside of an impl or trait
SelfUsedOutsideImplOrTrait,
/// error E0412: use of undeclared
@ -269,14 +269,19 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
from,
to)
}
ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
struct_span_err!(resolver.session,
ResolutionError::VariableBoundWithDifferentMode(variable_name,
pattern_number,
first_binding_span) => {
let mut err = struct_span_err!(resolver.session,
span,
E0409,
"variable `{}` is bound with different mode in pattern #{} than in \
pattern #1",
variable_name,
pattern_number)
pattern_number);
err.span_label(span, &format!("bound in different ways"));
err.span_label(first_binding_span, &format!("first binding"));
err
}
ResolutionError::SelfUsedOutsideImplOrTrait => {
let mut err = struct_span_err!(resolver.session,
@ -316,11 +321,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
err
}
ResolutionError::DoesNotNameAStruct(name) => {
struct_span_err!(resolver.session,
let mut err = struct_span_err!(resolver.session,
span,
E0422,
"`{}` does not name a structure",
name)
name);
err.span_label(span, &format!("not a structure"));
err
}
ResolutionError::StructVariantUsedAsFunction(path_name) => {
struct_span_err!(resolver.session,
@ -2028,8 +2035,10 @@ impl<'a> Resolver<'a> {
if binding_0.binding_mode != binding_i.binding_mode {
resolve_error(self,
binding_i.span,
ResolutionError::VariableBoundWithDifferentMode(key.name,
i + 1));
ResolutionError::VariableBoundWithDifferentMode(
key.name,
i + 1,
binding_0.span));
}
}
}

View File

@ -584,12 +584,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
source);
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
} else {
let msg = format!("`{}` is private, and cannot be reexported", source);
let note_msg =
format!("consider declaring type or module `{}` with `pub`", source);
struct_span_err!(self.session, directive.span, E0365, "{}", &msg)
.span_note(directive.span, &note_msg)
.emit();
let mut err = struct_span_err!(self.session, directive.span, E0365,
"`{}` is private, and cannot be reexported",
source);
err.span_label(directive.span, &format!("reexport of private `{}`", source));
err.note(&format!("consider declaring type or module `{}` with `pub`", source));
err.emit();
}
}

View File

@ -624,8 +624,10 @@ fn error_380(ccx: &CrateCtxt, span: Span) {
fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::Name)
-> DiagnosticBuilder<'tcx> {
struct_span_err!(ccx.tcx.sess, span, E0392,
"parameter `{}` is never used", param_name)
let mut err = struct_span_err!(ccx.tcx.sess, span, E0392,
"parameter `{}` is never used", param_name);
err.span_label(span, &format!("unused type parameter"));
err
}
fn error_194(tcx: TyCtxt, span: Span, name: ast::Name) {

View File

@ -458,13 +458,25 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
being coerced, none found");
return;
} else if diff_fields.len() > 1 {
span_err!(tcx.sess, span, E0375,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with one field \
being coerced, but {} fields need coercions: {}",
diff_fields.len(), diff_fields.iter().map(|&(i, a, b)| {
format!("{} ({} to {})", fields[i].name, a, b)
}).collect::<Vec<_>>().join(", "));
let item = tcx.map.expect_item(impl_node_id);
let span = if let ItemImpl(_, _, _, Some(ref t), _, _) = item.node {
t.path.span
} else {
tcx.map.span(impl_node_id)
};
let mut err = struct_span_err!(tcx.sess, span, E0375,
"implementing the trait `CoerceUnsized` \
requires multiple coercions");
err.note("`CoerceUnsized` may only be implemented for \
a coercion between structures with one field being coerced");
err.note(&format!("currently, {} fields need coercions: {}",
diff_fields.len(),
diff_fields.iter().map(|&(i, a, b)| {
format!("{} ({} to {})", fields[i].name, a, b)
}).collect::<Vec<_>>().join(", ") ));
err.span_label(span, &format!("requires multiple coercions"));
err.emit();
return;
}

View File

@ -335,8 +335,10 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
// Disallow *all* explicit impls of `Sized` and `Unsize` for now.
if Some(trait_def_id) == self.tcx.lang_items.sized_trait() {
span_err!(self.tcx.sess, item.span, E0322,
"explicit impls for the `Sized` trait are not permitted");
struct_span_err!(self.tcx.sess, item.span, E0322,
"explicit impls for the `Sized` trait are not permitted")
.span_label(item.span, &format!("impl of 'Sized' not allowed"))
.emit();
return;
}
if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {

View File

@ -2236,7 +2236,6 @@ fn report_unused_parameter(ccx: &CrateCtxt,
"the {} parameter `{}` is not constrained by the \
impl trait, self type, or predicates",
kind, name)
.span_label(span, &format!("unconstrained lifetime parameter"))
.span_label(span, &format!("unconstrained {} parameter", kind))
.emit();
}

View File

@ -211,6 +211,17 @@ impl CString {
/// This method is equivalent to `new` except that no runtime assertion
/// is made that `v` contains no 0 bytes, and it requires an actual
/// byte vector, not anything that can be converted to one with Into.
///
/// # Examples
///
/// ```
/// use std::ffi::CString;
///
/// let raw = b"foo".to_vec();
/// unsafe {
/// let c_string = CString::from_vec_unchecked(raw);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.push(0);

View File

@ -269,13 +269,18 @@ mod prim_pointer { }
/// - `Borrow`, `BorrowMut`
/// - `Default`
///
/// This limitation to `N in 0..33` exists because Rust does not yet support
/// generics over the size of an array type. `[Foo; 3]` and `[Bar; 3]` are
/// instances of same generic type `[T; 3]`, but `[Foo; 3]` and `[Foo; 5]` are
/// entirely different types. As a stopgap, trait implementations are
/// statically generated for `N in 0..33`.
///
/// Arrays coerce to [slices (`[T]`)][slice], so their methods can be called on
/// arrays.
/// arrays. Slices are dynamic and do not coerce to arrays; consequently more
/// methods are defined on `slice` where they support both types.
///
/// [slice]: primitive.slice.html
///
/// Rust does not currently support generics over the size of an array type.
///
/// # Examples
///
/// ```
@ -385,6 +390,10 @@ mod prim_slice { }
///
/// [`.as_ptr()`]: #method.as_ptr
/// [`len()`]: #method.len
///
/// Note: This example shows the internals of `&str`. `unsafe` should not be
/// used to get a string slice under normal circumstances. Use `.as_slice()`
/// instead.
mod prim_str { }
#[doc(primitive = "tuple")]

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*
* Inline assembly support.
*/
// Inline assembly support.
//
use self::State::*;
use syntax::ast;
@ -31,43 +30,48 @@ enum State {
Inputs,
Clobbers,
Options,
StateNone
StateNone,
}
impl State {
fn next(&self) -> State {
match *self {
Asm => Outputs,
Outputs => Inputs,
Inputs => Clobbers,
Clobbers => Options,
Options => StateNone,
StateNone => StateNone
Asm => Outputs,
Outputs => Inputs,
Inputs => Clobbers,
Clobbers => Options,
Options => StateNone,
StateNone => StateNone,
}
}
}
const OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult + 'cx> {
if !cx.ecfg.enable_asm() {
feature_gate::emit_feature_err(
&cx.parse_sess.span_diagnostic, "asm", sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_ASM);
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"asm",
sp,
feature_gate::GateIssue::Language,
feature_gate::EXPLAIN_ASM);
return DummyResult::expr(sp);
}
// Split the tts before the first colon, to avoid `asm!("x": y)` being
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
let first_colon = tts.iter().position(|tt| {
match *tt {
tokenstream::TokenTree::Token(_, token::Colon) |
tokenstream::TokenTree::Token(_, token::ModSep) => true,
_ => false
}
}).unwrap_or(tts.len());
let first_colon = tts.iter()
.position(|tt| {
match *tt {
tokenstream::TokenTree::Token(_, token::Colon) |
tokenstream::TokenTree::Token(_, token::ModSep) => true,
_ => false,
}
})
.unwrap_or(tts.len());
let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
let mut asm = token::InternedString::new("");
let mut asm_str_style = None;
@ -91,8 +95,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
}
// Nested parser, stop before the first colon (see above).
let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
let (s, style) = match expr_to_string(cx, panictry!(p2.parse_expr()),
"inline assembly must be a string literal") {
let (s, style) = match expr_to_string(cx,
panictry!(p2.parse_expr()),
"inline assembly must be a string literal") {
Some((s, st)) => (s, st),
// let compilation continue
None => return DummyResult::expr(sp),
@ -109,9 +114,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
asm_str_style = Some(style);
}
Outputs => {
while p.token != token::Eof &&
p.token != token::Colon &&
p.token != token::ModSep {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !outputs.is_empty() {
p.eat(&token::Comma);
@ -136,8 +139,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
let output = match ch.next() {
Some('=') => None,
Some('+') => {
Some(token::intern_and_get_ident(&format!(
"={}", ch.as_str())))
Some(token::intern_and_get_ident(&format!("={}", ch.as_str())))
}
_ => {
cx.span_err(span, "output operand constraint lacks '=' or '+'");
@ -156,9 +158,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
}
}
Inputs => {
while p.token != token::Eof &&
p.token != token::Colon &&
p.token != token::ModSep {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !inputs.is_empty() {
p.eat(&token::Comma);
@ -180,9 +180,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
}
}
Clobbers => {
while p.token != token::Eof &&
p.token != token::Colon &&
p.token != token::ModSep {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !clobs.is_empty() {
p.eat(&token::Comma);
@ -218,25 +216,25 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
p.eat(&token::Comma);
}
}
StateNone => ()
StateNone => (),
}
loop {
// MOD_SEP is a double colon '::' without space in between.
// When encountered, the state must be advanced twice.
match (&p.token, state.next(), state.next().next()) {
(&token::Colon, StateNone, _) |
(&token::Colon, StateNone, _) |
(&token::ModSep, _, StateNone) => {
p.bump();
break 'statement;
}
(&token::Colon, st, _) |
(&token::Colon, st, _) |
(&token::ModSep, _, st) => {
p.bump();
state = st;
}
(&token::Eof, _, _) => break 'statement,
_ => break
_ => break,
}
}
}

View File

@ -23,7 +23,7 @@ use syntax_pos::Span;
pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
-> Box<base::MacResult + 'static> {
let mut p = cx.new_parser_from_tts(tts);
let cfg = panictry!(p.parse_meta_item());

View File

@ -20,10 +20,10 @@ use std::string::String;
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
sp: syntax_pos::Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'static> {
-> Box<base::MacResult + 'static> {
let es = match base::get_exprs_from_tts(cx, sp, tts) {
Some(e) => e,
None => return base::DummyResult::expr(sp)
None => return base::DummyResult::expr(sp),
};
let mut accumulator = String::new();
for e in es {
@ -57,7 +57,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
}
}
}
base::MacEager::expr(cx.expr_str(
sp,
token::intern_and_get_ident(&accumulator[..])))
base::MacEager::expr(cx.expr_str(sp, token::intern_and_get_ident(&accumulator[..])))
}

View File

@ -18,8 +18,10 @@ use syntax::ptr::P;
use syntax_pos::Span;
use syntax::tokenstream::TokenTree;
pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
-> Box<base::MacResult+'cx> {
pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
sp: Span,
tts: &[TokenTree])
-> Box<base::MacResult + 'cx> {
if !cx.ecfg.enable_concat_idents() {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"concat_idents",
@ -33,35 +35,40 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
for (i, e) in tts.iter().enumerate() {
if i & 1 == 1 {
match *e {
TokenTree::Token(_, token::Comma) => {},
TokenTree::Token(_, token::Comma) => {}
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
return DummyResult::expr(sp);
},
}
}
} else {
match *e {
TokenTree::Token(_, token::Ident(ident)) => {
res_str.push_str(&ident.name.as_str())
},
TokenTree::Token(_, token::Ident(ident)) => res_str.push_str(&ident.name.as_str()),
_ => {
cx.span_err(sp, "concat_idents! requires ident args.");
return DummyResult::expr(sp);
},
}
}
}
}
let res = str_to_ident(&res_str);
struct Result { ident: ast::Ident, span: Span };
struct Result {
ident: ast::Ident,
span: Span,
};
impl Result {
fn path(&self) -> ast::Path {
let segment = ast::PathSegment {
identifier: self.ident,
parameters: ast::PathParameters::none()
parameters: ast::PathParameters::none(),
};
ast::Path { span: self.span, global: false, segments: vec![segment] }
ast::Path {
span: self.span,
global: false,
segments: vec![segment],
}
}
}
@ -84,5 +91,8 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
}
}
Box::new(Result { ident: res, span: sp })
Box::new(Result {
ident: res,
span: sp,
})
}

View File

@ -36,20 +36,20 @@ pub enum PtrTy<'a> {
/// for type parameters and a lifetime.
#[derive(Clone, Eq, PartialEq)]
pub struct Path<'a> {
pub path: Vec<&'a str> ,
pub path: Vec<&'a str>,
pub lifetime: Option<&'a str>,
pub params: Vec<Box<Ty<'a>>>,
pub global: bool,
}
impl<'a> Path<'a> {
pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
pub fn new<'r>(path: Vec<&'r str>) -> Path<'r> {
Path::new_(path, None, Vec::new(), true)
}
pub fn new_local<'r>(path: &'r str) -> Path<'r> {
Path::new_(vec!( path ), None, Vec::new(), false)
Path::new_(vec![path], None, Vec::new(), false)
}
pub fn new_<'r>(path: Vec<&'r str> ,
pub fn new_<'r>(path: Vec<&'r str>,
lifetime: Option<&'r str>,
params: Vec<Box<Ty<'r>>>,
global: bool)
@ -58,7 +58,7 @@ impl<'a> Path<'a> {
path: path,
lifetime: lifetime,
params: params,
global: global
global: global,
}
}
@ -94,7 +94,7 @@ pub enum Ty<'a> {
/// parameter, and things like `i32`
Literal(Path<'a>),
/// includes unit
Tuple(Vec<Ty<'a>> )
Tuple(Vec<Ty<'a>>),
}
pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
@ -119,14 +119,14 @@ pub fn nil_ty<'r>() -> Ty<'r> {
fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
match *lt {
Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
None => None
None => None,
}
}
fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
match *lt {
Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
None => vec!()
Some(ref s) => vec![cx.lifetime(span, cx.ident_of(*s).name)],
None => vec![],
}
}
@ -145,13 +145,11 @@ impl<'a> Ty<'a> {
let lt = mk_lifetime(cx, span, lt);
cx.ty_rptr(span, raw_ty, lt, mutbl)
}
Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl)
Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl),
}
}
Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
Self_ => {
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
}
Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics),
Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)),
Tuple(ref fields) => {
let ty = ast::TyKind::Tup(fields.iter()
.map(|f| f.to_ty(cx, span, self_ty, self_generics))
@ -169,20 +167,25 @@ impl<'a> Ty<'a> {
-> ast::Path {
match *self {
Self_ => {
let self_params = self_generics.ty_params.iter().map(|ty_param| {
cx.ty_ident(span, ty_param.ident)
}).collect();
let lifetimes = self_generics.lifetimes.iter()
.map(|d| d.lifetime)
.collect();
let self_params = self_generics.ty_params
.iter()
.map(|ty_param| cx.ty_ident(span, ty_param.ident))
.collect();
let lifetimes = self_generics.lifetimes
.iter()
.map(|d| d.lifetime)
.collect();
cx.path_all(span, false, vec![self_ty], lifetimes, self_params, Vec::new())
cx.path_all(span,
false,
vec![self_ty],
lifetimes,
self_params,
Vec::new())
}
Literal(ref p) => {
p.to_path(cx, span, self_ty, self_generics)
}
Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `derive`") }
Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `derive`") }
Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),
Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
}
}
}
@ -195,16 +198,16 @@ fn mk_ty_param(cx: &ExtCtxt,
self_ident: Ident,
self_generics: &Generics)
-> ast::TyParam {
let bounds =
bounds.iter().map(|b| {
let bounds = bounds.iter()
.map(|b| {
let path = b.to_path(cx, span, self_ident, self_generics);
cx.typarambound(path)
}).collect();
})
.collect();
cx.typaram(span, cx.ident_of(name), bounds, None)
}
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
-> Generics {
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>) -> Generics {
Generics {
lifetimes: lifetimes,
ty_params: P::from_vec(ty_params),
@ -225,7 +228,8 @@ pub struct LifetimeBounds<'a> {
impl<'a> LifetimeBounds<'a> {
pub fn empty() -> LifetimeBounds<'a> {
LifetimeBounds {
lifetimes: Vec::new(), bounds: Vec::new()
lifetimes: Vec::new(),
bounds: Vec::new(),
}
}
pub fn to_generics(&self,
@ -234,46 +238,49 @@ impl<'a> LifetimeBounds<'a> {
self_ty: Ident,
self_generics: &Generics)
-> Generics {
let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
let bounds =
bounds.iter().map(
|b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
}).collect();
let ty_params = self.bounds.iter().map(|t| {
match *t {
(ref name, ref bounds) => {
mk_ty_param(cx,
span,
*name,
bounds,
self_ty,
self_generics)
let lifetimes = self.lifetimes
.iter()
.map(|&(ref lt, ref bounds)| {
let bounds = bounds.iter()
.map(|b| cx.lifetime(span, cx.ident_of(*b).name))
.collect();
cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
})
.collect();
let ty_params = self.bounds
.iter()
.map(|t| {
match *t {
(ref name, ref bounds) => {
mk_ty_param(cx, span, *name, bounds, self_ty, self_generics)
}
}
}
}).collect();
})
.collect();
mk_generics(lifetimes, ty_params)
}
}
pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
-> (P<Expr>, ast::ExplicitSelf) {
pub fn get_explicit_self(cx: &ExtCtxt,
span: Span,
self_ptr: &Option<PtrTy>)
-> (P<Expr>, ast::ExplicitSelf) {
// this constructs a fresh `self` path
let self_path = cx.expr_self(span);
match *self_ptr {
None => {
(self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable)))
}
None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))),
Some(ref ptr) => {
let self_ty = respan(
span,
match *ptr {
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
SelfKind::Region(lt, mutbl)
}
Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition")
});
let self_ty =
respan(span,
match *ptr {
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
SelfKind::Region(lt, mutbl)
}
Raw(_) => {
cx.span_bug(span, "attempted to use *self in deriving definition")
}
});
let self_expr = cx.expr_deref(span, self_path);
(self_expr, self_ty)
}

View File

@ -10,7 +10,7 @@
//! The compiler code necessary to implement the `#[derive]` extensions.
use syntax::ast::{MetaItem, self};
use syntax::ast::{self, MetaItem};
use syntax::attr::AttrMetaMethods;
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
@ -99,11 +99,11 @@ fn expand_derive(cx: &mut ExtCtxt,
for titem in traits.iter().rev() {
let tname = if titem.is_word() {
titem.name() }
else {
cx.span_err(titem.span, "malformed `derive` entry");
continue;
};
titem.name()
} else {
cx.span_err(titem.span, "malformed `derive` entry");
continue;
};
if !(is_builtin_trait(&tname) || cx.ecfg.enable_custom_derive()) {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,

View File

@ -8,11 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*
* The compiler code necessary to support the env! extension. Eventually this
* should all get sucked into either the compiler syntax extension plugin
* interface.
*/
// The compiler code necessary to support the env! extension. Eventually this
// should all get sucked into either the compiler syntax extension plugin
// interface.
//
use syntax::ast;
use syntax::ext::base::*;
@ -24,66 +23,61 @@ use syntax::tokenstream;
use std::env;
pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult + 'cx> {
let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
None => return DummyResult::expr(sp),
Some(v) => v
Some(v) => v,
};
let e = match env::var(&var[..]) {
Err(..) => {
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec!(cx.ty_rptr(sp,
cx.ty_ident(sp,
cx.ident_of("str")),
Some(cx.lifetime(sp,
cx.ident_of(
"'static").name)),
ast::Mutability::Immutable)),
Vec::new()))
}
Ok(s) => {
cx.expr_call_global(sp,
cx.std_path(&["option", "Option", "Some"]),
vec!(cx.expr_str(sp,
token::intern_and_get_ident(
&s[..]))))
}
Err(..) => {
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec![cx.ty_rptr(sp,
cx.ty_ident(sp, cx.ident_of("str")),
Some(cx.lifetime(sp,
cx.ident_of("'static")
.name)),
ast::Mutability::Immutable)],
Vec::new()))
}
Ok(s) => {
cx.expr_call_global(sp,
cx.std_path(&["option", "Option", "Some"]),
vec![cx.expr_str(sp, token::intern_and_get_ident(&s[..]))])
}
};
MacEager::expr(e)
}
pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult + 'cx> {
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
Some(ref exprs) if exprs.is_empty() => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::expr(sp);
}
None => return DummyResult::expr(sp),
Some(exprs) => exprs.into_iter()
Some(exprs) => exprs.into_iter(),
};
let var = match expr_to_string(cx,
exprs.next().unwrap(),
"expected string literal") {
let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") {
None => return DummyResult::expr(sp),
Some((v, _style)) => v
Some((v, _style)) => v,
};
let msg = match exprs.next() {
None => {
token::intern_and_get_ident(&format!("environment variable `{}` \
not defined",
var))
}
None => token::intern_and_get_ident(&format!("environment variable `{}` not defined", var)),
Some(second) => {
match expr_to_string(cx, second, "expected string literal") {
None => return DummyResult::expr(sp),
Some((s, _style)) => s
Some((s, _style)) => s,
}
}
};
@ -98,7 +92,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::Token
cx.span_err(sp, &msg);
cx.expr_usize(sp, 0)
}
Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s))
Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s)),
};
MacEager::expr(e)
}

View File

@ -37,7 +37,7 @@ enum Position {
Named(String),
}
struct Context<'a, 'b:'a> {
struct Context<'a, 'b: 'a> {
ecx: &'a mut ExtCtxt<'b>,
/// The macro's call site. References to unstable formatting internals must
/// use this span to pass the stability checker.
@ -120,7 +120,9 @@ struct Context<'a, 'b:'a> {
/// ```ignore
/// Some((fmtstr, parsed arguments, index map for named arguments))
/// ```
fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
fn parse_args(ecx: &mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, HashMap<String, usize>)> {
let mut args = Vec::<P<ast::Expr>>::new();
let mut names = HashMap::<String, usize>::new();
@ -138,7 +140,9 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
ecx.span_err(sp, "expected token: `,`");
return None;
}
if p.token == token::Eof { break } // accept trailing commas
if p.token == token::Eof {
break;
} // accept trailing commas
if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) {
named = true;
let ident = match p.token {
@ -155,7 +159,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
_ => {
ecx.span_err(p.span,
&format!("expected ident for named argument, found `{}`",
p.this_token_to_string()));
p.this_token_to_string()));
return None;
}
};
@ -164,9 +168,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
panictry!(p.expect(&token::Eq));
let e = panictry!(p.parse_expr());
if let Some(prev) = names.get(name) {
ecx.struct_span_err(e.span,
&format!("duplicate argument named `{}`",
name))
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name))
.span_note(args[*prev].span, "previously here")
.emit();
continue;
@ -235,7 +237,8 @@ impl<'a, 'b> Context<'a, 'b> {
fn verify_count(&mut self, c: parse::Count) {
match c {
parse::CountImplied | parse::CountIs(..) => {}
parse::CountImplied |
parse::CountIs(..) => {}
parse::CountIsParam(i) => {
self.verify_arg_type(Exact(i), Count);
}
@ -260,7 +263,8 @@ impl<'a, 'b> Context<'a, 'b> {
Exact(arg) => {
if self.args.len() <= arg {
let msg = format!("invalid reference to argument `{}` ({})",
arg, self.describe_num_args());
arg,
self.describe_num_args());
self.ecx.span_err(self.fmtsp, &msg[..]);
return;
@ -394,9 +398,7 @@ impl<'a, 'b> Context<'a, 'b> {
let arg = self.ecx.expr_usize(sp, i);
self.ecx.expr_call_global(sp, path, vec![arg])
}
None => {
self.ecx.expr_path(self.ecx.path_global(sp, path))
}
None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
}
};
match arg.position {
@ -436,11 +438,14 @@ impl<'a, 'b> Context<'a, 'b> {
flags: 0,
precision: parse::CountImplied,
width: parse::CountImplied,
ty: arg.format.ty
}
ty: arg.format.ty,
},
};
let fill = match arg.format.fill { Some(c) => c, None => ' ' };
let fill = match arg.format.fill {
Some(c) => c,
None => ' ',
};
if *arg != simple_arg || fill != ' ' {
self.all_pieces_simple = false;
@ -464,17 +469,33 @@ impl<'a, 'b> Context<'a, 'b> {
let prec = self.trans_count(arg.format.precision);
let width = self.trans_count(arg.format.width);
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec"));
let fmt = self.ecx.expr_struct(sp, path, vec!(
self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags),
self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
self.ecx.field_imm(sp, self.ecx.ident_of("width"), width)));
let fmt =
self.ecx.expr_struct(sp,
path,
vec![self.ecx
.field_imm(sp, self.ecx.ident_of("fill"), fill),
self.ecx.field_imm(sp,
self.ecx.ident_of("align"),
align),
self.ecx.field_imm(sp,
self.ecx.ident_of("flags"),
flags),
self.ecx.field_imm(sp,
self.ecx.ident_of("precision"),
prec),
self.ecx.field_imm(sp,
self.ecx.ident_of("width"),
width)]);
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "Argument"));
Some(self.ecx.expr_struct(sp, path, vec!(
self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt))))
Some(self.ecx.expr_struct(sp,
path,
vec![self.ecx.field_imm(sp,
self.ecx.ident_of("position"),
pos),
self.ecx.field_imm(sp,
self.ecx.ident_of("format"),
fmt)]))
}
}
}
@ -486,9 +507,9 @@ impl<'a, 'b> Context<'a, 'b> {
-> P<ast::Expr> {
let sp = piece_ty.span;
let ty = ecx.ty_rptr(sp,
ecx.ty(sp, ast::TyKind::Vec(piece_ty)),
Some(ecx.lifetime(sp, keywords::StaticLifetime.name())),
ast::Mutability::Immutable);
ecx.ty(sp, ast::TyKind::Vec(piece_ty)),
Some(ecx.lifetime(sp, keywords::StaticLifetime.name())),
ast::Mutability::Immutable);
let slice = ecx.expr_vec_slice(sp, pieces);
// static instead of const to speed up codegen by not requiring this to be inlined
let st = ast::ItemKind::Static(ty, ast::Mutability::Immutable, slice);
@ -516,15 +537,11 @@ impl<'a, 'b> Context<'a, 'b> {
// First, build up the static array which will become our precompiled
// format "string"
let static_lifetime = self.ecx.lifetime(self.fmtsp, keywords::StaticLifetime.name());
let piece_ty = self.ecx.ty_rptr(
self.fmtsp,
self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
Some(static_lifetime),
ast::Mutability::Immutable);
let pieces = Context::static_array(self.ecx,
"__STATIC_FMTSTR",
piece_ty,
self.str_pieces);
let piece_ty = self.ecx.ty_rptr(self.fmtsp,
self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
Some(static_lifetime),
ast::Mutability::Immutable);
let pieces = Context::static_array(self.ecx, "__STATIC_FMTSTR", piece_ty, self.str_pieces);
// Before consuming the expressions, we have to remember spans for
// count arguments as they are now generated separate from other
@ -542,7 +559,10 @@ impl<'a, 'b> Context<'a, 'b> {
let name = self.ecx.ident_of(&format!("__arg{}", i));
pats.push(self.ecx.pat_ident(DUMMY_SP, name));
for ref arg_ty in self.arg_unique_types[i].iter() {
locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty,
locals.push(Context::format_arg(self.ecx,
self.macsp,
e.span,
arg_ty,
self.ecx.expr_ident(e.span, name)));
}
heads.push(self.ecx.expr_addr_of(e.span, e));
@ -556,7 +576,10 @@ impl<'a, 'b> Context<'a, 'b> {
Exact(i) => spans_pos[i],
_ => panic!("should never happen"),
};
counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count,
counts.push(Context::format_arg(self.ecx,
self.macsp,
span,
&Count,
self.ecx.expr_ident(span, name)));
}
@ -593,9 +616,9 @@ impl<'a, 'b> Context<'a, 'b> {
// But the nested match expression is proved to perform not as well
// as series of let's; the first approach does.
let pat = self.ecx.pat_tuple(self.fmtsp, pats);
let arm = self.ecx.arm(self.fmtsp, vec!(pat), args_array);
let arm = self.ecx.arm(self.fmtsp, vec![pat], args_array);
let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
let result = self.ecx.expr_match(self.fmtsp, head, vec!(arm));
let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
@ -605,13 +628,9 @@ impl<'a, 'b> Context<'a, 'b> {
} else {
// Build up the static array which will store our precompiled
// nonstandard placeholders, if there are any.
let piece_ty = self.ecx.ty_path(self.ecx.path_global(
self.macsp,
Context::rtpath(self.ecx, "Argument")));
let fmt = Context::static_array(self.ecx,
"__STATIC_FMTARGS",
piece_ty,
self.pieces);
let piece_ty = self.ecx
.ty_path(self.ecx.path_global(self.macsp, Context::rtpath(self.ecx, "Argument")));
let fmt = Context::static_array(self.ecx, "__STATIC_FMTARGS", piece_ty, self.pieces);
("new_v1_formatted", vec![pieces, args_slice, fmt])
};
@ -620,13 +639,16 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.expr_call_global(self.macsp, path, fn_args)
}
fn format_arg(ecx: &ExtCtxt, macsp: Span, sp: Span,
ty: &ArgumentType, arg: P<ast::Expr>)
fn format_arg(ecx: &ExtCtxt,
macsp: Span,
sp: Span,
ty: &ArgumentType,
arg: P<ast::Expr>)
-> P<ast::Expr> {
let trait_ = match *ty {
Placeholder(ref tyname) => {
match &tyname[..] {
"" => "Display",
"" => "Display",
"?" => "Debug",
"e" => "LowerExp",
"E" => "UpperExp",
@ -636,16 +658,14 @@ impl<'a, 'b> Context<'a, 'b> {
"x" => "LowerHex",
"X" => "UpperHex",
_ => {
ecx.span_err(sp,
&format!("unknown format trait `{}`",
*tyname));
ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname));
"Dummy"
}
}
}
Count => {
let path = ecx.std_path(&["fmt", "ArgumentV1", "from_usize"]);
return ecx.expr_call_global(macsp, path, vec![arg])
return ecx.expr_call_global(macsp, path, vec![arg]);
}
};
@ -656,22 +676,23 @@ impl<'a, 'b> Context<'a, 'b> {
}
}
pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp: Span,
pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
sp: Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
-> Box<base::MacResult + 'cx> {
match parse_args(ecx, sp, tts) {
Some((efmt, args, names)) => {
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt,
args, names))
MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names))
}
None => DummyResult::expr(sp)
None => DummyResult::expr(sp),
}
}
/// Take the various parts of `format_args!(efmt, args..., name=names...)`
/// and construct the appropriate formatting expression.
pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
sp: Span,
efmt: P<ast::Expr>,
args: Vec<P<ast::Expr>>,
names: HashMap<String, usize>)
@ -704,11 +725,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
macsp: macsp,
fmtsp: efmt.span,
};
let fmt = match expr_to_string(cx.ecx,
efmt,
"format argument must be a string literal.") {
let fmt = match expr_to_string(cx.ecx, efmt, "format argument must be a string literal.") {
Some((fmt, _)) => fmt,
None => return DummyResult::raw_expr(sp)
None => return DummyResult::raw_expr(sp),
};
let mut parser = parse::Parser::new(&fmt);
@ -717,12 +736,14 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
loop {
match parser.next() {
Some(mut piece) => {
if !parser.errors.is_empty() { break }
if !parser.errors.is_empty() {
break;
}
cx.verify_piece(&piece);
cx.resolve_name_inplace(&mut piece);
pieces.push(piece);
}
None => break
None => break,
}
}
@ -738,8 +759,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
}
if !parser.errors.is_empty() {
cx.ecx.span_err(cx.fmtsp, &format!("invalid format string: {}",
parser.errors.remove(0)));
cx.ecx.span_err(cx.fmtsp,
&format!("invalid format string: {}", parser.errors.remove(0)));
return DummyResult::raw_expr(sp);
}
if !cx.literal.is_empty() {

View File

@ -23,7 +23,8 @@
#![feature(staged_api)]
extern crate fmt_macros;
#[macro_use] extern crate log;
#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
@ -52,16 +53,13 @@ pub fn register_builtins(env: &mut SyntaxEnv) {
NormalTT(Box::new(f), None, false)
}
env.insert(intern("asm"),
builtin_normal_expander(asm::expand_asm));
env.insert(intern("cfg"),
builtin_normal_expander(cfg::expand_cfg));
env.insert(intern("asm"), builtin_normal_expander(asm::expand_asm));
env.insert(intern("cfg"), builtin_normal_expander(cfg::expand_cfg));
env.insert(intern("concat"),
builtin_normal_expander(concat::expand_syntax_ext));
env.insert(intern("concat_idents"),
builtin_normal_expander(concat_idents::expand_syntax_ext));
env.insert(intern("env"),
builtin_normal_expander(env::expand_env));
env.insert(intern("env"), builtin_normal_expander(env::expand_env));
env.insert(intern("option_env"),
builtin_normal_expander(env::expand_option_env));
env.insert(intern("format_args"),

View File

@ -17,7 +17,7 @@ use syntax_pos;
pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
sp: syntax_pos::Span,
tts: &[tokenstream::TokenTree])
-> Box<base::MacResult+'cx> {
-> Box<base::MacResult + 'cx> {
if !cx.ecfg.enable_log_syntax() {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"log_syntax",

View File

@ -18,7 +18,7 @@ use syntax::tokenstream::TokenTree;
pub fn expand_trace_macros(cx: &mut ExtCtxt,
sp: Span,
tt: &[TokenTree])
-> Box<base::MacResult+'static> {
-> Box<base::MacResult + 'static> {
if !cx.ecfg.enable_trace_macros() {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"trace_macros",

View File

@ -11,4 +11,5 @@
fn main() {
let x = Some(1);
let Some(y) = x; //~ ERROR E0005
//~| NOTE pattern `None` not covered
}

View File

@ -11,6 +11,8 @@
fn main() {
match 5u32 {
1000 ... 5 => {} //~ ERROR E0030
1000 ... 5 => {}
//~^ ERROR lower range bound must be less than or equal to upper
//~| NOTE lower bound larger than upper bound
}
}

View File

@ -11,7 +11,7 @@
struct Foo;
impl<T: Default> Foo { //~ ERROR E0207
//~| NOTE unconstrained lifetime parameter
//~| NOTE unconstrained type parameter
fn get(&self) -> T {
<T as Default>::default()
}

View File

@ -12,6 +12,9 @@ mod foo {
pub const X: u32 = 1;
}
pub use foo as foo2; //~ ERROR E0365
pub use foo as foo2;
//~^ ERROR `foo` is private, and cannot be reexported [E0365]
//~| NOTE reexport of private `foo`
//~| NOTE consider declaring type or module `foo` with `pub`
fn main() {}

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
#![feature(coerce_unsized)]
use std::ops::CoerceUnsized;
@ -17,6 +19,10 @@ struct Foo<T: ?Sized, U: ?Sized> {
c: U,
}
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} //~ ERROR E0375
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
//~^ ERROR E0375
//~| NOTE requires multiple coercions
//~| NOTE `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
//~| NOTE currently, 2 fields need coercions: b (T to U), c (U to T)
fn main() {}

View File

@ -9,6 +9,7 @@
// except according to those terms.
enum Foo<T> { Bar } //~ ERROR E0392
//~| NOTE unused type parameter
fn main() {
}

View File

@ -9,7 +9,10 @@
// except according to those terms.
static A: u32 = 0;
static B: u32 = A; //~ ERROR E0394
static B: u32 = A;
//~^ ERROR E0394
//~| NOTE referring to another static by value
//~| NOTE use the address-of operator or a constant instead
fn main() {
}

View File

@ -13,7 +13,12 @@ fn main() {
match x {
(0, ref y) | (y, 0) => {} //~ ERROR E0409
//~^ ERROR E0308
//~^ NOTE bound in different ways
//~| NOTE first binding
//~| ERROR E0308
//~| NOTE expected &{integer}, found integral variable
//~| NOTE expected type `&{integer}`
//~| NOTE found type `{integer}`
_ => ()
}
}

View File

@ -9,5 +9,7 @@
// except according to those terms.
fn main () {
let x = Foo { x: 1, y: 2 }; //~ ERROR E0422
let x = Foo { x: 1, y: 2 };
//~^ ERROR E0422
//~| NOTE not a structure
}

View File

@ -22,12 +22,15 @@ struct NotSync;
impl !Sync for NotSync {}
impl Sized for TestE {} //~ ERROR E0322
//~^ impl of 'Sized' not allowed
impl Sized for MyType {} //~ ERROR E0322
//~^ impl of 'Sized' not allowed
impl Sized for (MyType, MyType) {} //~ ERROR E0117
impl Sized for &'static NotSync {} //~ ERROR E0322
//~^ impl of 'Sized' not allowed
impl Sized for [MyType] {} //~ ERROR E0117

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
#![feature(optin_builtin_traits)]
fn main() {
struct Foo;

View File

@ -1,7 +1,7 @@
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static main::Foo`
--> $DIR/empty_span.rs:18:5
--> $DIR/empty_span.rs:17:5
|
18 | unsafe impl Send for &'static Foo { }
17 | unsafe impl Send for &'static Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let x = "foo";
@ -94,11 +92,10 @@ fn main() {
let y = &mut x;
}

View File

@ -1,7 +1,7 @@
error: cannot borrow immutable local variable `x` as mutable
--> $DIR/huge_multispan_highlight.rs:100:18
|
14 | let x = "foo";
12 | let x = "foo";
| - use `mut x` here to make mutable
...
100 | let y = &mut x;

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
@ -99,6 +99,3 @@ fn main() {
let y = &mut x;
let z = &mut x;
}

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let mut v = vec![Some("foo"), Some("bar")];
v.push(v.pop().unwrap());

View File

@ -1,7 +1,7 @@
error[E0499]: cannot borrow `v` as mutable more than once at a time
--> $DIR/one_line.rs:15:12
--> $DIR/one_line.rs:13:12
|
15 | v.push(v.pop().unwrap());
13 | v.push(v.pop().unwrap());
| - ^ - first borrow ends here
| | |
| | second mutable borrow occurs here

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
#[derive(Debug)]
struct Foo { }

View File

@ -1,7 +1,7 @@
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/overlapping_spans.rs:22:9
--> $DIR/overlapping_spans.rs:21:9
|
22 | S {f:_s} => {}
21 | S {f:_s} => {}
| ^^^^^--^
| | |
| | hint: to prevent move, use `ref _s` or `ref mut _s`

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
// ignore-tidy-tab
fn main() {
bar;
}

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
include!("two_files_data.rs");
struct Baz { }

View File

@ -1,7 +1,7 @@
error[E0404]: `Bar` is not a trait
--> $DIR/two_files.rs:16:6
--> $DIR/two_files.rs:15:6
|
16 | impl Bar for Baz { }
15 | impl Bar for Baz { }
| ^^^ not a trait
|
= note: type aliases cannot be used for traits

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
// ignore-test
trait Foo { }
type Bar = Foo;

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
extern "路濫狼á́́" fn foo() {}
fn main() { }

View File

@ -1,7 +1,7 @@
error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́`
--> $DIR/unicode.rs:12:8
--> $DIR/unicode.rs:11:8
|
12 | extern "路濫狼á́́" fn foo() {}
11 | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^
error: aborting due to previous error

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
extern {
fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
}

View File

@ -1,16 +1,16 @@
error[E0308]: mismatched types
--> $DIR/issue-26480.rs:27:19
--> $DIR/issue-26480.rs:26:19
|
27 | $arr.len() * size_of($arr[0]));
26 | $arr.len() * size_of($arr[0]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
$DIR/issue-26480.rs:38:5: 38:19 note: in this expansion of write! (defined in $DIR/issue-26480.rs)
$DIR/issue-26480.rs:37:5: 37:19 note: in this expansion of write! (defined in $DIR/issue-26480.rs)
error: non-scalar cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:33:19
--> $DIR/issue-26480.rs:32:19
|
33 | ($x:expr) => ($x as ())
32 | ($x:expr) => ($x as ())
| ^^^^^^^^
$DIR/issue-26480.rs:39:5: 39:14 note: in this expansion of cast! (defined in $DIR/issue-26480.rs)
$DIR/issue-26480.rs:38:5: 38:14 note: in this expansion of cast! (defined in $DIR/issue-26480.rs)
error: aborting due to 2 previous errors

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// rustc-env:RUST_NEW_ERROR_FORMAT
fn main() {
let x: u32 = (
);

View File

@ -1,7 +1,7 @@
error[E0308]: mismatched types
--> $DIR/main.rs:14:18
--> $DIR/main.rs:12:18
|
14 | let x: u32 = (
12 | let x: u32 = (
| ^ expected u32, found ()
|
= note: expected type `u32`

View File

@ -8,10 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for issue #24986
// Make sure that the span of a closure marked `move` begins at the `move` keyword.
fn main() {
let x: () =
move //~ ERROR mismatched types
|| ();
let x: () = move || ();
}

View File

@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/move-closure.rs:15:17
|
15 | let x: () = move || ();
| ^^^^^^^^^^ expected (), found closure
|
= note: expected type `()`
= note: found type `[closure@$DIR/move-closure.rs:15:17: 15:27]`
error: aborting due to previous error

View File

@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for issue #28158
// Test the type binding span doesn't include >>
use std::ops::Deref;
fn homura<T: Deref<Trget=i32 //~ ERROR associated type
>>(_: T) { }
fn homura<T: Deref<Trget = i32>>(_: T) {}
fn main() {
}
fn main() {}

View File

@ -0,0 +1,8 @@
error[E0220]: associated type `Trget` not found for `std::ops::Deref`
--> $DIR/type-binding.rs:16:20
|
16 | fn homura<T: Deref<Trget = i32>>(_: T) {}
| ^^^^^^^^^^^
error: aborting due to previous error