mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Auto merge of #35592 - jonathandturner:rollup, r=jonathandturner
Rollup of 23 pull requests - Successful merges: #35279, #35331, #35358, #35375, #35445, #35448, #35482, #35486, #35505, #35528, #35530, #35532, #35536, #35537, #35541, #35552, #35554, #35555, #35557, #35562, #35565, #35569, #35576 - Failed merges: #35395, #35415, #35563
This commit is contained in:
@@ -57,6 +57,7 @@ __pycache__/
|
||||
.project
|
||||
.settings/
|
||||
.valgrindrc
|
||||
.vscode/
|
||||
/*-*-*-*/
|
||||
/*-*-*/
|
||||
/Makefile
|
||||
|
||||
@@ -1180,7 +1180,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
|
||||
#[inline]
|
||||
#[unstable(feature = "insert_str",
|
||||
reason = "recent addition",
|
||||
issue = "0")]
|
||||
issue = "35553")]
|
||||
pub fn insert_str(&mut self, idx: usize, string: &str) {
|
||||
let len = self.len();
|
||||
assert!(idx <= len);
|
||||
|
||||
+37
-8
@@ -229,14 +229,28 @@ macro_rules! try {
|
||||
})
|
||||
}
|
||||
|
||||
/// Use the `format!` syntax to write data into a buffer.
|
||||
/// Write formatted data into a buffer
|
||||
///
|
||||
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
|
||||
/// This macro accepts any value with `write_fmt` method as a writer, a format string, and a list
|
||||
/// of arguments to format.
|
||||
///
|
||||
/// `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write] or
|
||||
/// [`std::io::Write`][io_write] traits. These are sometimes called 'writers'.
|
||||
///
|
||||
/// Passed arguments will be formatted according to the specified format string and the resulting
|
||||
/// string will be passed to the writer.
|
||||
///
|
||||
/// See [`std::fmt`][fmt] for more information on format syntax.
|
||||
///
|
||||
/// Return value is completely dependent on the 'write_fmt' method.
|
||||
///
|
||||
/// Common return values are: [`Result`][enum_result], [`io::Result`][type_result]
|
||||
///
|
||||
/// [fmt]: ../std/fmt/index.html
|
||||
/// [write]: ../std/io/trait.Write.html
|
||||
/// [fmt_write]: ../std/fmt/trait.Write.html
|
||||
/// [io_write]: ../std/io/trait.Write.html
|
||||
/// [enum_result]: ../std/result/enum.Result.html
|
||||
/// [type_result]: ../std/io/type.Result.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -255,16 +269,31 @@ macro_rules! write {
|
||||
($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
|
||||
}
|
||||
|
||||
/// Use the `format!` syntax to write data into a buffer, appending a newline.
|
||||
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`)
|
||||
/// alone (no additional CARRIAGE RETURN (`\r`/`U+000D`).
|
||||
/// Write formatted data into a buffer, with appending a newline.
|
||||
///
|
||||
/// This macro is typically used with a buffer of `&mut `[`Write`][write].
|
||||
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
|
||||
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
|
||||
///
|
||||
/// This macro accepts any value with `write_fmt` method as a writer, a format string, and a list
|
||||
/// of arguments to format.
|
||||
///
|
||||
/// `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write] or
|
||||
/// [`std::io::Write`][io_write] traits. These are sometimes called 'writers'.
|
||||
///
|
||||
/// Passed arguments will be formatted according to the specified format string and the resulting
|
||||
/// string will be passed to the writer.
|
||||
///
|
||||
/// See [`std::fmt`][fmt] for more information on format syntax.
|
||||
///
|
||||
/// Return value is completely dependent on the 'write_fmt' method.
|
||||
///
|
||||
/// Common return values are: [`Result`][enum_result], [`io::Result`][type_result]
|
||||
///
|
||||
/// [fmt]: ../std/fmt/index.html
|
||||
/// [write]: ../std/io/trait.Write.html
|
||||
/// [fmt_write]: ../std/fmt/trait.Write.html
|
||||
/// [io_write]: ../std/io/trait.Write.html
|
||||
/// [enum_result]: ../std/result/enum.Result.html
|
||||
/// [type_result]: ../std/io/type.Result.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
@@ -402,8 +402,8 @@ pub fn as_ref(&self) -> Result<&T, &E> {
|
||||
/// ```
|
||||
/// fn mutate(r: &mut Result<i32, i32>) {
|
||||
/// match r.as_mut() {
|
||||
/// Ok(&mut ref mut v) => *v = 42,
|
||||
/// Err(&mut ref mut e) => *e = 0,
|
||||
/// Ok(v) => *v = 42,
|
||||
/// Err(e) => *e = 0,
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
||||
@@ -63,9 +63,11 @@ fn require_unsafe(&mut self, span: Span, description: &str) {
|
||||
match self.unsafe_context.root {
|
||||
SafeContext => {
|
||||
// Report an error.
|
||||
span_err!(self.tcx.sess, span, E0133,
|
||||
"{} requires unsafe function or block",
|
||||
description);
|
||||
struct_span_err!(
|
||||
self.tcx.sess, span, E0133,
|
||||
"{} requires unsafe function or block", description)
|
||||
.span_label(span, &format!("unsafe call requires unsafe function or block"))
|
||||
.emit();
|
||||
}
|
||||
UnsafeBlock(block_id) => {
|
||||
// OK, but record this.
|
||||
|
||||
@@ -718,10 +718,14 @@ fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &[hir::LifetimeDe
|
||||
let lifetime_j = &lifetimes[j];
|
||||
|
||||
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
|
||||
span_err!(self.sess, lifetime_j.lifetime.span, E0263,
|
||||
"lifetime name `{}` declared twice in \
|
||||
the same scope",
|
||||
lifetime_j.lifetime.name);
|
||||
struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263,
|
||||
"lifetime name `{}` declared twice in the same scope",
|
||||
lifetime_j.lifetime.name)
|
||||
.span_label(lifetime_j.lifetime.span,
|
||||
&format!("declared twice"))
|
||||
.span_label(lifetime_i.lifetime.span,
|
||||
&format!("previous declaration here"))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -654,6 +654,7 @@ pub fn recursive_type_with_infinite_size_error(self,
|
||||
let mut err = struct_span_err!(self.sess, span, E0072,
|
||||
"recursive type `{}` has infinite size",
|
||||
self.item_path_str(type_def_id));
|
||||
err.span_label(span, &format!("recursive type has infinite size"));
|
||||
err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
|
||||
at some point to make `{}` representable",
|
||||
self.item_path_str(type_def_id)));
|
||||
@@ -670,10 +671,15 @@ pub fn report_object_safety_error(self,
|
||||
let mut err = match warning_node_id {
|
||||
Some(_) => None,
|
||||
None => {
|
||||
Some(struct_span_err!(
|
||||
self.sess, span, E0038,
|
||||
"the trait `{}` cannot be made into an object",
|
||||
self.item_path_str(trait_def_id)))
|
||||
let trait_str = self.item_path_str(trait_def_id);
|
||||
let mut db = struct_span_err!(
|
||||
self.sess, span, E0038,
|
||||
"the trait `{}` cannot be made into an object",
|
||||
trait_str);
|
||||
db.span_label(span,
|
||||
&format!("the trait `{}` cannot be made \
|
||||
into an object", trait_str));
|
||||
Some(db)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -760,12 +760,16 @@ pub fn report_reassigned_immutable_variable(&self,
|
||||
lp: &LoanPath<'tcx>,
|
||||
assign:
|
||||
&move_data::Assignment) {
|
||||
struct_span_err!(
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess, span, E0384,
|
||||
"re-assignment of immutable variable `{}`",
|
||||
self.loan_path_to_string(lp))
|
||||
.span_note(assign.span, "prior assignment occurs here")
|
||||
.emit();
|
||||
self.loan_path_to_string(lp));
|
||||
err.span_label(span, &format!("re-assignment of immutable variable"));
|
||||
if span != assign.span {
|
||||
err.span_label(assign.span, &format!("first assignment to `{}`",
|
||||
self.loan_path_to_string(lp)));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
pub fn span_err(&self, s: Span, m: &str) {
|
||||
|
||||
@@ -235,12 +235,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
|
||||
.flat_map(|arm| &arm.0)
|
||||
.map(|pat| vec![wrap_pat(cx, &pat)])
|
||||
.collect();
|
||||
let match_span = Span {
|
||||
lo: ex.span.lo,
|
||||
hi: scrut.span.hi,
|
||||
expn_id: ex.span.expn_id
|
||||
};
|
||||
check_exhaustive(cx, match_span, &matrix, source);
|
||||
check_exhaustive(cx, scrut.span, &matrix, source);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
@@ -1115,9 +1110,15 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
|
||||
|
||||
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
|
||||
if sub.map_or(false, |p| pat_contains_bindings(&p)) {
|
||||
span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings");
|
||||
struct_span_err!(cx.tcx.sess, p.span, E0007,
|
||||
"cannot bind by-move with sub-bindings")
|
||||
.span_label(p.span, &format!("binds an already bound by-move value by moving it"))
|
||||
.emit();
|
||||
} else if has_guard {
|
||||
span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
|
||||
struct_span_err!(cx.tcx.sess, p.span, E0008,
|
||||
"cannot bind by-move into a pattern guard")
|
||||
.span_label(p.span, &format!("moves value into pattern guard"))
|
||||
.emit();
|
||||
} else if by_ref_span.is_some() {
|
||||
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0009,
|
||||
"cannot bind by-move and by-ref in the same pattern");
|
||||
|
||||
@@ -615,9 +615,12 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
|
||||
if !allow {
|
||||
self.add(Qualif::NOT_CONST);
|
||||
if self.mode != Mode::Fn {
|
||||
span_err!(self.tcx.sess, self.span, E0017,
|
||||
"references in {}s may only refer \
|
||||
to immutable values", self.mode);
|
||||
struct_span_err!(self.tcx.sess, self.span, E0017,
|
||||
"references in {}s may only refer \
|
||||
to immutable values", self.mode)
|
||||
.span_label(self.span, &format!("{}s require immutable values",
|
||||
self.mode))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -183,6 +183,7 @@ fn visit_foreign_item(&mut self, fi: &ForeignItem) {
|
||||
E0130,
|
||||
"patterns aren't allowed in foreign function \
|
||||
declarations");
|
||||
err.span_label(span, &format!("pattern not allowed in foreign function"));
|
||||
if is_recent {
|
||||
err.span_note(span,
|
||||
"this is a recent error, see issue #35203 for more details");
|
||||
|
||||
@@ -412,7 +412,10 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
||||
struct_span_err!(resolver.session, span, E0432, "{}", msg)
|
||||
}
|
||||
ResolutionError::FailedToResolve(msg) => {
|
||||
struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg)
|
||||
let mut err = struct_span_err!(resolver.session, span, E0433,
|
||||
"failed to resolve. {}", msg);
|
||||
err.span_label(span, &msg);
|
||||
err
|
||||
}
|
||||
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
||||
struct_span_err!(resolver.session,
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
use rustc::traits::{self, ProjectionMode};
|
||||
use rustc::ty::error::ExpectedFound;
|
||||
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
|
||||
use rustc::hir::map::Node;
|
||||
use rustc::hir::{ImplItemKind, TraitItem_};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
@@ -461,7 +463,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
// Compute skolemized form of impl and trait const tys.
|
||||
let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
|
||||
let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
|
||||
let origin = TypeOrigin::Misc(impl_c_span);
|
||||
let mut origin = TypeOrigin::Misc(impl_c_span);
|
||||
|
||||
let err = infcx.commit_if_ok(|_| {
|
||||
// There is no "body" here, so just pass dummy id.
|
||||
@@ -496,11 +498,31 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
|
||||
impl_ty,
|
||||
trait_ty);
|
||||
|
||||
// Locate the Span containing just the type of the offending impl
|
||||
if let Some(impl_trait_node) = tcx.map.get_if_local(impl_c.def_id) {
|
||||
if let Node::NodeImplItem(impl_trait_item) = impl_trait_node {
|
||||
if let ImplItemKind::Const(ref ty, _) = impl_trait_item.node {
|
||||
origin = TypeOrigin::Misc(ty.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess, origin.span(), E0326,
|
||||
"implemented const `{}` has an incompatible type for trait",
|
||||
trait_c.name
|
||||
);
|
||||
|
||||
// Add a label to the Span containing just the type of the item
|
||||
if let Some(orig_trait_node) = tcx.map.get_if_local(trait_c.def_id) {
|
||||
if let Node::NodeTraitItem(orig_trait_item) = orig_trait_node {
|
||||
if let TraitItem_::ConstTraitItem(ref ty, _) = orig_trait_item.node {
|
||||
diag.span_label(ty.span, &format!("original trait requirement"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infcx.note_type_err(
|
||||
&mut diag, origin,
|
||||
Some(infer::ValuePairs::Types(ExpectedFound {
|
||||
|
||||
@@ -97,8 +97,10 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
|
||||
(0, Vec::new(), tcx.mk_nil())
|
||||
}
|
||||
op => {
|
||||
span_err!(tcx.sess, it.span, E0092,
|
||||
"unrecognized atomic operation function: `{}`", op);
|
||||
struct_span_err!(tcx.sess, it.span, E0092,
|
||||
"unrecognized atomic operation function: `{}`", op)
|
||||
.span_label(it.span, &format!("unrecognized atomic operation"))
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1272,13 +1272,21 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||
|
||||
// Check for duplicate discriminant values
|
||||
if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) {
|
||||
let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0081,
|
||||
"discriminant value `{}` already exists", disr_vals[i]);
|
||||
let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
|
||||
err.span_label(ccx.tcx.map.span(variant_i_node_id),
|
||||
&format!("first use of `{}`", disr_vals[i]));
|
||||
err.span_label(v.span , &format!("enum already has `{}`", disr_vals[i]));
|
||||
err.emit();
|
||||
let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id);
|
||||
let i_span = match variant_i.node.disr_expr {
|
||||
Some(ref expr) => expr.span,
|
||||
None => ccx.tcx.map.span(variant_i_node_id)
|
||||
};
|
||||
let span = match v.node.disr_expr {
|
||||
Some(ref expr) => expr.span,
|
||||
None => v.span
|
||||
};
|
||||
struct_span_err!(ccx.tcx.sess, span, E0081,
|
||||
"discriminant value `{}` already exists", disr_vals[i])
|
||||
.span_label(i_span, &format!("first use of `{}`", disr_vals[i]))
|
||||
.span_label(span , &format!("enum already has `{}`", disr_vals[i]))
|
||||
.emit();
|
||||
}
|
||||
disr_vals.push(current_disr_val);
|
||||
}
|
||||
@@ -4640,9 +4648,11 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
for (i, b) in tps_used.iter().enumerate() {
|
||||
if !*b {
|
||||
span_err!(ccx.tcx.sess, tps[i].span, E0091,
|
||||
struct_span_err!(ccx.tcx.sess, tps[i].span, E0091,
|
||||
"type parameter `{}` is unused",
|
||||
tps[i].name);
|
||||
tps[i].name)
|
||||
.span_label(tps[i].span, &format!("unused type parameter"))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1903,9 +1903,12 @@ fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
for leaf_ty in ty.walk() {
|
||||
if let ty::TyParam(p) = leaf_ty.sty {
|
||||
if p.space == space && p.idx >= index {
|
||||
span_err!(ccx.tcx.sess, path.span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers");
|
||||
struct_span_err!(ccx.tcx.sess, path.span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers")
|
||||
.span_label(path.span, &format!("defaulted type parameters \
|
||||
cannot be forward declared"))
|
||||
.emit();
|
||||
|
||||
return ccx.tcx.types.err
|
||||
}
|
||||
|
||||
@@ -178,8 +178,10 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
|
||||
abi: Abi,
|
||||
span: Span) {
|
||||
if decl.variadic && abi != Abi::C {
|
||||
span_err!(tcx.sess, span, E0045,
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0045,
|
||||
"variadic function must have C calling convention");
|
||||
err.span_label(span, &("variadics require C calling conventions").to_string())
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-17
@@ -99,11 +99,9 @@ pub struct CString {
|
||||
///
|
||||
/// extern { fn my_string() -> *const c_char; }
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// let slice = CStr::from_ptr(my_string());
|
||||
/// println!("string length: {}", slice.to_bytes().len());
|
||||
/// }
|
||||
/// unsafe {
|
||||
/// let slice = CStr::from_ptr(my_string());
|
||||
/// println!("string length: {}", slice.to_bytes().len());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
@@ -119,10 +117,8 @@ pub struct CString {
|
||||
/// unsafe { work_with(data.as_ptr()) }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let s = CString::new("data data data data").unwrap();
|
||||
/// work(&s);
|
||||
/// }
|
||||
/// let s = CString::new("data data data data").unwrap();
|
||||
/// work(&s);
|
||||
/// ```
|
||||
///
|
||||
/// Converting a foreign C string into a Rust `String`
|
||||
@@ -139,9 +135,7 @@ pub struct CString {
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("string: {}", my_string_safe());
|
||||
/// }
|
||||
/// println!("string: {}", my_string_safe());
|
||||
/// ```
|
||||
#[derive(Hash)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@@ -188,11 +182,9 @@ impl CString {
|
||||
///
|
||||
/// extern { fn puts(s: *const c_char); }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let to_print = CString::new("Hello!").unwrap();
|
||||
/// unsafe {
|
||||
/// puts(to_print.as_ptr());
|
||||
/// }
|
||||
/// let to_print = CString::new("Hello!").unwrap();
|
||||
/// unsafe {
|
||||
/// puts(to_print.as_ptr());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
||||
@@ -110,7 +110,7 @@ fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<S
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true iff the address is unnamed.
|
||||
/// Returns true if and only if the address is unnamed.
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn is_unnamed(&self) -> bool {
|
||||
if let AddressKind::Unnamed = self.address() {
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
fn main() {
|
||||
let x = Some("s".to_string());
|
||||
match x {
|
||||
op_string @ Some(s) => {}, //~ ERROR E0007
|
||||
//~| ERROR E0303
|
||||
op_string @ Some(s) => {},
|
||||
//~^ ERROR E0007
|
||||
//~| NOTE binds an already bound by-move value by moving it
|
||||
//~| ERROR E0303
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
fn main() {
|
||||
match Some("hi".to_string()) {
|
||||
Some(s) if s.len() == 0 => {}, //~ ERROR E0008
|
||||
Some(s) if s.len() == 0 => {},
|
||||
//~^ ERROR E0008
|
||||
//~| NOTE moves value into pattern guard
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,16 @@
|
||||
const C: i32 = 2;
|
||||
|
||||
const CR: &'static mut i32 = &mut C; //~ ERROR E0017
|
||||
//~| NOTE constants require immutable values
|
||||
//~| ERROR E0017
|
||||
//~| NOTE constants require immutable values
|
||||
static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
|
||||
//~| NOTE statics require immutable values
|
||||
//~| ERROR E0017
|
||||
//~| NOTE statics require immutable values
|
||||
//~| ERROR E0388
|
||||
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
|
||||
//~| NOTE statics require immutable values
|
||||
//~| ERROR E0017
|
||||
|
||||
//~| NOTE statics require immutable values
|
||||
fn main() {}
|
||||
|
||||
@@ -12,7 +12,10 @@ trait Trait {
|
||||
fn foo(&self) -> Self;
|
||||
}
|
||||
|
||||
fn call_foo(x: Box<Trait>) { //~ ERROR E0038
|
||||
fn call_foo(x: Box<Trait>) {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait `Trait` cannot be made into an object
|
||||
//~| NOTE method `foo` references the `Self` type in its arguments or return type
|
||||
let y = x.foo();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
|
||||
extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
|
||||
//~| NOTE variadics require C calling conventions
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct ListNode { //~ ERROR E0072
|
||||
//~| NOTE recursive type has infinite size
|
||||
head: u8,
|
||||
tail: Option<ListNode>,
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
// except according to those terms.
|
||||
|
||||
enum Enum {
|
||||
P = 3,
|
||||
X = 3, //~ ERROR E0081
|
||||
P = 3, //~ NOTE first use of `3isize`
|
||||
X = 3,
|
||||
//~^ ERROR discriminant value `3isize` already exists
|
||||
//~| NOTE enum already has `3isize`
|
||||
Y = 5
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
type Foo<T> = u32; //~ ERROR E0091
|
||||
//~| NOTE unused type parameter
|
||||
type Foo2<A, B> = Box<A>; //~ ERROR E0091
|
||||
//~| NOTE unused type parameter
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#![feature(intrinsics)]
|
||||
extern "rust-intrinsic" {
|
||||
fn atomic_foo(); //~ ERROR E0092
|
||||
}
|
||||
} //~| NOTE unrecognized atomic operation
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo<T=U, U=()> { //~ ERROR E0128
|
||||
//~| NOTE defaulted type parameters cannot be forward declared
|
||||
field1: T,
|
||||
field2: U,
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
extern {
|
||||
fn foo((a, b): (u32, u32)); //~ ERROR E0130
|
||||
fn foo((a, b): (u32, u32));
|
||||
//~^ ERROR E0130
|
||||
//~| NOTE pattern not allowed in foreign function
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -11,5 +11,7 @@
|
||||
unsafe fn f() { return; }
|
||||
|
||||
fn main() {
|
||||
f(); //~ ERROR E0133
|
||||
f();
|
||||
//~^ ERROR E0133
|
||||
//~| NOTE unsafe call requires unsafe function or block
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } //~ ERROR E0263
|
||||
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
|
||||
//~^ ERROR E0263
|
||||
//~| NOTE declared twice
|
||||
//~| NOTE previous declaration here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
target_arch = "aarch64"))]
|
||||
pub fn main() {
|
||||
let x: isize;
|
||||
x = 1; //~ NOTE prior assignment occurs here
|
||||
x = 1; //~ NOTE first assignment
|
||||
foo(x);
|
||||
unsafe {
|
||||
asm!("mov $1, $0" : "=r"(x) : "r"(5));
|
||||
//~^ ERROR re-assignment of immutable variable `x`
|
||||
//~| NOTE re-assignment of immutable
|
||||
//~| NOTE in this expansion of asm!
|
||||
}
|
||||
foo(x);
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
|
||||
fn test() {
|
||||
let v: isize;
|
||||
v = 1; //~ NOTE prior assignment occurs here
|
||||
v = 1; //~ NOTE first assignment
|
||||
println!("v={}", v);
|
||||
v = 2; //~ ERROR re-assignment of immutable variable
|
||||
//~| NOTE re-assignment of immutable
|
||||
println!("v={}", v);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#![feature(associated_consts)]
|
||||
|
||||
trait Foo {
|
||||
const BAR: u32;
|
||||
const BAR: u32; //~ NOTE original trait requirement
|
||||
}
|
||||
|
||||
struct SignedBar;
|
||||
@@ -19,7 +19,7 @@ trait Foo {
|
||||
impl Foo for SignedBar {
|
||||
const BAR: i32 = -1;
|
||||
//~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
|
||||
//~| expected u32, found i32
|
||||
//~| NOTE expected u32, found i32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -29,6 +29,7 @@ fn main() {
|
||||
|
||||
let mut map = HashMap::new();
|
||||
//~^ ERROR E0433
|
||||
//~| NOTE Use of undeclared type or module `HashMap`
|
||||
|
||||
for line in input.lines() {
|
||||
let line = line.unwrap();
|
||||
|
||||
@@ -12,17 +12,20 @@
|
||||
|
||||
enum Foo {
|
||||
A = 1,
|
||||
//~^ NOTE first use
|
||||
//~| NOTE first use
|
||||
//~| NOTE first use
|
||||
B = 1, //~ ERROR discriminant value
|
||||
//~^ NOTE enum already
|
||||
//~^ NOTE first use of `1isize`
|
||||
//~| NOTE first use of `1isize`
|
||||
//~| NOTE first use of `1isize`
|
||||
B = 1,
|
||||
//~^ ERROR discriminant value `1isize` already exists
|
||||
//~| NOTE enum already has `1isize`
|
||||
C = 0,
|
||||
D, //~ ERROR discriminant value
|
||||
//~^ NOTE enum already
|
||||
D,
|
||||
//~^ ERROR discriminant value `1isize` already exists
|
||||
//~| NOTE enum already has `1isize`
|
||||
|
||||
E = N, //~ ERROR discriminant value
|
||||
//~^ NOTE enum already
|
||||
E = N,
|
||||
//~^ ERROR discriminant value `1isize` already exists
|
||||
//~| NOTE enum already has `1isize`
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
pub struct Foo<Bar=Bar>; //~ ERROR E0128
|
||||
//~| NOTE defaulted type parameters cannot be forward declared
|
||||
pub struct Baz(Foo);
|
||||
fn main() {}
|
||||
|
||||
@@ -15,10 +15,12 @@ fn f<T: Array>(x: &T) {
|
||||
//~^ ERROR `Array` cannot be made into an object
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
//~| NOTE requirements on the impl of `std::ops::CoerceUnsized<&Array>`
|
||||
//~| NOTE the trait `Array` cannot be made into an object
|
||||
as
|
||||
&Array;
|
||||
//~^ ERROR `Array` cannot be made into an object
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
//~| NOTE the trait `Array` cannot be made into an object
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -28,6 +28,7 @@ impl<K> Map for K {
|
||||
fn main() {
|
||||
let _ = &()
|
||||
as &Map<Key=u32,MapValue=u32>;
|
||||
//~^ ERROR the trait `Map` cannot be made into an object
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot use `Self` as a type parameter
|
||||
//~| NOTE the trait `Map` cannot be made into an object
|
||||
}
|
||||
|
||||
@@ -11,5 +11,7 @@
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
(&ptr::write)(1 as *mut _, 42); //~ ERROR E0133
|
||||
(&ptr::write)(1 as *mut _, 42);
|
||||
//~^ ERROR E0133
|
||||
//~| NOTE unsafe call requires unsafe function or block
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
enum foo { foo_(bar) }
|
||||
struct bar { x: bar }
|
||||
//~^ ERROR E0072
|
||||
//~| NOTE recursive type has infinite size
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// too big.
|
||||
|
||||
enum Expr { //~ ERROR E0072
|
||||
//~| NOTE recursive type has infinite size
|
||||
Plus(Expr, Expr),
|
||||
Literal(i64),
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct S { //~ ERROR E0072
|
||||
//~| NOTE recursive type has infinite size
|
||||
element: Option<S>
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ fn test() {
|
||||
let v: isize;
|
||||
loop {
|
||||
v = 1; //~ ERROR re-assignment of immutable variable
|
||||
//~^ NOTE prior assignment occurs here
|
||||
//~^ NOTE re-assignment of immutable variable
|
||||
v.clone(); // just to prevent liveness warnings
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
fn test() {
|
||||
let v: isize;
|
||||
v = 2; //~ NOTE prior assignment occurs here
|
||||
v = 2; //~ NOTE first assignment
|
||||
v += 1; //~ ERROR re-assignment of immutable variable
|
||||
//~| NOTE re-assignment of immutable
|
||||
v.clone();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn test() {
|
||||
let v: isize = 1; //~ NOTE prior assignment occurs here
|
||||
let v: isize = 1; //~ NOTE first assignment
|
||||
v.clone();
|
||||
v = 2; //~ ERROR re-assignment of immutable variable
|
||||
//~| NOTE re-assignment of immutable
|
||||
v.clone();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
|
||||
extern {
|
||||
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||
//~^ NOTE this is a recent error
|
||||
//~^ NOTE pattern not allowed in foreign function
|
||||
//~| NOTE this is a recent error
|
||||
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||
//~^ NOTE pattern not allowed in foreign function
|
||||
fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||
//~^ NOTE this is a recent error
|
||||
//~^ NOTE pattern not allowed in foreign function
|
||||
//~| NOTE this is a recent error
|
||||
fn g1(arg: u8); // OK
|
||||
fn g2(_: u8); // OK
|
||||
// fn g3(u8); // Not yet
|
||||
|
||||
@@ -24,12 +24,14 @@ fn bar<T>(&self, t: T)
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` has generic type parameters
|
||||
//~| NOTE the trait `Bar` cannot be made into an object
|
||||
t
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
|
||||
//~^ ERROR E0038
|
||||
//~^^ NOTE method `bar` has generic type parameters
|
||||
//~| NOTE method `bar` has generic type parameters
|
||||
//~| NOTE the trait `Bar` cannot be made into an object
|
||||
t as &Bar
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,14 @@ trait Quux {
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
//~| NOTE the trait `Bar` cannot be made into an object
|
||||
loop { }
|
||||
}
|
||||
|
||||
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE method `bar` references the `Self` type in its arguments or return type
|
||||
//~| NOTE the trait `Baz` cannot be made into an object
|
||||
t
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ trait Bar : Sized {
|
||||
fn make_bar<T:Bar>(t: &T) -> &Bar {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot require that `Self : Sized`
|
||||
//~| NOTE the trait `Bar` cannot be made into an object
|
||||
t
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
|
||||
fn make_baz<T:Baz>(t: &T) -> &Baz {
|
||||
//~^ ERROR E0038
|
||||
//~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
|
||||
//~| NOTE the trait `Baz` cannot be made into an object
|
||||
t
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ fn foo(self) { }
|
||||
unsafe impl UnsafeTrait for *mut isize {
|
||||
fn foo(self) {
|
||||
// Unsafe actions are not made legal by taking place in an unsafe trait:
|
||||
*self += 1; //~ ERROR E0133
|
||||
*self += 1;
|
||||
//~^ ERROR E0133
|
||||
//~| NOTE unsafe call requires unsafe function or block
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
struct t1 { //~ ERROR E0072
|
||||
//~| NOTE recursive type has infinite size
|
||||
foo: isize,
|
||||
foolish: t1
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
!v
|
||||
}
|
||||
|
||||
const VAL: u32 = dummy(0xFFFF); //~ ERROR E0133
|
||||
const VAL: u32 = dummy(0xFFFF);
|
||||
//~^ ERROR E0133
|
||||
//~| NOTE unsafe call requires unsafe function or block
|
||||
|
||||
fn main() {
|
||||
assert_eq!(VAL, 0xFFFF0000);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let x: &'static str = "x";
|
||||
|
||||
{
|
||||
let y = "y".to_string();
|
||||
let ref mut x = &*x;
|
||||
*x = &*y;
|
||||
}
|
||||
|
||||
assert_eq!(x, "x");
|
||||
}
|
||||
@@ -36,22 +36,22 @@ impl FromStr for Mode {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Mode, ()> {
|
||||
match s {
|
||||
"compile-fail" => Ok(CompileFail),
|
||||
"parse-fail" => Ok(ParseFail),
|
||||
"run-fail" => Ok(RunFail),
|
||||
"run-pass" => Ok(RunPass),
|
||||
"run-pass-valgrind" => Ok(RunPassValgrind),
|
||||
"pretty" => Ok(Pretty),
|
||||
"debuginfo-lldb" => Ok(DebugInfoLldb),
|
||||
"debuginfo-gdb" => Ok(DebugInfoGdb),
|
||||
"codegen" => Ok(Codegen),
|
||||
"rustdoc" => Ok(Rustdoc),
|
||||
"codegen-units" => Ok(CodegenUnits),
|
||||
"incremental" => Ok(Incremental),
|
||||
"run-make" => Ok(RunMake),
|
||||
"ui" => Ok(Ui),
|
||||
"mir-opt" => Ok(MirOpt),
|
||||
_ => Err(()),
|
||||
"compile-fail" => Ok(CompileFail),
|
||||
"parse-fail" => Ok(ParseFail),
|
||||
"run-fail" => Ok(RunFail),
|
||||
"run-pass" => Ok(RunPass),
|
||||
"run-pass-valgrind" => Ok(RunPassValgrind),
|
||||
"pretty" => Ok(Pretty),
|
||||
"debuginfo-lldb" => Ok(DebugInfoLldb),
|
||||
"debuginfo-gdb" => Ok(DebugInfoGdb),
|
||||
"codegen" => Ok(Codegen),
|
||||
"rustdoc" => Ok(Rustdoc),
|
||||
"codegen-units" => Ok(CodegenUnits),
|
||||
"incremental" => Ok(Incremental),
|
||||
"run-make" => Ok(RunMake),
|
||||
"ui" => Ok(Ui),
|
||||
"mir-opt" => Ok(MirOpt),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,22 +59,23 @@ fn from_str(s: &str) -> Result<Mode, ()> {
|
||||
impl fmt::Display for Mode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(match *self {
|
||||
CompileFail => "compile-fail",
|
||||
ParseFail => "parse-fail",
|
||||
RunFail => "run-fail",
|
||||
RunPass => "run-pass",
|
||||
RunPassValgrind => "run-pass-valgrind",
|
||||
Pretty => "pretty",
|
||||
DebugInfoGdb => "debuginfo-gdb",
|
||||
DebugInfoLldb => "debuginfo-lldb",
|
||||
Codegen => "codegen",
|
||||
Rustdoc => "rustdoc",
|
||||
CodegenUnits => "codegen-units",
|
||||
Incremental => "incremental",
|
||||
RunMake => "run-make",
|
||||
Ui => "ui",
|
||||
MirOpt => "mir-opt",
|
||||
}, f)
|
||||
CompileFail => "compile-fail",
|
||||
ParseFail => "parse-fail",
|
||||
RunFail => "run-fail",
|
||||
RunPass => "run-pass",
|
||||
RunPassValgrind => "run-pass-valgrind",
|
||||
Pretty => "pretty",
|
||||
DebugInfoGdb => "debuginfo-gdb",
|
||||
DebugInfoLldb => "debuginfo-lldb",
|
||||
Codegen => "codegen",
|
||||
Rustdoc => "rustdoc",
|
||||
CodegenUnits => "codegen-units",
|
||||
Incremental => "incremental",
|
||||
RunMake => "run-make",
|
||||
Ui => "ui",
|
||||
MirOpt => "mir-opt",
|
||||
},
|
||||
f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,11 @@ pub struct Error {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum WhichLine { ThisLine, FollowPrevious(usize), AdjustBackward(usize) }
|
||||
enum WhichLine {
|
||||
ThisLine,
|
||||
FollowPrevious(usize),
|
||||
AdjustBackward(usize),
|
||||
}
|
||||
|
||||
/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
|
||||
/// The former is a "follow" that inherits its target from the preceding line;
|
||||
@@ -91,25 +95,22 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
|
||||
|
||||
let tag = match cfg {
|
||||
Some(rev) => format!("//[{}]~", rev),
|
||||
None => format!("//~")
|
||||
None => format!("//~"),
|
||||
};
|
||||
|
||||
rdr.lines()
|
||||
.enumerate()
|
||||
.filter_map(|(line_num, line)| {
|
||||
parse_expected(last_nonfollow_error,
|
||||
line_num + 1,
|
||||
&line.unwrap(),
|
||||
&tag)
|
||||
.map(|(which, error)| {
|
||||
match which {
|
||||
FollowPrevious(_) => {}
|
||||
_ => last_nonfollow_error = Some(error.line_num),
|
||||
}
|
||||
error
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
.enumerate()
|
||||
.filter_map(|(line_num, line)| {
|
||||
parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag)
|
||||
.map(|(which, error)| {
|
||||
match which {
|
||||
FollowPrevious(_) => {}
|
||||
_ => last_nonfollow_error = Some(error.line_num),
|
||||
}
|
||||
error
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_expected(last_nonfollow_error: Option<usize>,
|
||||
@@ -117,7 +118,10 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
|
||||
line: &str,
|
||||
tag: &str)
|
||||
-> Option<(WhichLine, Error)> {
|
||||
let start = match line.find(tag) { Some(i) => i, None => return None };
|
||||
let start = match line.find(tag) {
|
||||
Some(i) => i,
|
||||
None => return None,
|
||||
};
|
||||
let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' {
|
||||
(true, 0)
|
||||
} else {
|
||||
@@ -125,26 +129,25 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
|
||||
};
|
||||
let kind_start = start + tag.len() + adjusts + (follow as usize);
|
||||
let (kind, msg);
|
||||
match
|
||||
line[kind_start..].split_whitespace()
|
||||
.next()
|
||||
.expect("Encountered unexpected empty comment")
|
||||
.parse::<ErrorKind>()
|
||||
{
|
||||
match line[kind_start..]
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.expect("Encountered unexpected empty comment")
|
||||
.parse::<ErrorKind>() {
|
||||
Ok(k) => {
|
||||
// If we find `//~ ERROR foo` or something like that:
|
||||
kind = Some(k);
|
||||
let letters = line[kind_start..].chars();
|
||||
msg = letters.skip_while(|c| c.is_whitespace())
|
||||
.skip_while(|c| !c.is_whitespace())
|
||||
.collect::<String>();
|
||||
.skip_while(|c| !c.is_whitespace())
|
||||
.collect::<String>();
|
||||
}
|
||||
Err(_) => {
|
||||
// Otherwise we found `//~ foo`:
|
||||
kind = None;
|
||||
let letters = line[kind_start..].chars();
|
||||
msg = letters.skip_while(|c| c.is_whitespace())
|
||||
.collect::<String>();
|
||||
.collect::<String>();
|
||||
}
|
||||
}
|
||||
let msg = msg.trim().to_owned();
|
||||
@@ -155,15 +158,25 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
|
||||
preceding //~^ line.");
|
||||
(FollowPrevious(line_num), line_num)
|
||||
} else {
|
||||
let which =
|
||||
if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine };
|
||||
let which = if adjusts > 0 {
|
||||
AdjustBackward(adjusts)
|
||||
} else {
|
||||
ThisLine
|
||||
};
|
||||
let line_num = line_num - adjusts;
|
||||
(which, line_num)
|
||||
};
|
||||
|
||||
debug!("line={} tag={:?} which={:?} kind={:?} msg={:?}",
|
||||
line_num, tag, which, kind, msg);
|
||||
Some((which, Error { line_num: line_num,
|
||||
kind: kind,
|
||||
msg: msg, }))
|
||||
line_num,
|
||||
tag,
|
||||
which,
|
||||
kind,
|
||||
msg);
|
||||
Some((which,
|
||||
Error {
|
||||
line_num: line_num,
|
||||
kind: kind,
|
||||
msg: msg,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -32,24 +32,21 @@ pub fn from_file(config: &Config, testfile: &Path) -> Self {
|
||||
should_fail: false,
|
||||
};
|
||||
|
||||
iter_header(testfile, None, &mut |ln| {
|
||||
iter_header(testfile,
|
||||
None,
|
||||
&mut |ln| {
|
||||
props.ignore =
|
||||
props.ignore ||
|
||||
parse_name_directive(ln, "ignore-test") ||
|
||||
props.ignore || parse_name_directive(ln, "ignore-test") ||
|
||||
parse_name_directive(ln, &ignore_target(config)) ||
|
||||
parse_name_directive(ln, &ignore_architecture(config)) ||
|
||||
parse_name_directive(ln, &ignore_stage(config)) ||
|
||||
parse_name_directive(ln, &ignore_env(config)) ||
|
||||
(config.mode == common::Pretty &&
|
||||
parse_name_directive(ln, "ignore-pretty")) ||
|
||||
(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) ||
|
||||
(config.target != config.host &&
|
||||
parse_name_directive(ln, "ignore-cross-compile")) ||
|
||||
ignore_gdb(config, ln) ||
|
||||
ignore_lldb(config, ln);
|
||||
ignore_gdb(config, ln) || ignore_lldb(config, ln);
|
||||
|
||||
props.should_fail =
|
||||
props.should_fail ||
|
||||
parse_name_directive(ln, "should-fail");
|
||||
props.should_fail = props.should_fail || parse_name_directive(ln, "should-fail");
|
||||
});
|
||||
|
||||
return props;
|
||||
@@ -61,11 +58,11 @@ fn ignore_architecture(config: &Config) -> String {
|
||||
format!("ignore-{}", util::get_arch(&config.target))
|
||||
}
|
||||
fn ignore_stage(config: &Config) -> String {
|
||||
format!("ignore-{}",
|
||||
config.stage_id.split('-').next().unwrap())
|
||||
format!("ignore-{}", config.stage_id.split('-').next().unwrap())
|
||||
}
|
||||
fn ignore_env(config: &Config) -> String {
|
||||
format!("ignore-{}", util::get_env(&config.target).unwrap_or("<unknown>"))
|
||||
format!("ignore-{}",
|
||||
util::get_env(&config.target).unwrap_or("<unknown>"))
|
||||
}
|
||||
fn ignore_gdb(config: &Config, line: &str) -> bool {
|
||||
if config.mode != common::DebugInfoGdb {
|
||||
@@ -79,13 +76,12 @@ fn ignore_gdb(config: &Config, line: &str) -> bool {
|
||||
if let Some(ref actual_version) = config.gdb_version {
|
||||
if line.contains("min-gdb-version") {
|
||||
let min_version = line.trim()
|
||||
.split(' ')
|
||||
.last()
|
||||
.expect("Malformed GDB version directive");
|
||||
.split(' ')
|
||||
.last()
|
||||
.expect("Malformed GDB version directive");
|
||||
// Ignore if actual version is smaller the minimum required
|
||||
// version
|
||||
gdb_version_to_int(actual_version) <
|
||||
gdb_version_to_int(min_version)
|
||||
gdb_version_to_int(actual_version) < gdb_version_to_int(min_version)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -106,13 +102,12 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
|
||||
if let Some(ref actual_version) = config.lldb_version {
|
||||
if line.contains("min-lldb-version") {
|
||||
let min_version = line.trim()
|
||||
.split(' ')
|
||||
.last()
|
||||
.expect("Malformed lldb version directive");
|
||||
.split(' ')
|
||||
.last()
|
||||
.expect("Malformed lldb version directive");
|
||||
// Ignore if actual version is smaller the minimum required
|
||||
// version
|
||||
lldb_version_to_int(actual_version) <
|
||||
lldb_version_to_int(min_version)
|
||||
lldb_version_to_int(actual_version) < lldb_version_to_int(min_version)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -126,7 +121,7 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TestProps {
|
||||
// Lines that should be expected, in order, on standard out
|
||||
pub error_patterns: Vec<String> ,
|
||||
pub error_patterns: Vec<String>,
|
||||
// Extra flags to pass to the compiler
|
||||
pub compile_flags: Vec<String>,
|
||||
// Extra flags to pass when the compiled code is run (such as --bench)
|
||||
@@ -137,13 +132,13 @@ pub struct TestProps {
|
||||
// Other crates that should be compiled (typically from the same
|
||||
// directory as the test, but for backwards compatibility reasons
|
||||
// we also check the auxiliary directory)
|
||||
pub aux_builds: Vec<String> ,
|
||||
pub aux_builds: Vec<String>,
|
||||
// Environment settings to use for compiling
|
||||
pub rustc_env: Vec<(String,String)> ,
|
||||
pub rustc_env: Vec<(String, String)>,
|
||||
// Environment settings to use during execution
|
||||
pub exec_env: Vec<(String,String)> ,
|
||||
pub exec_env: Vec<(String, String)>,
|
||||
// Lines to check if they appear in the expected debugger output
|
||||
pub check_lines: Vec<String> ,
|
||||
pub check_lines: Vec<String>,
|
||||
// Build documentation for all specified aux-builds as well
|
||||
pub build_aux_docs: bool,
|
||||
// Flag to force a crate to be built with the host architecture
|
||||
@@ -226,17 +221,17 @@ pub fn from_file(testfile: &Path) -> Self {
|
||||
/// tied to a particular revision `foo` (indicated by writing
|
||||
/// `//[foo]`), then the property is ignored unless `cfg` is
|
||||
/// `Some("foo")`.
|
||||
pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
|
||||
iter_header(testfile, cfg, &mut |ln| {
|
||||
pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
|
||||
iter_header(testfile,
|
||||
cfg,
|
||||
&mut |ln| {
|
||||
if let Some(ep) = parse_error_pattern(ln) {
|
||||
self.error_patterns.push(ep);
|
||||
}
|
||||
|
||||
if let Some(flags) = parse_compile_flags(ln) {
|
||||
self.compile_flags.extend(
|
||||
flags
|
||||
.split_whitespace()
|
||||
.map(|s| s.to_owned()));
|
||||
self.compile_flags.extend(flags.split_whitespace()
|
||||
.map(|s| s.to_owned()));
|
||||
}
|
||||
|
||||
if let Some(r) = parse_revisions(ln) {
|
||||
@@ -279,7 +274,7 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
|
||||
self.pretty_compare_only = parse_pretty_compare_only(ln);
|
||||
}
|
||||
|
||||
if let Some(ab) = parse_aux_build(ln) {
|
||||
if let Some(ab) = parse_aux_build(ln) {
|
||||
self.aux_builds.push(ab);
|
||||
}
|
||||
|
||||
@@ -291,7 +286,7 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
|
||||
self.rustc_env.push(ee);
|
||||
}
|
||||
|
||||
if let Some(cl) = parse_check_line(ln) {
|
||||
if let Some(cl) = parse_check_line(ln) {
|
||||
self.check_lines.push(cl);
|
||||
}
|
||||
|
||||
@@ -302,21 +297,20 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
|
||||
|
||||
for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
|
||||
match env::var(key) {
|
||||
Ok(val) =>
|
||||
Ok(val) => {
|
||||
if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() {
|
||||
self.exec_env.push((key.to_owned(), val))
|
||||
},
|
||||
}
|
||||
}
|
||||
Err(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_header(testfile: &Path,
|
||||
cfg: Option<&str>,
|
||||
it: &mut FnMut(&str)) {
|
||||
fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
|
||||
if testfile.is_dir() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let rdr = BufReader::new(File::open(testfile).unwrap());
|
||||
for ln in rdr.lines() {
|
||||
@@ -336,7 +330,7 @@ fn iter_header(testfile: &Path,
|
||||
None => false,
|
||||
};
|
||||
if matches {
|
||||
it(&ln[close_brace+1..]);
|
||||
it(&ln[close_brace + 1..]);
|
||||
}
|
||||
} else {
|
||||
panic!("malformed condition directive: expected `//[foo]`, found `{}`",
|
||||
@@ -409,18 +403,17 @@ fn parse_pretty_compare_only(line: &str) -> bool {
|
||||
fn parse_env(line: &str, name: &str) -> Option<(String, String)> {
|
||||
parse_name_value_directive(line, name).map(|nv| {
|
||||
// nv is either FOO or FOO=BAR
|
||||
let mut strs: Vec<String> = nv
|
||||
.splitn(2, '=')
|
||||
.map(str::to_owned)
|
||||
.collect();
|
||||
let mut strs: Vec<String> = nv.splitn(2, '=')
|
||||
.map(str::to_owned)
|
||||
.collect();
|
||||
|
||||
match strs.len() {
|
||||
1 => (strs.pop().unwrap(), "".to_owned()),
|
||||
2 => {
|
||||
let end = strs.pop().unwrap();
|
||||
(strs.pop().unwrap(), end)
|
||||
}
|
||||
n => panic!("Expected 1 or 2 strings, not {}", n)
|
||||
1 => (strs.pop().unwrap(), "".to_owned()),
|
||||
2 => {
|
||||
let end = strs.pop().unwrap();
|
||||
(strs.pop().unwrap(), end)
|
||||
}
|
||||
n => panic!("Expected 1 or 2 strings, not {}", n),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -442,11 +435,10 @@ fn parse_name_directive(line: &str, directive: &str) -> bool {
|
||||
line.contains(directive) && !line.contains(&("no-".to_owned() + directive))
|
||||
}
|
||||
|
||||
pub fn parse_name_value_directive(line: &str, directive: &str)
|
||||
-> Option<String> {
|
||||
pub fn parse_name_value_directive(line: &str, directive: &str) -> Option<String> {
|
||||
let keycolon = format!("{}:", directive);
|
||||
if let Some(colon) = line.find(&keycolon) {
|
||||
let value = line[(colon + keycolon.len()) .. line.len()].to_owned();
|
||||
let value = line[(colon + keycolon.len())..line.len()].to_owned();
|
||||
debug!("{}: {}", directive, value);
|
||||
Some(value)
|
||||
} else {
|
||||
@@ -455,9 +447,8 @@ pub fn parse_name_value_directive(line: &str, directive: &str)
|
||||
}
|
||||
|
||||
pub fn gdb_version_to_int(version_string: &str) -> isize {
|
||||
let error_string = format!(
|
||||
"Encountered GDB version string with unexpected format: {}",
|
||||
version_string);
|
||||
let error_string = format!("Encountered GDB version string with unexpected format: {}",
|
||||
version_string);
|
||||
let error_string = error_string;
|
||||
|
||||
let components: Vec<&str> = version_string.trim().split('.').collect();
|
||||
@@ -473,9 +464,8 @@ pub fn gdb_version_to_int(version_string: &str) -> isize {
|
||||
}
|
||||
|
||||
pub fn lldb_version_to_int(version_string: &str) -> isize {
|
||||
let error_string = format!(
|
||||
"Encountered LLDB version string with unexpected format: {}",
|
||||
version_string);
|
||||
let error_string = format!("Encountered LLDB version string with unexpected format: {}",
|
||||
version_string);
|
||||
let error_string = error_string;
|
||||
let major: isize = version_string.parse().ok().expect(&error_string);
|
||||
return major;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use rustc_serialize::json;
|
||||
use std::str::FromStr;
|
||||
use std::path::Path;
|
||||
use runtest::{ProcRes};
|
||||
use runtest::ProcRes;
|
||||
|
||||
// These structs are a subset of the ones found in
|
||||
// `syntax::json`.
|
||||
@@ -58,8 +58,8 @@ struct DiagnosticCode {
|
||||
|
||||
pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
|
||||
output.lines()
|
||||
.flat_map(|line| parse_line(file_name, line, output, proc_res))
|
||||
.collect()
|
||||
.flat_map(|line| parse_line(file_name, line, output, proc_res))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
|
||||
@@ -73,9 +73,11 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
|
||||
expected_errors
|
||||
}
|
||||
Err(error) => {
|
||||
proc_res.fatal(Some(&format!(
|
||||
"failed to decode compiler output as json: `{}`\noutput: {}\nline: {}",
|
||||
error, line, output)));
|
||||
proc_res.fatal(Some(&format!("failed to decode compiler output as json: \
|
||||
`{}`\noutput: {}\nline: {}",
|
||||
error,
|
||||
line,
|
||||
output)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -87,16 +89,15 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
|
||||
diagnostic: &Diagnostic,
|
||||
default_spans: &[&DiagnosticSpan],
|
||||
file_name: &str) {
|
||||
let spans_in_this_file: Vec<_> =
|
||||
diagnostic.spans.iter()
|
||||
.filter(|span| Path::new(&span.file_name) == Path::new(&file_name))
|
||||
.collect();
|
||||
let spans_in_this_file: Vec<_> = diagnostic.spans
|
||||
.iter()
|
||||
.filter(|span| Path::new(&span.file_name) == Path::new(&file_name))
|
||||
.collect();
|
||||
|
||||
let primary_spans: Vec<_> =
|
||||
spans_in_this_file.iter()
|
||||
.cloned()
|
||||
.filter(|span| span.is_primary)
|
||||
.collect();
|
||||
let primary_spans: Vec<_> = spans_in_this_file.iter()
|
||||
.cloned()
|
||||
.filter(|span| span.is_primary)
|
||||
.collect();
|
||||
let primary_spans = if primary_spans.is_empty() {
|
||||
// subdiagnostics often don't have a span of their own;
|
||||
// inherit the span from the parent in that case
|
||||
@@ -144,24 +145,20 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
|
||||
for span in primary_spans {
|
||||
let msg = with_code(span, first_line);
|
||||
let kind = ErrorKind::from_str(&diagnostic.level).ok();
|
||||
expected_errors.push(
|
||||
Error {
|
||||
line_num: span.line_start,
|
||||
kind: kind,
|
||||
msg: msg,
|
||||
}
|
||||
);
|
||||
expected_errors.push(Error {
|
||||
line_num: span.line_start,
|
||||
kind: kind,
|
||||
msg: msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
for next_line in message_lines {
|
||||
for span in primary_spans {
|
||||
expected_errors.push(
|
||||
Error {
|
||||
line_num: span.line_start,
|
||||
kind: None,
|
||||
msg: with_code(span, next_line),
|
||||
}
|
||||
);
|
||||
expected_errors.push(Error {
|
||||
line_num: span.line_start,
|
||||
kind: None,
|
||||
msg: with_code(span, next_line),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,33 +167,28 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
|
||||
let start_line = primary_spans.iter().map(|s| s.line_start).min().expect("\
|
||||
every suggestion should have at least one span");
|
||||
for (index, line) in rendered.lines().enumerate() {
|
||||
expected_errors.push(
|
||||
Error {
|
||||
line_num: start_line + index,
|
||||
kind: Some(ErrorKind::Suggestion),
|
||||
msg: line.to_string()
|
||||
}
|
||||
);
|
||||
expected_errors.push(Error {
|
||||
line_num: start_line + index,
|
||||
kind: Some(ErrorKind::Suggestion),
|
||||
msg: line.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add notes for the backtrace
|
||||
for span in primary_spans {
|
||||
for frame in &span.expansion {
|
||||
push_backtrace(expected_errors,
|
||||
frame,
|
||||
file_name);
|
||||
push_backtrace(expected_errors, frame, file_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Add notes for any labels that appear in the message.
|
||||
for span in spans_in_this_file.iter()
|
||||
.filter(|span| span.label.is_some())
|
||||
{
|
||||
.filter(|span| span.label.is_some()) {
|
||||
expected_errors.push(Error {
|
||||
line_num: span.line_start,
|
||||
kind: Some(ErrorKind::Note),
|
||||
msg: span.label.clone().unwrap()
|
||||
msg: span.label.clone().unwrap(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -210,13 +202,11 @@ fn push_backtrace(expected_errors: &mut Vec<Error>,
|
||||
expansion: &DiagnosticSpanMacroExpansion,
|
||||
file_name: &str) {
|
||||
if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
|
||||
expected_errors.push(
|
||||
Error {
|
||||
line_num: expansion.span.line_start,
|
||||
kind: Some(ErrorKind::Note),
|
||||
msg: format!("in this expansion of {}", expansion.macro_decl_name),
|
||||
}
|
||||
);
|
||||
expected_errors.push(Error {
|
||||
line_num: expansion.span.line_start,
|
||||
kind: Some(ErrorKind::Note),
|
||||
msg: format!("in this expansion of {}", expansion.macro_decl_name),
|
||||
});
|
||||
}
|
||||
|
||||
for previous_expansion in &expansion.span.expansion {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use std::ffi::OsString;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{ExitStatus, Command, Child, Output, Stdio};
|
||||
use std::process::{Child, Command, ExitStatus, Output, Stdio};
|
||||
|
||||
pub fn dylib_env_var() -> &'static str {
|
||||
if cfg!(windows) {
|
||||
@@ -29,7 +29,7 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
|
||||
// search path for the child.
|
||||
let var = dylib_env_var();
|
||||
let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
|
||||
.collect::<Vec<_>>();
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(p) = aux_path {
|
||||
path.insert(0, PathBuf::from(p))
|
||||
}
|
||||
@@ -40,20 +40,25 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
|
||||
cmd.env(var, newpath);
|
||||
}
|
||||
|
||||
pub struct Result {pub status: ExitStatus, pub out: String, pub err: String}
|
||||
pub struct Result {
|
||||
pub status: ExitStatus,
|
||||
pub out: String,
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
pub fn run(lib_path: &str,
|
||||
prog: &str,
|
||||
aux_path: Option<&str>,
|
||||
args: &[String],
|
||||
env: Vec<(String, String)> ,
|
||||
input: Option<String>) -> Option<Result> {
|
||||
env: Vec<(String, String)>,
|
||||
input: Option<String>)
|
||||
-> Option<Result> {
|
||||
|
||||
let mut cmd = Command::new(prog);
|
||||
cmd.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
add_target_env(&mut cmd, lib_path, aux_path);
|
||||
for (key, val) in env {
|
||||
cmd.env(&key, &val);
|
||||
@@ -64,31 +69,31 @@ pub fn run(lib_path: &str,
|
||||
if let Some(input) = input {
|
||||
process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
|
||||
}
|
||||
let Output { status, stdout, stderr } =
|
||||
process.wait_with_output().unwrap();
|
||||
let Output { status, stdout, stderr } = process.wait_with_output().unwrap();
|
||||
|
||||
Some(Result {
|
||||
status: status,
|
||||
out: String::from_utf8(stdout).unwrap(),
|
||||
err: String::from_utf8(stderr).unwrap()
|
||||
err: String::from_utf8(stderr).unwrap(),
|
||||
})
|
||||
},
|
||||
Err(..) => None
|
||||
}
|
||||
Err(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_background(lib_path: &str,
|
||||
prog: &str,
|
||||
aux_path: Option<&str>,
|
||||
args: &[String],
|
||||
env: Vec<(String, String)> ,
|
||||
input: Option<String>) -> Option<Child> {
|
||||
prog: &str,
|
||||
aux_path: Option<&str>,
|
||||
args: &[String],
|
||||
env: Vec<(String, String)>,
|
||||
input: Option<String>)
|
||||
-> Option<Child> {
|
||||
|
||||
let mut cmd = Command::new(prog);
|
||||
cmd.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
add_target_env(&mut cmd, lib_path, aux_path);
|
||||
for (key, val) in env {
|
||||
cmd.env(&key, &val);
|
||||
@@ -101,7 +106,7 @@ pub fn run_background(lib_path: &str,
|
||||
}
|
||||
|
||||
Some(process)
|
||||
},
|
||||
Err(..) => None
|
||||
}
|
||||
Err(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,14 +34,21 @@ pub unsafe fn raise_fd_limit() {
|
||||
let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
|
||||
let mut maxfiles: libc::c_int = 0;
|
||||
let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
|
||||
if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size,
|
||||
null_mut(), 0) != 0 {
|
||||
if libc::sysctl(&mut mib[0],
|
||||
2,
|
||||
&mut maxfiles as *mut _ as *mut _,
|
||||
&mut size,
|
||||
null_mut(),
|
||||
0) != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
panic!("raise_fd_limit: error calling sysctl: {}", err);
|
||||
}
|
||||
|
||||
// Fetch the current resource limits
|
||||
let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0};
|
||||
let mut rlim = libc::rlimit {
|
||||
rlim_cur: 0,
|
||||
rlim_max: 0,
|
||||
};
|
||||
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
panic!("raise_fd_limit: error calling getrlimit: {}", err);
|
||||
|
||||
@@ -13,24 +13,23 @@
|
||||
|
||||
pub fn diff_lines(actual: &str, expected: &str) -> Vec<String> {
|
||||
// mega simplistic diff algorithm that just prints the things added/removed
|
||||
zip_all(actual.lines(), expected.lines()).enumerate().filter_map(|(i, (a,e))| {
|
||||
match (a, e) {
|
||||
(Some(a), Some(e)) => {
|
||||
if lines_match(e, a) {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{:3} - |{}|\n + |{}|\n", i, e, a))
|
||||
zip_all(actual.lines(), expected.lines())
|
||||
.enumerate()
|
||||
.filter_map(|(i, (a, e))| {
|
||||
match (a, e) {
|
||||
(Some(a), Some(e)) => {
|
||||
if lines_match(e, a) {
|
||||
None
|
||||
} else {
|
||||
Some(format!("{:3} - |{}|\n + |{}|\n", i, e, a))
|
||||
}
|
||||
}
|
||||
},
|
||||
(Some(a), None) => {
|
||||
Some(format!("{:3} -\n + |{}|\n", i, a))
|
||||
},
|
||||
(None, Some(e)) => {
|
||||
Some(format!("{:3} - |{}|\n +\n", i, e))
|
||||
},
|
||||
(None, None) => panic!("Cannot get here")
|
||||
}
|
||||
}).collect()
|
||||
(Some(a), None) => Some(format!("{:3} -\n + |{}|\n", i, a)),
|
||||
(None, Some(e)) => Some(format!("{:3} - |{}|\n +\n", i, e)),
|
||||
(None, None) => panic!("Cannot get here"),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn lines_match(expected: &str, mut actual: &str) -> bool {
|
||||
@@ -38,13 +37,11 @@ fn lines_match(expected: &str, mut actual: &str) -> bool {
|
||||
match actual.find(part) {
|
||||
Some(j) => {
|
||||
if i == 0 && j != 0 {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
actual = &actual[j + part.len()..];
|
||||
}
|
||||
None => {
|
||||
return false
|
||||
}
|
||||
None => return false,
|
||||
}
|
||||
}
|
||||
actual.is_empty() || expected.ends_with("[..]")
|
||||
@@ -55,7 +52,7 @@ struct ZipAll<I1: Iterator, I2: Iterator> {
|
||||
second: I2,
|
||||
}
|
||||
|
||||
impl<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>> Iterator for ZipAll<I1, I2> {
|
||||
impl<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Iterator for ZipAll<I1, I2> {
|
||||
type Item = (Option<T>, Option<T>);
|
||||
fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
|
||||
let first = self.first.next();
|
||||
@@ -63,12 +60,12 @@ fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
|
||||
|
||||
match (first, second) {
|
||||
(None, None) => None,
|
||||
(a, b) => Some((a, b))
|
||||
(a, b) => Some((a, b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn zip_all<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
|
||||
fn zip_all<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
|
||||
ZipAll {
|
||||
first: a,
|
||||
second: b,
|
||||
|
||||
@@ -12,46 +12,42 @@
|
||||
use common::Config;
|
||||
|
||||
/// Conversion table from triple OS name to Rust SYSNAME
|
||||
const OS_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
("android", "android"),
|
||||
("bitrig", "bitrig"),
|
||||
("darwin", "macos"),
|
||||
("dragonfly", "dragonfly"),
|
||||
("freebsd", "freebsd"),
|
||||
("ios", "ios"),
|
||||
("linux", "linux"),
|
||||
("mingw32", "windows"),
|
||||
("netbsd", "netbsd"),
|
||||
("openbsd", "openbsd"),
|
||||
("win32", "windows"),
|
||||
("windows", "windows"),
|
||||
("solaris", "solaris"),
|
||||
("emscripten", "emscripten"),
|
||||
];
|
||||
const OS_TABLE: &'static [(&'static str, &'static str)] = &[("android", "android"),
|
||||
("bitrig", "bitrig"),
|
||||
("darwin", "macos"),
|
||||
("dragonfly", "dragonfly"),
|
||||
("freebsd", "freebsd"),
|
||||
("ios", "ios"),
|
||||
("linux", "linux"),
|
||||
("mingw32", "windows"),
|
||||
("netbsd", "netbsd"),
|
||||
("openbsd", "openbsd"),
|
||||
("win32", "windows"),
|
||||
("windows", "windows"),
|
||||
("solaris", "solaris"),
|
||||
("emscripten", "emscripten")];
|
||||
|
||||
const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
("aarch64", "aarch64"),
|
||||
("amd64", "x86_64"),
|
||||
("arm", "arm"),
|
||||
("arm64", "aarch64"),
|
||||
("hexagon", "hexagon"),
|
||||
("i386", "x86"),
|
||||
("i686", "x86"),
|
||||
("mips", "mips"),
|
||||
("msp430", "msp430"),
|
||||
("powerpc", "powerpc"),
|
||||
("powerpc64", "powerpc64"),
|
||||
("s390x", "systemz"),
|
||||
("sparc", "sparc"),
|
||||
("x86_64", "x86_64"),
|
||||
("xcore", "xcore"),
|
||||
("asmjs", "asmjs"),
|
||||
];
|
||||
const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[("aarch64", "aarch64"),
|
||||
("amd64", "x86_64"),
|
||||
("arm", "arm"),
|
||||
("arm64", "aarch64"),
|
||||
("hexagon", "hexagon"),
|
||||
("i386", "x86"),
|
||||
("i686", "x86"),
|
||||
("mips", "mips"),
|
||||
("msp430", "msp430"),
|
||||
("powerpc", "powerpc"),
|
||||
("powerpc64", "powerpc64"),
|
||||
("s390x", "systemz"),
|
||||
("sparc", "sparc"),
|
||||
("x86_64", "x86_64"),
|
||||
("xcore", "xcore"),
|
||||
("asmjs", "asmjs")];
|
||||
|
||||
pub fn get_os(triple: &str) -> &'static str {
|
||||
for &(triple_os, os) in OS_TABLE {
|
||||
if triple.contains(triple_os) {
|
||||
return os
|
||||
return os;
|
||||
}
|
||||
}
|
||||
panic!("Cannot determine OS from triple");
|
||||
@@ -59,7 +55,7 @@ pub fn get_os(triple: &str) -> &'static str {
|
||||
pub fn get_arch(triple: &str) -> &'static str {
|
||||
for &(triple_arch, arch) in ARCH_TABLE {
|
||||
if triple.contains(triple_arch) {
|
||||
return arch
|
||||
return arch;
|
||||
}
|
||||
}
|
||||
panic!("Cannot determine Architecture from triple");
|
||||
@@ -74,17 +70,21 @@ pub fn make_new_path(path: &str) -> String {
|
||||
// Windows just uses PATH as the library search path, so we have to
|
||||
// maintain the current value while adding our own
|
||||
match env::var(lib_path_env_var()) {
|
||||
Ok(curr) => {
|
||||
format!("{}{}{}", path, path_div(), curr)
|
||||
}
|
||||
Err(..) => path.to_owned()
|
||||
Ok(curr) => format!("{}{}{}", path, path_div(), curr),
|
||||
Err(..) => path.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lib_path_env_var() -> &'static str { "PATH" }
|
||||
fn path_div() -> &'static str { ";" }
|
||||
pub fn lib_path_env_var() -> &'static str {
|
||||
"PATH"
|
||||
}
|
||||
fn path_div() -> &'static str {
|
||||
";"
|
||||
}
|
||||
|
||||
pub fn logv(config: &Config, s: String) {
|
||||
debug!("{}", s);
|
||||
if config.verbose { println!("{}", s); }
|
||||
if config.verbose {
|
||||
println!("{}", s);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user