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:
commit
7ac11cad3f
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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 @@ Let’s 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 @@ isn’t 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) }
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) => {}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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, ¬e_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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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")]
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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[..])))
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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"),
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -11,4 +11,5 @@
|
||||
fn main() {
|
||||
let x = Some(1);
|
||||
let Some(y) = x; //~ ERROR E0005
|
||||
//~| NOTE pattern `None` not covered
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
enum Foo<T> { Bar } //~ ERROR E0392
|
||||
//~| NOTE unused type parameter
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
@ -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() {
|
||||
}
|
||||
|
@ -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}`
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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 { }
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 { }
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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() { }
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = (
|
||||
);
|
||||
|
@ -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`
|
||||
|
@ -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 || ();
|
||||
}
|
11
src/test/ui/span/move-closure.stderr
Normal file
11
src/test/ui/span/move-closure.stderr
Normal 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
|
||||
|
@ -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() {}
|
8
src/test/ui/span/type-binding.stderr
Normal file
8
src/test/ui/span/type-binding.stderr
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user