From 38abca8c2d7de08861cd61bc439efdb7cf4de398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 22 Jul 2018 22:40:24 -0700 Subject: [PATCH 01/43] Point at internal span in format string --- src/libfmt_macros/lib.rs | 17 +- src/libsyntax_ext/format.rs | 34 ++-- src/test/{compile-fail => ui}/ifmt-bad-arg.rs | 0 src/test/ui/ifmt-bad-arg.stderr | 187 ++++++++++++++++++ .../ui/macros/macro-backtrace-println.stderr | 4 +- 5 files changed, 224 insertions(+), 18 deletions(-) rename src/test/{compile-fail => ui}/ifmt-bad-arg.rs (100%) create mode 100644 src/test/ui/ifmt-bad-arg.stderr diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 9952e5f64d6ab..f6dcebf8c50f5 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -154,6 +154,7 @@ pub struct Parser<'a> { style: Option, /// How many newlines have been seen in the string so far, to adjust the error spans seen_newlines: usize, + pub arg_places: Vec<(usize, usize)>, } impl<'a> Iterator for Parser<'a> { @@ -168,9 +169,13 @@ impl<'a> Iterator for Parser<'a> { if self.consume('{') { Some(String(self.string(pos + 1))) } else { - let ret = Some(NextArgument(self.argument())); - self.must_consume('}'); - ret + let mut arg = self.argument(); + if let Some(arg_pos) = self.must_consume('}').map(|end| { + (pos + raw + 1, end + raw + 2) + }) { + self.arg_places.push(arg_pos); + } + Some(NextArgument(arg)) } } '}' => { @@ -211,6 +216,7 @@ impl<'a> Parser<'a> { curarg: 0, style, seen_newlines: 0, + arg_places: vec![], } } @@ -271,7 +277,7 @@ impl<'a> Parser<'a> { /// Forces consumption of the specified character. If the character is not /// found, an error is emitted. - fn must_consume(&mut self, c: char) { + fn must_consume(&mut self, c: char) -> Option { self.ws(); let raw = self.style.unwrap_or(0); @@ -279,12 +285,14 @@ impl<'a> Parser<'a> { if let Some(&(pos, maybe)) = self.cur.peek() { if c == maybe { self.cur.next(); + Some(pos) } else { let pos = pos + padding + 1; self.err(format!("expected `{:?}`, found `{:?}`", c, maybe), format!("expected `{}`", c), pos, pos); + None } } else { let msg = format!("expected `{:?}` but string was terminated", c); @@ -302,6 +310,7 @@ impl<'a> Parser<'a> { } else { self.err(msg, format!("expected `{:?}`", c), pos, pos); } + None } } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 755d2b476b716..4700f814e5853 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -21,7 +21,7 @@ use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::Symbol; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::{Span, MultiSpan, DUMMY_SP}; use syntax::tokenstream; use std::collections::{HashMap, HashSet}; @@ -264,28 +264,38 @@ impl<'a, 'b> Context<'a, 'b> { /// errors for the case where all arguments are positional and for when /// there are named arguments or numbered positional arguments in the /// format string. - fn report_invalid_references(&self, numbered_position_args: bool) { + fn report_invalid_references(&self, numbered_position_args: bool, arg_places: &[(usize, usize)]) { let mut e; - let mut refs: Vec = self.invalid_refs - .iter() - .map(|r| r.to_string()) - .collect(); + let sps = arg_places.iter() + .map(|&(start, end)| self.fmtsp.from_inner_byte_pos(start, end)) + .collect::>(); + let sp = MultiSpan::from_spans(sps); + let mut refs: Vec<_> = self.invalid_refs + .iter() + .map(|r| r.to_string()) + .collect(); if self.names.is_empty() && !numbered_position_args { - e = self.ecx.mut_span_err(self.fmtsp, + e = self.ecx.mut_span_err(sp, &format!("{} positional argument{} in format string, but {}", self.pieces.len(), if self.pieces.len() > 1 { "s" } else { "" }, self.describe_num_args())); } else { let arg_list = match refs.len() { - 1 => format!("argument {}", refs.pop().unwrap()), - _ => format!("arguments {head} and {tail}", - tail=refs.pop().unwrap(), + 1 => { + let reg = refs.pop().unwrap(); + format!("argument {}", reg) + }, + _ => { + let reg = refs.pop().unwrap(); + format!("arguments {head} and {tail}", + tail=reg, head=refs.join(", ")) + } }; - e = self.ecx.mut_span_err(self.fmtsp, + e = self.ecx.mut_span_err(sp, &format!("invalid reference to positional {} ({})", arg_list, self.describe_num_args())); @@ -835,7 +845,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } if cx.invalid_refs.len() >= 1 { - cx.report_invalid_references(numbered_position_args); + cx.report_invalid_references(numbered_position_args, &parser.arg_places); } // Make sure that all arguments were used and all arguments have types. diff --git a/src/test/compile-fail/ifmt-bad-arg.rs b/src/test/ui/ifmt-bad-arg.rs similarity index 100% rename from src/test/compile-fail/ifmt-bad-arg.rs rename to src/test/ui/ifmt-bad-arg.rs diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr new file mode 100644 index 0000000000000..4ad3c2b655047 --- /dev/null +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -0,0 +1,187 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:16:14 + | +LL | format!("{}"); + | ^^ + +error: invalid reference to positional argument 1 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:19:14 + | +LL | format!("{1}", 1); + | ^^^ + | + = note: positional arguments are zero-based + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:19:20 + | +LL | format!("{1}", 1); + | ^ + +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:23:14 + | +LL | format!("{} {}"); + | ^^ ^^ + +error: invalid reference to positional argument 1 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:26:14 + | +LL | format!("{0} {1}", 1); + | ^^^ ^^^ + | + = note: positional arguments are zero-based + +error: invalid reference to positional argument 2 (there are 2 arguments) + --> $DIR/ifmt-bad-arg.rs:29:14 + | +LL | format!("{0} {1} {2}", 1, 2); + | ^^^ ^^^ ^^^ + | + = note: positional arguments are zero-based + +error: invalid reference to positional argument 2 (there are 2 arguments) + --> $DIR/ifmt-bad-arg.rs:32:14 + | +LL | format!("{} {value} {} {}", 1, value=2); + | ^^ ^^^^^^^ ^^ ^^ + | + = note: positional arguments are zero-based + +error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments) + --> $DIR/ifmt-bad-arg.rs:34:14 + | +LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); + | ^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ + | + = note: positional arguments are zero-based + +error: there is no argument named `foo` + --> $DIR/ifmt-bad-arg.rs:37:13 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: there is no argument named `bar` + --> $DIR/ifmt-bad-arg.rs:37:13 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: there is no argument named `foo` + --> $DIR/ifmt-bad-arg.rs:41:13 + | +LL | format!("{foo}"); //~ ERROR: no argument named `foo` + | ^^^^^^^ + +error: multiple unused formatting arguments + --> $DIR/ifmt-bad-arg.rs:42:17 + | +LL | format!("", 1, 2); //~ ERROR: multiple unused formatting arguments + | -- ^ ^ + | | + | multiple missing formatting arguments + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:43:22 + | +LL | format!("{}", 1, 2); //~ ERROR: argument never used + | ^ + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:44:20 + | +LL | format!("{1}", 1, 2); //~ ERROR: argument never used + | ^ + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:45:26 + | +LL | format!("{}", 1, foo=2); //~ ERROR: named argument never used + | ^ + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:46:22 + | +LL | format!("{foo}", 1, foo=2); //~ ERROR: argument never used + | ^ + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:47:21 + | +LL | format!("", foo=2); //~ ERROR: named argument never used + | ^ + +error: multiple unused formatting arguments + --> $DIR/ifmt-bad-arg.rs:48:32 + | +LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments + | ------- ^ ^ + | | + | multiple missing formatting arguments + +error: duplicate argument named `foo` + --> $DIR/ifmt-bad-arg.rs:50:33 + | +LL | format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument + | ^ + | +note: previously here + --> $DIR/ifmt-bad-arg.rs:50:26 + | +LL | format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument + | ^ + +error: expected ident, positional arguments cannot follow named arguments + --> $DIR/ifmt-bad-arg.rs:51:24 + | +LL | format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow + | ^ + +error: there is no argument named `valueb` + --> $DIR/ifmt-bad-arg.rs:55:13 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ^^^^^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:55:51 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ^ + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/ifmt-bad-arg.rs:61:15 + | +LL | format!("{"); //~ ERROR: expected `'}'` but string was terminated + | ^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/ifmt-bad-arg.rs:63:18 + | +LL | format!("foo } bar"); //~ ERROR: unmatched `}` found + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/ifmt-bad-arg.rs:64:18 + | +LL | format!("foo }"); //~ ERROR: unmatched `}` found + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:66:27 + | +LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used + | ^^^^^ + | + = help: `%s` should be written as `{}` + = note: printf formatting not supported; see the documentation for `std::fmt` + +error: aborting due to 26 previous errors + diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 8f2eb0173a499..f0ca576f652eb 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -1,8 +1,8 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-backtrace-println.rs:24:30 + --> $DIR/macro-backtrace-println.rs:24:31 | LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); //~ ERROR no arguments were given - | ^^^^^^^^^^^^^^^^^^^ + | ^^ ... LL | myprintln!("{}"); | ----------------- in this macro invocation From 87f0c1f33789df39db871857055a2d7d533da47f Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Mon, 23 Jul 2018 22:16:53 +0800 Subject: [PATCH 02/43] Suggest to take and ignore args while closure args count mismatching --- src/librustc/traits/error_reporting.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index df26ac670601c..1c502b6610302 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1048,7 +1048,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); if let Some(found_span) = found_span { - err.span_label(found_span, format!("takes {}", found_str)); + // Suggest to take and ignore the arguments with expected_args_length `_`s if + // found arguments is empty(Suppose the user just wants to ignore args in this case). + // like `|_, _|` for closure with 2 expected args. + if found_args.is_empty() && is_closure { + let mut underscores = "_".repeat(expected_args.len()) + .split("") + .filter(|s| !s.is_empty()) + .collect::>() + .join(", "); + err.span_suggestion( + found_span, + "consider changing this to", + format!("|{}|", underscores), + ); + } else { + err.span_label(found_span, format!("takes {}", found_str)); + } + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { if fields.len() == expected_args.len() { From 42306591b9c0a280da363c83df16b47ad8b04024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jul 2018 00:01:17 -0700 Subject: [PATCH 03/43] Point at incorrect named arg in format string --- src/libsyntax_ext/format.rs | 21 +++++++++++++++++++-- src/test/ui/ifmt-bad-arg.stderr | 16 ++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 4700f814e5853..215e4f5a83523 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -111,8 +111,10 @@ struct Context<'a, 'b: 'a> { /// still existed in this phase of processing. /// Used only for `all_pieces_simple` tracking in `build_piece`. curarg: usize, + curpiece: usize, /// Keep track of invalid references to positional arguments invalid_refs: Vec, + arg_spans: Vec, } /// Parses the arguments from the given list of tokens, returning None @@ -235,6 +237,7 @@ impl<'a, 'b> Context<'a, 'b> { let ty = Placeholder(arg.format.ty.to_string()); self.verify_arg_type(pos, ty); + self.curpiece += 1; } } } @@ -347,7 +350,9 @@ impl<'a, 'b> Context<'a, 'b> { Some(e) => *e, None => { let msg = format!("there is no argument named `{}`", name); - self.ecx.span_err(self.fmtsp, &msg[..]); + let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp); + let mut err = self.ecx.struct_span_err(sp, &msg[..]); + err.emit(); return; } }; @@ -773,6 +778,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, arg_unique_types, names, curarg: 0, + curpiece: 0, arg_index_map: Vec::new(), count_args: Vec::new(), count_positions: HashMap::new(), @@ -785,6 +791,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, macsp, fmtsp: fmt.span, invalid_refs: Vec::new(), + arg_spans: Vec::new(), }; let fmt_str = &*fmt.node.0.as_str(); @@ -793,12 +800,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, ast::StrStyle::Raw(raw) => Some(raw as usize), }; let mut parser = parse::Parser::new(fmt_str, str_style); + let mut unverified_pieces = vec![]; let mut pieces = vec![]; - while let Some(mut piece) = parser.next() { + while let Some(piece) = parser.next() { if !parser.errors.is_empty() { break; } + unverified_pieces.push(piece); + } + + cx.arg_spans = parser.arg_places.iter() + .map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end)) + .collect(); + + // This needs to happen *after* the Parser has consumed all pieces to create all the spans + for mut piece in unverified_pieces { cx.verify_piece(&piece); cx.resolve_name_inplace(&mut piece); pieces.push(piece); diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index 4ad3c2b655047..2d49c36c06de1 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -57,22 +57,22 @@ LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); = note: positional arguments are zero-based error: there is no argument named `foo` - --> $DIR/ifmt-bad-arg.rs:37:13 + --> $DIR/ifmt-bad-arg.rs:37:17 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: there is no argument named `bar` - --> $DIR/ifmt-bad-arg.rs:37:13 + --> $DIR/ifmt-bad-arg.rs:37:26 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: there is no argument named `foo` - --> $DIR/ifmt-bad-arg.rs:41:13 + --> $DIR/ifmt-bad-arg.rs:41:14 | LL | format!("{foo}"); //~ ERROR: no argument named `foo` - | ^^^^^^^ + | ^^^^^ error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:42:17 @@ -139,10 +139,10 @@ LL | format!("", foo=1, 2); //~ ERROR: positional arguments cannot | ^ error: there is no argument named `valueb` - --> $DIR/ifmt-bad-arg.rs:55:13 + --> $DIR/ifmt-bad-arg.rs:55:23 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: named argument never used --> $DIR/ifmt-bad-arg.rs:55:51 From 338d545b9062a3efec018c05c2f8834778c9cf2d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 22 Jul 2018 16:02:31 +0100 Subject: [PATCH 04/43] Don't match on region kinds when reporting NLL errors With NLL region kinds are always ReVar --- .../borrow_check/error_reporting.rs | 109 +++--------------- ...rrowck-escaping-closure-error-1.nll.stderr | 2 +- ...rrowck-escaping-closure-error-2.nll.stderr | 2 +- .../dropck-eyepatch-extern-crate.nll.stderr | 2 +- .../dropck/dropck-eyepatch-reorder.nll.stderr | 2 +- src/test/ui/dropck/dropck-eyepatch.nll.stderr | 2 +- src/test/ui/error-codes/E0597.nll.stderr | 2 +- src/test/ui/generator/borrowing.nll.stderr | 4 +- src/test/ui/generator/dropck.nll.stderr | 4 +- .../ref-escapes-but-not-over-yield.nll.stderr | 2 +- src/test/ui/issue-12470.nll.stderr | 2 +- src/test/ui/issue-13497-2.nll.stderr | 18 +++ src/test/ui/issue-17954.ast.nll.stderr | 2 +- src/test/ui/issue-17954.mir.stderr | 2 +- src/test/ui/issue-17954.rs | 2 +- src/test/ui/issue-18118.nll.stderr | 2 +- src/test/ui/issue-30438-c.nll.stderr | 2 +- src/test/ui/issue-4335.nll.stderr | 2 +- src/test/ui/issue-46036.stderr | 2 +- src/test/ui/issue-46471-1.stderr | 2 +- src/test/ui/issue-46471.stderr | 2 +- ...ssue-52126-assign-op-invariance.nll.stderr | 2 +- src/test/ui/nll/borrowed-local-error.stderr | 2 +- .../ui/nll/borrowed-universal-error-2.stderr | 2 +- src/test/ui/nll/capture-ref-in-struct.stderr | 2 +- .../escape-argument.stderr | 2 +- .../escape-upvar-nested.stderr | 2 +- .../escape-upvar-ref.stderr | 2 +- ...er-to-static-comparing-against-free.stderr | 2 +- src/test/ui/nll/issue-31567.stderr | 2 +- src/test/ui/nll/issue-47470.stderr | 2 +- ...borrow-params-issue-29793-small.nll.stderr | 40 +++---- src/test/ui/regions-nested-fns-2.nll.stderr | 2 +- .../span/destructor-restrictions.nll.stderr | 2 +- .../ui/span/dropck-object-cycle.nll.stderr | 2 +- .../span/dropck_arr_cycle_checked.nll.stderr | 6 +- .../dropck_direct_cycle_with_drop.nll.stderr | 4 +- .../ui/span/dropck_misc_variants.nll.stderr | 4 +- .../span/dropck_vec_cycle_checked.nll.stderr | 6 +- src/test/ui/span/issue-11925.nll.stderr | 2 +- ...locals-die-before-temps-of-body.nll.stderr | 4 +- ...opck-child-has-items-via-parent.nll.stderr | 2 +- ...ue-24805-dropck-trait-has-items.nll.stderr | 6 +- .../issue-24895-copy-clone-dropck.nll.stderr | 2 +- src/test/ui/span/issue-25199.nll.stderr | 2 +- src/test/ui/span/issue-26656.nll.stderr | 2 +- src/test/ui/span/issue-29106.nll.stderr | 4 +- src/test/ui/span/issue-36537.nll.stderr | 2 +- src/test/ui/span/issue-40157.nll.stderr | 2 +- .../ui/span/issue28498-reject-ex1.nll.stderr | 2 +- ...ssue28498-reject-lifetime-param.nll.stderr | 2 +- .../issue28498-reject-passed-to-fn.nll.stderr | 2 +- .../issue28498-reject-trait-bound.nll.stderr | 2 +- .../span/mut-ptr-cant-outlive-ref.nll.stderr | 2 +- src/test/ui/span/range-2.nll.stderr | 4 +- ...ionck-unboxed-closure-lifetimes.nll.stderr | 2 +- ...ons-close-over-type-parameter-2.nll.stderr | 2 +- ...egions-escape-loop-via-variable.nll.stderr | 2 +- .../regions-escape-loop-via-vec.nll.stderr | 2 +- ...-infer-borrow-scope-within-loop.nll.stderr | 2 +- ...d-is-not-static-ensures-scoping.nll.stderr | 4 +- .../send-is-not-static-std-sync-2.nll.stderr | 6 +- .../send-is-not-static-std-sync.nll.stderr | 6 +- ...-must-not-hide-type-from-dropck.nll.stderr | 4 +- .../vec_refs_data_with_early_death.nll.stderr | 4 +- .../wf-method-late-bound-regions.nll.stderr | 2 +- 66 files changed, 135 insertions(+), 198 deletions(-) create mode 100644 src/test/ui/issue-13497-2.nll.stderr diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 9e822d28056de..e3534b0fc7f6b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -14,7 +14,7 @@ use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::mir::VarBindingForm; -use rustc::ty::{self, RegionKind}; +use rustc::ty; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; use syntax_pos::Span; @@ -427,34 +427,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((root_place.clone(), borrow_span)); - match (borrow.region, &self.describe_place(&borrow.borrowed_place)) { - (RegionKind::ReScope(_), Some(name)) => { - self.report_scoped_local_value_does_not_live_long_enough( - context, - name, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - ); - } - (RegionKind::ReScope(_), None) => { - self.report_scoped_temporary_value_does_not_live_long_enough( - context, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - ); - } - (RegionKind::ReEarlyBound(_), Some(name)) - | (RegionKind::ReFree(_), Some(name)) - | (RegionKind::ReStatic, Some(name)) - | (RegionKind::ReEmpty, Some(name)) - | (RegionKind::ReVar(_), Some(name)) => { - self.report_unscoped_local_value_does_not_live_long_enough( + match &self.describe_place(&borrow.borrowed_place) { + Some(name) => { + self.report_local_value_does_not_live_long_enough( context, name, &scope_tree, @@ -465,12 +440,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { kind.map(|k| (k, place_span.0)), ); } - (RegionKind::ReEarlyBound(_), None) - | (RegionKind::ReFree(_), None) - | (RegionKind::ReStatic, None) - | (RegionKind::ReEmpty, None) - | (RegionKind::ReVar(_), None) => { - self.report_unscoped_temporary_value_does_not_live_long_enough( + None => { + self.report_temporary_value_does_not_live_long_enough( context, &scope_tree, &borrow, @@ -479,65 +450,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span, ); } - (RegionKind::ReLateBound(_, _), _) - | (RegionKind::ReSkolemized(_, _), _) - | (RegionKind::ReClosureBound(_), _) - | (RegionKind::ReCanonical(_), _) - | (RegionKind::ReErased, _) => { - span_bug!( - drop_span, - "region {:?} does not make sense in this context", - borrow.region - ); - } } } - fn report_scoped_local_value_does_not_live_long_enough( - &mut self, - context: Context, - name: &String, - _scope_tree: &Lrc, - borrow: &BorrowData<'tcx>, - drop_span: Span, - borrow_span: Span, - _proper_span: Span, - ) { - let tcx = self.tcx; - let mut err = - tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir); - err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label( - drop_span, - format!("`{}` dropped here while still borrowed", name), - ); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); - } - - fn report_scoped_temporary_value_does_not_live_long_enough( - &mut self, - context: Context, - _scope_tree: &Lrc, - borrow: &BorrowData<'tcx>, - drop_span: Span, - _borrow_span: Span, - proper_span: Span, - ) { - let tcx = self.tcx; - let mut err = - tcx.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir); - err.span_label(proper_span, "temporary value does not live long enough"); - err.span_label( - drop_span, - "temporary value dropped here while still borrowed", - ); - err.note("consider using a `let` binding to increase its lifetime"); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); - } - - fn report_unscoped_local_value_does_not_live_long_enough( + fn report_local_value_does_not_live_long_enough( &mut self, context: Context, name: &String, @@ -549,7 +465,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { kind_place: Option<(WriteKind, &Place<'tcx>)>, ) { debug!( - "report_unscoped_local_value_does_not_live_long_enough(\ + "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ )", context, name, scope_tree, borrow, drop_span, borrow_span @@ -559,13 +475,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut err = tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir); err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label(drop_span, "borrowed value only lives until here"); + err.span_label( + drop_span, + format!("`{}` dropped here while still borrowed", name), + ); self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err); err.buffer(&mut self.errors_buffer); } - fn report_unscoped_temporary_value_does_not_live_long_enough( + fn report_temporary_value_does_not_live_long_enough( &mut self, context: Context, scope_tree: &Lrc, @@ -575,7 +494,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span: Span, ) { debug!( - "report_unscoped_temporary_value_does_not_live_long_enough(\ + "report_temporary_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ )", context, scope_tree, borrow, drop_span, proper_span diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr index b931bc45b77ee..b15f156b7c201 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr @@ -5,7 +5,7 @@ LL | spawn(|| books.push(4)); | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough LL | //~^ ERROR E0373 LL | } - | - borrowed value only lives until here + | - `books` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr index 5448049a8017d..8c643973af67b 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr @@ -5,7 +5,7 @@ LL | Box::new(|| books.push(4)) | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough LL | //~^ ERROR E0373 LL | } - | - borrowed value only lives until here + | - `books` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 19:8... --> $DIR/borrowck-escaping-closure-error-2.rs:19:8 diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr index 730ace7858bd1..b59f628c746bb 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr @@ -7,7 +7,7 @@ LL | dt = Dt("dt", &c_shortest); LL | } | - | | - | borrowed value only lives until here + | `c_shortest` dropped here while still borrowed | borrow later used here, when `dt` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr index f0df7109ba4b6..ad460fcf55e57 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr @@ -7,7 +7,7 @@ LL | dt = Dt("dt", &c_shortest); LL | } | - | | - | borrowed value only lives until here + | `c_shortest` dropped here while still borrowed | borrow later used here, when `dt` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/dropck/dropck-eyepatch.nll.stderr b/src/test/ui/dropck/dropck-eyepatch.nll.stderr index 2072bc6a756c9..864fb2f2ea6f4 100644 --- a/src/test/ui/dropck/dropck-eyepatch.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.nll.stderr @@ -7,7 +7,7 @@ LL | dt = Dt("dt", &c_shortest); LL | } | - | | - | borrowed value only lives until here + | `c_shortest` dropped here while still borrowed | borrow later used here, when `dt` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/error-codes/E0597.nll.stderr b/src/test/ui/error-codes/E0597.nll.stderr index 172db9ced82f9..31ba24b0004fb 100644 --- a/src/test/ui/error-codes/E0597.nll.stderr +++ b/src/test/ui/error-codes/E0597.nll.stderr @@ -7,7 +7,7 @@ LL | //~^ `y` does not live long enough [E0597] LL | } | - | | - | borrowed value only lives until here + | `y` dropped here while still borrowed | borrow later used here, when `x` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index 015538b16f971..e03d72a02f0aa 100644 --- a/src/test/ui/generator/borrowing.nll.stderr +++ b/src/test/ui/generator/borrowing.nll.stderr @@ -5,7 +5,7 @@ LL | unsafe { (|| yield &a).resume() } | ^^^^^^^^^^^^^ borrowed value does not live long enough LL | //~^ ERROR: `a` does not live long enough LL | }; - | - borrowed value only lives until here + | - `a` dropped here while still borrowed error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:24:9 @@ -16,7 +16,7 @@ LL | | //~^ ERROR: `a` does not live long enough LL | | } | |_________^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `a` dropped here while still borrowed LL | } | - borrow later used here, when `_b` is dropped diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr index 01a53cdd6dd4a..ef7e64ffd97ae 100644 --- a/src/test/ui/generator/dropck.nll.stderr +++ b/src/test/ui/generator/dropck.nll.stderr @@ -7,7 +7,7 @@ LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); LL | } | - | | - | borrowed value only lives until here + | `*cell` dropped here while still borrowed | borrow later used here, when `gen` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -26,7 +26,7 @@ LL | | }; LL | } | - | | - | borrowed value only lives until here + | `ref_` dropped here while still borrowed | borrow later used here, when `gen` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr index 08839c23c3762..56d853c2966c5 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr @@ -5,7 +5,7 @@ LL | a = &b; | ^^ borrowed value does not live long enough LL | //~^ ERROR `b` does not live long enough LL | }; - | - borrowed value only lives until here + | - `b` dropped here while still borrowed error: aborting due to previous error diff --git a/src/test/ui/issue-12470.nll.stderr b/src/test/ui/issue-12470.nll.stderr index 09cbfe4f66daa..6eb2765514054 100644 --- a/src/test/ui/issue-12470.nll.stderr +++ b/src/test/ui/issue-12470.nll.stderr @@ -5,7 +5,7 @@ LL | let bb: &B = &*b; //~ ERROR does not live long enough | ^^^ borrowed value does not live long enough LL | make_a(bb) LL | } - | - borrowed value only lives until here + | - `*b` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 36:16... --> $DIR/issue-12470.rs:36:16 diff --git a/src/test/ui/issue-13497-2.nll.stderr b/src/test/ui/issue-13497-2.nll.stderr new file mode 100644 index 0000000000000..5c592f6f37523 --- /dev/null +++ b/src/test/ui/issue-13497-2.nll.stderr @@ -0,0 +1,18 @@ +error[E0597]: `rawLines` does not live long enough + --> $DIR/issue-13497-2.rs:13:5 + | +LL | rawLines //~ ERROR `rawLines` does not live long enough + | ^^^^^^^^ borrowed value does not live long enough +LL | .iter().map(|l| l.trim()).collect() +LL | } + | - `rawLines` dropped here while still borrowed + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 11:24... + --> $DIR/issue-13497-2.rs:11:24 + | +LL | fn read_lines_borrowed<'a>() -> Vec<&'a str> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-17954.ast.nll.stderr b/src/test/ui/issue-17954.ast.nll.stderr index f731e8eeae67f..5cab7ca9e7a3f 100644 --- a/src/test/ui/issue-17954.ast.nll.stderr +++ b/src/test/ui/issue-17954.ast.nll.stderr @@ -5,7 +5,7 @@ LL | let a = &FOO; | ^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `FOO` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issue-17954.mir.stderr b/src/test/ui/issue-17954.mir.stderr index f731e8eeae67f..5cab7ca9e7a3f 100644 --- a/src/test/ui/issue-17954.mir.stderr +++ b/src/test/ui/issue-17954.mir.stderr @@ -5,7 +5,7 @@ LL | let a = &FOO; | ^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `FOO` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issue-17954.rs b/src/test/ui/issue-17954.rs index 4211057610bc7..b5e550e5be1c9 100644 --- a/src/test/ui/issue-17954.rs +++ b/src/test/ui/issue-17954.rs @@ -29,5 +29,5 @@ fn main() { println!("{}", a); }); } -//[mir]~^ borrowed value only lives until here +//[mir]~^ `FOO` dropped here while still borrowed //[ast]~^^ temporary value only lives until here diff --git a/src/test/ui/issue-18118.nll.stderr b/src/test/ui/issue-18118.nll.stderr index 7acab8426f62b..860359b5937cc 100644 --- a/src/test/ui/issue-18118.nll.stderr +++ b/src/test/ui/issue-18118.nll.stderr @@ -57,7 +57,7 @@ LL | &p //~ ERROR `p` does not live long enough | ^^ borrowed value does not live long enough LL | //~^ ERROR let bindings in constants are unstable LL | }; - | - borrowed value only lives until here + | - `p` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issue-30438-c.nll.stderr b/src/test/ui/issue-30438-c.nll.stderr index 0bfac131e224d..28e63b2d36b11 100644 --- a/src/test/ui/issue-30438-c.nll.stderr +++ b/src/test/ui/issue-30438-c.nll.stderr @@ -5,7 +5,7 @@ LL | &x | ^^ borrowed value does not live long enough LL | //~^ ERROR: `x` does not live long enough LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'y as defined on the function body at 17:10... --> $DIR/issue-30438-c.rs:17:10 diff --git a/src/test/ui/issue-4335.nll.stderr b/src/test/ui/issue-4335.nll.stderr index eacd8b5e58047..40d7838a80325 100644 --- a/src/test/ui/issue-4335.nll.stderr +++ b/src/test/ui/issue-4335.nll.stderr @@ -11,7 +11,7 @@ LL | id(Box::new(|| *v)) | ^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `v` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'r as defined on the function body at 15:6... --> $DIR/issue-4335.rs:15:6 diff --git a/src/test/ui/issue-46036.stderr b/src/test/ui/issue-46036.stderr index e0df49f582338..463abaede88f9 100644 --- a/src/test/ui/issue-46036.stderr +++ b/src/test/ui/issue-46036.stderr @@ -5,7 +5,7 @@ LL | let foo = Foo { x: &a }; //~ ERROR E0597 | ^^ borrowed value does not live long enough LL | loop { } LL | } - | - borrowed value only lives until here + | - `a` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issue-46471-1.stderr b/src/test/ui/issue-46471-1.stderr index 0108056bc7278..7d12827dda5d2 100644 --- a/src/test/ui/issue-46471-1.stderr +++ b/src/test/ui/issue-46471-1.stderr @@ -20,7 +20,7 @@ LL | | &mut z LL | | }; | | - | | | - | |_____borrowed value only lives until here + | |_____`z` dropped here while still borrowed | borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-46471.stderr b/src/test/ui/issue-46471.stderr index ac974afa13a1e..560c341b4df05 100644 --- a/src/test/ui/issue-46471.stderr +++ b/src/test/ui/issue-46471.stderr @@ -16,7 +16,7 @@ LL | &x | ^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issue-52126-assign-op-invariance.nll.stderr b/src/test/ui/issue-52126-assign-op-invariance.nll.stderr index dcca491a87bb4..ccbb852b14574 100644 --- a/src/test/ui/issue-52126-assign-op-invariance.nll.stderr +++ b/src/test/ui/issue-52126-assign-op-invariance.nll.stderr @@ -8,7 +8,7 @@ LL | println!("accumulator before add_assign {:?}", acc.map); | ------- borrow later used here ... LL | } - | - borrowed value only lives until here + | - `line` dropped here while still borrowed error: aborting due to previous error diff --git a/src/test/ui/nll/borrowed-local-error.stderr b/src/test/ui/nll/borrowed-local-error.stderr index 901b1ca271a5f..28353a8bc2be7 100644 --- a/src/test/ui/nll/borrowed-local-error.stderr +++ b/src/test/ui/nll/borrowed-local-error.stderr @@ -10,7 +10,7 @@ LL | | //~^ ERROR `v` does not live long enough [E0597] LL | | }); | |_____-- borrow later used here | | - | borrowed value only lives until here + | `v` dropped here while still borrowed error: aborting due to previous error diff --git a/src/test/ui/nll/borrowed-universal-error-2.stderr b/src/test/ui/nll/borrowed-universal-error-2.stderr index ea7d819938443..867e473af2c0e 100644 --- a/src/test/ui/nll/borrowed-universal-error-2.stderr +++ b/src/test/ui/nll/borrowed-universal-error-2.stderr @@ -5,7 +5,7 @@ LL | &v | ^^ borrowed value does not live long enough LL | //~^ ERROR `v` does not live long enough [E0597] LL | } - | - borrowed value only lives until here + | - `v` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 14:8... --> $DIR/borrowed-universal-error-2.rs:14:8 diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr index 81946de612afe..12a9adf6e0ba6 100644 --- a/src/test/ui/nll/capture-ref-in-struct.stderr +++ b/src/test/ui/nll/capture-ref-in-struct.stderr @@ -5,7 +5,7 @@ LL | y: &y, | ^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed LL | LL | deref(p); | - borrow later used here diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index dba27f16e8cac..a830768b36e1c 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -30,7 +30,7 @@ LL | closure(&mut p, &y); | ^^ borrowed value does not live long enough LL | //~^ ERROR `y` does not live long enough [E0597] LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed LL | LL | deref(p); | - borrow later used here diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index a7fb9d90a2183..bf12800e58d71 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -57,7 +57,7 @@ LL | | }; | |_________^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed LL | LL | deref(p); | - borrow later used here diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index fd6b7a2e68d33..4b0dad3bda022 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -34,7 +34,7 @@ LL | let mut closure = || p = &y; | ^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed LL | LL | deref(p); | - borrow later used here diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index d51ba8201aaa6..0295747d529f1 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -82,7 +82,7 @@ LL | let cell = Cell::new(&a); | ^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `a` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/nll/issue-31567.stderr b/src/test/ui/nll/issue-31567.stderr index 065de6ea600b4..532bc493e7dbc 100644 --- a/src/test/ui/nll/issue-31567.stderr +++ b/src/test/ui/nll/issue-31567.stderr @@ -5,7 +5,7 @@ LL | let s_inner: &'a S = &*v.0; //~ ERROR `*v.0` does not live long enough | ^^^^^ borrowed value does not live long enough LL | &s_inner.0 LL | } - | - borrowed value only lives until here + | - `*v.0` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 21:17... --> $DIR/issue-31567.rs:21:17 diff --git a/src/test/ui/nll/issue-47470.stderr b/src/test/ui/nll/issue-47470.stderr index a89e186540a47..e73df61a30371 100644 --- a/src/test/ui/nll/issue-47470.stderr +++ b/src/test/ui/nll/issue-47470.stderr @@ -4,7 +4,7 @@ error[E0597]: `local` does not live long enough LL | &local //~ ERROR `local` does not live long enough | ^^^^^^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `local` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the impl at 23:6... --> $DIR/issue-47470.rs:23:6 diff --git a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr index 443af08e1cc7c..ae7193ef4fa79 100644 --- a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr +++ b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr @@ -5,7 +5,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough --> $DIR/region-borrow-params-issue-29793-small.rs:19:17 @@ -14,7 +14,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 @@ -23,7 +23,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 @@ -32,7 +32,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough --> $DIR/region-borrow-params-issue-29793-small.rs:65:17 @@ -41,7 +41,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:10... --> $DIR/region-borrow-params-issue-29793-small.rs:64:10 @@ -56,7 +56,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:10... --> $DIR/region-borrow-params-issue-29793-small.rs:64:10 @@ -71,7 +71,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 75:10... --> $DIR/region-borrow-params-issue-29793-small.rs:75:10 @@ -86,7 +86,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the function body at 75:10... --> $DIR/region-borrow-params-issue-29793-small.rs:75:10 @@ -101,7 +101,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 99:14... --> $DIR/region-borrow-params-issue-29793-small.rs:99:14 @@ -116,7 +116,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 99:14... --> $DIR/region-borrow-params-issue-29793-small.rs:99:14 @@ -131,7 +131,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 113:14... --> $DIR/region-borrow-params-issue-29793-small.rs:113:14 @@ -146,7 +146,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 113:14... --> $DIR/region-borrow-params-issue-29793-small.rs:113:14 @@ -161,7 +161,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 141:14... --> $DIR/region-borrow-params-issue-29793-small.rs:141:14 @@ -176,7 +176,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 141:14... --> $DIR/region-borrow-params-issue-29793-small.rs:141:14 @@ -191,7 +191,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 156:14... --> $DIR/region-borrow-params-issue-29793-small.rs:156:14 @@ -206,7 +206,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 156:14... --> $DIR/region-borrow-params-issue-29793-small.rs:156:14 @@ -221,7 +221,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 184:14... --> $DIR/region-borrow-params-issue-29793-small.rs:184:14 @@ -236,7 +236,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 184:14... --> $DIR/region-borrow-params-issue-29793-small.rs:184:14 @@ -251,7 +251,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 198:14... --> $DIR/region-borrow-params-issue-29793-small.rs:198:14 @@ -266,7 +266,7 @@ LL | let f = |t: bool| if t { x } else { y }; // (separate errors fo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | note: borrowed value must be valid for the lifetime 'a as defined on the method body at 198:14... --> $DIR/region-borrow-params-issue-29793-small.rs:198:14 diff --git a/src/test/ui/regions-nested-fns-2.nll.stderr b/src/test/ui/regions-nested-fns-2.nll.stderr index 2c973f9bdea5e..13e34d85210a7 100644 --- a/src/test/ui/regions-nested-fns-2.nll.stderr +++ b/src/test/ui/regions-nested-fns-2.nll.stderr @@ -7,7 +7,7 @@ LL | | if false { &y } else { z } LL | | }); | |_________^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr index 8be4cf445da3f..22f2f13f1f7cf 100644 --- a/src/test/ui/span/destructor-restrictions.nll.stderr +++ b/src/test/ui/span/destructor-restrictions.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `*a` does not live long enough LL | *a.borrow() + 1 | ^ borrowed value does not live long enough LL | }; //~^ ERROR `*a` does not live long enough - | - borrowed value only lives until here + | - `*a` dropped here while still borrowed error: aborting due to previous error diff --git a/src/test/ui/span/dropck-object-cycle.nll.stderr b/src/test/ui/span/dropck-object-cycle.nll.stderr index b268f6e3ab014..225ed0f9cc832 100644 --- a/src/test/ui/span/dropck-object-cycle.nll.stderr +++ b/src/test/ui/span/dropck-object-cycle.nll.stderr @@ -7,7 +7,7 @@ LL | assert_eq!(object_invoke1(&*m), (4,5)); LL | } | - | | - | borrowed value only lives until here + | `*m` dropped here while still borrowed | borrow later used here, when `m` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr index cbb9d0429c616..6c0373ce1570a 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr @@ -7,7 +7,7 @@ LL | b1.a[1].v.set(Some(&b3)); LL | } | - | | - | borrowed value only lives until here + | `b3` dropped here while still borrowed | borrow later used here, when `b1` is dropped error[E0597]: `b2` does not live long enough @@ -19,7 +19,7 @@ LL | b1.a[0].v.set(Some(&b2)); LL | } | - | | - | borrowed value only lives until here + | `b2` dropped here while still borrowed | borrow later used here, when `b1` is dropped error[E0597]: `b1` does not live long enough @@ -31,7 +31,7 @@ LL | b3.a[0].v.set(Some(&b1)); LL | } | - | | - | borrowed value only lives until here + | `b1` dropped here while still borrowed | borrow later used here, when `b1` is dropped error: aborting due to 3 previous errors diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr index 37fffe886e309..2884b1818baa9 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr @@ -7,7 +7,7 @@ LL | d1.p.set(Some(&d2)); LL | } | - | | - | borrowed value only lives until here + | `d2` dropped here while still borrowed | borrow later used here, when `d1` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -21,7 +21,7 @@ LL | //~^ ERROR `d1` does not live long enough LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `d1` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/dropck_misc_variants.nll.stderr b/src/test/ui/span/dropck_misc_variants.nll.stderr index 0eb84e4a7d0b2..27a52360bb701 100644 --- a/src/test/ui/span/dropck_misc_variants.nll.stderr +++ b/src/test/ui/span/dropck_misc_variants.nll.stderr @@ -6,7 +6,7 @@ LL | _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); LL | } | - | | - | borrowed value only lives until here + | `bomb` dropped here while still borrowed | borrow later used here, when `_w` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -20,7 +20,7 @@ LL | let u = NoisyDrop(&v); LL | } | - | | - | borrowed value only lives until here + | `v` dropped here while still borrowed | borrow later used here, when `_w` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr index 13bd1f5419821..c0950e7929678 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr @@ -7,7 +7,7 @@ LL | c1.v[1].v.set(Some(&c3)); LL | } | - | | - | borrowed value only lives until here + | `c3` dropped here while still borrowed | borrow later used here, when `c1` is dropped error[E0597]: `c2` does not live long enough @@ -19,7 +19,7 @@ LL | c1.v[0].v.set(Some(&c2)); LL | } | - | | - | borrowed value only lives until here + | `c2` dropped here while still borrowed | borrow later used here, when `c1` is dropped error[E0597]: `c1` does not live long enough @@ -31,7 +31,7 @@ LL | c3.v[0].v.set(Some(&c1)); LL | } | - | | - | borrowed value only lives until here + | `c1` dropped here while still borrowed | borrow later used here, when `c1` is dropped error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-11925.nll.stderr b/src/test/ui/span/issue-11925.nll.stderr index 68a4d5d25f424..e841e6c635bc3 100644 --- a/src/test/ui/span/issue-11925.nll.stderr +++ b/src/test/ui/span/issue-11925.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `x` does not live long enough LL | let f = to_fn_once(move|| &x); //~ ERROR does not live long enough | ^- | || - | |borrowed value only lives until here + | |`x` dropped here while still borrowed | borrowed value does not live long enough error: aborting due to previous error diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr index ec2f5a25631c4..fe0187f386378 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `y` does not live long enough LL | y.borrow().clone() | ^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `y` dropped here while still borrowed error[E0597]: `y` does not live long enough --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9 @@ -12,7 +12,7 @@ error[E0597]: `y` does not live long enough LL | y.borrow().clone() | ^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr index ec1df8aeca15a..b9834a3d4379e 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr @@ -7,7 +7,7 @@ LL | _d = D_Child(&d1); LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `_d` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr index 288c196b27b2d..cd3d658aa8726 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr @@ -6,7 +6,7 @@ LL | _d = D_HasSelfMethod(&d1); LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `_d` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -19,7 +19,7 @@ LL | _d = D_HasMethodWithSelfArg(&d1); LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `_d` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -32,7 +32,7 @@ LL | _d = D_HasType(&d1); LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `_d` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr index c89e68bcd0ae0..54c6ac43f347c 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr @@ -6,7 +6,7 @@ LL | d2 = D(S(&d1, "inner"), "d2"); LL | } | - | | - | borrowed value only lives until here + | `d1` dropped here while still borrowed | borrow later used here, when `d2` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue-25199.nll.stderr b/src/test/ui/span/issue-25199.nll.stderr index 770fed8cd9cc9..a81b591d288eb 100644 --- a/src/test/ui/span/issue-25199.nll.stderr +++ b/src/test/ui/span/issue-25199.nll.stderr @@ -7,7 +7,7 @@ LL | let test = Test{test: &container}; LL | } | - | | - | borrowed value only lives until here + | `container` dropped here while still borrowed | borrow later used here, when `container` is dropped error: aborting due to previous error diff --git a/src/test/ui/span/issue-26656.nll.stderr b/src/test/ui/span/issue-26656.nll.stderr index bea6dc6b3f6a0..b6c2882812088 100644 --- a/src/test/ui/span/issue-26656.nll.stderr +++ b/src/test/ui/span/issue-26656.nll.stderr @@ -6,7 +6,7 @@ LL | zook.button = B::BigRedButton(&ticking); LL | } | - | | - | borrowed value only lives until here + | `ticking` dropped here while still borrowed | borrow later used here, when `zook` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue-29106.nll.stderr b/src/test/ui/span/issue-29106.nll.stderr index 80a7421f4bd20..2cf408d097b83 100644 --- a/src/test/ui/span/issue-29106.nll.stderr +++ b/src/test/ui/span/issue-29106.nll.stderr @@ -6,7 +6,7 @@ LL | y = Arc::new(Foo(&x)); LL | } | - | | - | borrowed value only lives until here + | `x` dropped here while still borrowed | borrow later used here, when `y` is dropped error[E0597]: `x` does not live long enough @@ -17,7 +17,7 @@ LL | y = Rc::new(Foo(&x)); LL | } | - | | - | borrowed value only lives until here + | `x` dropped here while still borrowed | borrow later used here, when `y` is dropped error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-36537.nll.stderr b/src/test/ui/span/issue-36537.nll.stderr index a3b8a3e766bbf..0d13c9844b331 100644 --- a/src/test/ui/span/issue-36537.nll.stderr +++ b/src/test/ui/span/issue-36537.nll.stderr @@ -5,7 +5,7 @@ LL | p = &a; | ^^^^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `a` dropped here while still borrowed LL | p.use_ref(); | - borrow later used here diff --git a/src/test/ui/span/issue-40157.nll.stderr b/src/test/ui/span/issue-40157.nll.stderr index d9608f3a89630..def4a308bc75e 100644 --- a/src/test/ui/span/issue-40157.nll.stderr +++ b/src/test/ui/span/issue-40157.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `foo` does not live long enough LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} | ------------------------------^^^-------------------- | | | | - | | | borrowed value only lives until here + | | | `foo` dropped here while still borrowed | | borrowed value does not live long enough | borrow later used here diff --git a/src/test/ui/span/issue28498-reject-ex1.nll.stderr b/src/test/ui/span/issue28498-reject-ex1.nll.stderr index 3ed13f2653ccd..27eb4a3afed6d 100644 --- a/src/test/ui/span/issue28498-reject-ex1.nll.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.nll.stderr @@ -7,7 +7,7 @@ LL | foo.data[0].1.set(Some(&foo.data[1])); LL | } | - | | - | borrowed value only lives until here + | `foo.data` dropped here while still borrowed | borrow later used here, when `foo` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr index ce9e75b448318..72acc54bffb32 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr @@ -7,7 +7,7 @@ LL | foo1 = Foo(1, &first_dropped); LL | } | - | | - | borrowed value only lives until here + | `first_dropped` dropped here while still borrowed | borrow later used here, when `foo1` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr index fcdc1c3f9452d..a39050a519911 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr @@ -7,7 +7,7 @@ LL | foo1 = Foo(1, &first_dropped, Box::new(callback)); LL | } | - | | - | borrowed value only lives until here + | `first_dropped` dropped here while still borrowed | borrow later used here, when `foo1` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr index 6300bb3eacd64..fcffea25702b9 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr @@ -7,7 +7,7 @@ LL | foo1 = Foo(1, &first_dropped); LL | } | - | | - | borrowed value only lives until here + | `first_dropped` dropped here while still borrowed | borrow later used here, when `foo1` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr index a99ff9e272619..e5139dca351a6 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `b` does not live long enough LL | p = &*b; | ^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `b` dropped here while still borrowed LL | //~^^ ERROR `b` does not live long enough LL | p.use_ref(); | - borrow later used here diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr index aff1fededbb3c..049618fe4744b 100644 --- a/src/test/ui/span/range-2.nll.stderr +++ b/src/test/ui/span/range-2.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `b` does not live long enough LL | &a..&b | ^^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `b` dropped here while still borrowed ... LL | r.use_ref(); | - borrow later used here @@ -15,7 +15,7 @@ error[E0597]: `a` does not live long enough LL | &a..&b | ^^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `a` dropped here while still borrowed ... LL | r.use_ref(); | - borrow later used here diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr index 71e02af1f845f..4881259ff23ab 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr @@ -5,7 +5,7 @@ LL | let c_ref = &c; | ^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `c` dropped here while still borrowed LL | f.use_mut(); | - borrow later used here diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr index c8a1f80120148..f522521b400e4 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr @@ -10,7 +10,7 @@ LL | | repeater3(tmp1) LL | | }; | | - | | | - | |_____borrowed value only lives until here + | |_____`tmp0` dropped here while still borrowed | borrow later used here error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr index 7fd2bfbdd8f97..08ca100c247dc 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr @@ -6,7 +6,7 @@ LL | let x = 1 + *p; LL | p = &x; | ^^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `x` dropped here while still borrowed error: aborting due to previous error diff --git a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr index c7aa40f18e36a..33fca7fa703b0 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr @@ -41,7 +41,7 @@ LL | _y.push(&mut z); | borrow later used here ... LL | } - | - borrowed value only lives until here + | - `z` dropped here while still borrowed error: aborting due to 4 previous errors diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr index 034f80c7d54af..5fa25ae8506e6 100644 --- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr +++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr @@ -5,7 +5,7 @@ LL | y = borrow(&*x); | ^^^ borrowed value does not live long enough ... LL | } - | - borrowed value only lives until here + | - `*x` dropped here while still borrowed LL | assert!(*y != 0); | -- borrow later used here diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr index 710b19e193264..7f7217b8004a6 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr @@ -8,7 +8,7 @@ LL | | //~^ ERROR `y` does not live long enough LL | | }) | |_________^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `y` dropped here while still borrowed LL | LL | bad.join(); | --- borrow later used here @@ -20,7 +20,7 @@ LL | let y = &x; | ^^ borrowed value does not live long enough ... LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed LL | LL | bad.join(); | --- borrow later used here diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr index e794f8c27e854..58dad753ac4a1 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `x` does not live long enough LL | Mutex::new(&x) | ^^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed ... LL | let _dangling = *lock.lock().unwrap(); | ---- borrow later used here @@ -15,7 +15,7 @@ error[E0597]: `x` does not live long enough LL | RwLock::new(&x) | ^^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed LL | //~^^ ERROR `x` does not live long enough LL | let _dangling = *lock.read().unwrap(); | ---- borrow later used here @@ -30,7 +30,7 @@ LL | let _ = tx.send(&x); | ^^ borrowed value does not live long enough LL | (tx, rx) LL | }; - | - borrowed value only lives until here + | - `x` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr index 6ebbf3e1ec4d2..878ae36386371 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr @@ -15,7 +15,7 @@ error[E0597]: `z` does not live long enough LL | *lock.lock().unwrap() = &z; | ^^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `z` dropped here while still borrowed LL | //~^^ ERROR `z` does not live long enough LL | lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) | ---- borrow later used here @@ -37,7 +37,7 @@ error[E0597]: `z` does not live long enough LL | *lock.write().unwrap() = &z; | ^^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `z` dropped here while still borrowed LL | //~^^ ERROR `z` does not live long enough LL | lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) | ---- borrow later used here @@ -59,7 +59,7 @@ error[E0597]: `z` does not live long enough LL | tx.send(&z).unwrap(); | ^^ borrowed value does not live long enough LL | } - | - borrowed value only lives until here + | - `z` dropped here while still borrowed ... LL | } | - borrow later used here, when `tx` is dropped diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr index 100b4c1292f44..ee51304800d32 100644 --- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr +++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr @@ -7,7 +7,7 @@ LL | c1.v[0].v.set(Some(&c2)); LL | } | - | | - | borrowed value only lives until here + | `c2` dropped here while still borrowed | borrow later used here, when `c1` is dropped error[E0597]: `c1` does not live long enough @@ -19,7 +19,7 @@ LL | //~^ ERROR `c1` does not live long enough LL | } | - | | - | borrowed value only lives until here + | `c1` dropped here while still borrowed | borrow later used here, when `c1` is dropped error: aborting due to 2 previous errors diff --git a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr index 9d89fac08ffe2..73256b4fb17c9 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr @@ -7,7 +7,7 @@ LL | v.push(&y); LL | } | - | | - | borrowed value only lives until here + | `y` dropped here while still borrowed | borrow later used here, when `v` is dropped | = note: values in a scope are dropped in the opposite order they are defined @@ -21,7 +21,7 @@ LL | v.push(&x); LL | } | - | | - | borrowed value only lives until here + | `x` dropped here while still borrowed | borrow later used here, when `v` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr index 063ac376b05ec..cc32eaaa97991 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `pointer` does not live long enough LL | f2.xmute(&pointer) | ^^^^^^^^ borrowed value does not live long enough LL | }; - | - borrowed value only lives until here + | - `pointer` dropped here while still borrowed LL | //~^^ ERROR `pointer` does not live long enough LL | println!("{}", dangling); | -------- borrow later used here From 6bcf8777fe632fb2c506e31d12fbfe20712ecfe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jul 2018 15:09:00 -0700 Subject: [PATCH 05/43] Point only at invalid positional arguments --- src/libsyntax_ext/format.rs | 138 ++++++++++++++++++-------------- src/test/ui/ifmt-bad-arg.stderr | 16 ++-- 2 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 215e4f5a83523..a320b52fb7bd9 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -14,18 +14,18 @@ use self::Position::*; use fmt_macros as parse; use syntax::ast; -use syntax::ext::base::*; use syntax::ext::base; +use syntax::ext::base::*; use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::Symbol; -use syntax_pos::{Span, MultiSpan, DUMMY_SP}; use syntax::tokenstream; +use syntax_pos::{MultiSpan, Span, DUMMY_SP}; -use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry; +use std::collections::{HashMap, HashSet}; #[derive(PartialEq)] enum ArgumentType { @@ -111,9 +111,11 @@ struct Context<'a, 'b: 'a> { /// still existed in this phase of processing. /// Used only for `all_pieces_simple` tracking in `build_piece`. curarg: usize, + /// Current piece being evaluated, used for error reporting. curpiece: usize, - /// Keep track of invalid references to positional arguments - invalid_refs: Vec, + /// Keep track of invalid references to positional arguments. + invalid_refs: Vec<(usize, usize)>, + /// Spans of all the formatting arguments, in order. arg_spans: Vec, } @@ -157,15 +159,20 @@ fn parse_args(ecx: &mut ExtCtxt, i } _ if named => { - ecx.span_err(p.span, - "expected ident, positional arguments \ - cannot follow named arguments"); + ecx.span_err( + p.span, + "expected ident, positional arguments cannot follow named arguments", + ); return None; } _ => { - ecx.span_err(p.span, - &format!("expected ident for named argument, found `{}`", - p.this_token_to_string())); + ecx.span_err( + p.span, + &format!( + "expected ident for named argument, found `{}`", + p.this_token_to_string() + ), + ); return None; } }; @@ -267,34 +274,47 @@ impl<'a, 'b> Context<'a, 'b> { /// errors for the case where all arguments are positional and for when /// there are named arguments or numbered positional arguments in the /// format string. - fn report_invalid_references(&self, numbered_position_args: bool, arg_places: &[(usize, usize)]) { + fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sps = arg_places.iter() - .map(|&(start, end)| self.fmtsp.from_inner_byte_pos(start, end)) - .collect::>(); - let sp = MultiSpan::from_spans(sps); - let mut refs: Vec<_> = self.invalid_refs + let sp = MultiSpan::from_spans(self.arg_spans.clone()); + let mut refs: Vec<_> = self + .invalid_refs .iter() - .map(|r| r.to_string()) + .map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos))) .collect(); if self.names.is_empty() && !numbered_position_args { - e = self.ecx.mut_span_err(sp, - &format!("{} positional argument{} in format string, but {}", + e = self.ecx.mut_span_err( + sp, + &format!( + "{} positional argument{} in format string, but {}", self.pieces.len(), if self.pieces.len() > 1 { "s" } else { "" }, - self.describe_num_args())); + self.describe_num_args() + ), + ); } else { - let arg_list = match refs.len() { + let (arg_list, sp) = match refs.len() { 1 => { - let reg = refs.pop().unwrap(); - format!("argument {}", reg) - }, + let (reg, pos) = refs.pop().unwrap(); + ( + format!("argument {}", reg), + MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)), + ) + } _ => { + let pos = + MultiSpan::from_spans(refs.iter().map(|(_, p)| *p.unwrap()).collect()); + let mut refs: Vec = refs.iter().map(|(s, _)| s.to_owned()).collect(); let reg = refs.pop().unwrap(); - format!("arguments {head} and {tail}", - tail=reg, - head=refs.join(", ")) + ( + format!( + "arguments {head} and {tail}", + tail = reg, + head = refs.join(", ") + ), + pos, + ) } }; @@ -314,7 +334,7 @@ impl<'a, 'b> Context<'a, 'b> { match arg { Exact(arg) => { if self.args.len() <= arg { - self.invalid_refs.push(arg); + self.invalid_refs.push((arg, self.curpiece)); return; } match ty { @@ -520,33 +540,27 @@ impl<'a, 'b> Context<'a, 'b> { let prec = self.build_count(arg.format.precision); let width = self.build_count(arg.format.width); let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); - let fmt = - self.ecx.expr_struct(sp, + 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)]); + 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, + 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)])) + vec![ + self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos), + self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt), + ], + )) } } } @@ -559,9 +573,9 @@ impl<'a, 'b> Context<'a, 'b> { let mut pats = Vec::new(); let mut heads = Vec::new(); - let names_pos: Vec<_> = (0..self.args.len()).map(|i| { - self.ecx.ident_of(&format!("arg{}", i)).gensym() - }).collect(); + let names_pos: Vec<_> = (0..self.args.len()) + .map(|i| self.ecx.ident_of(&format!("arg{}", i)).gensym()) + .collect(); // First, build up the static array which will become our precompiled // format "string" @@ -705,10 +719,11 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, } } -pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt, +pub fn expand_format_args_nl<'cx>( + ecx: &'cx mut ExtCtxt, mut sp: Span, - tts: &[tokenstream::TokenTree]) - -> Box { + tts: &[tokenstream::TokenTree], +) -> Box { //if !ecx.ecfg.enable_allow_internal_unstable() { // For some reason, the only one that actually works for `println` is the first check @@ -759,7 +774,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let sugg_fmt = match args.len() { 0 => "{}".to_string(), _ => format!("{}{{}}", "{} ".repeat(args.len())), - }; err.span_suggestion( fmt_sp.shrink_to_lo(), @@ -768,7 +782,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, ); err.emit(); return DummyResult::raw_expr(sp); - }, + } }; let mut cx = Context { @@ -862,7 +876,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } if cx.invalid_refs.len() >= 1 { - cx.report_invalid_references(numbered_position_args, &parser.arg_places); + cx.report_invalid_references(numbered_position_args); } // Make sure that all arguments were used and all arguments have types. @@ -894,7 +908,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } else { let mut diag = cx.ecx.struct_span_err( errs.iter().map(|&(sp, _)| sp).collect::>(), - "multiple unused formatting arguments" + "multiple unused formatting arguments", ); diag.span_label(cx.fmtsp, "multiple missing formatting arguments"); diag diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index 2d49c36c06de1..4f5f37132e821 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -25,34 +25,34 @@ LL | format!("{} {}"); | ^^ ^^ error: invalid reference to positional argument 1 (there is 1 argument) - --> $DIR/ifmt-bad-arg.rs:26:14 + --> $DIR/ifmt-bad-arg.rs:26:18 | LL | format!("{0} {1}", 1); - | ^^^ ^^^ + | ^^^ | = note: positional arguments are zero-based error: invalid reference to positional argument 2 (there are 2 arguments) - --> $DIR/ifmt-bad-arg.rs:29:14 + --> $DIR/ifmt-bad-arg.rs:29:22 | LL | format!("{0} {1} {2}", 1, 2); - | ^^^ ^^^ ^^^ + | ^^^ | = note: positional arguments are zero-based error: invalid reference to positional argument 2 (there are 2 arguments) - --> $DIR/ifmt-bad-arg.rs:32:14 + --> $DIR/ifmt-bad-arg.rs:32:28 | LL | format!("{} {value} {} {}", 1, value=2); - | ^^ ^^^^^^^ ^^ ^^ + | ^^ | = note: positional arguments are zero-based error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments) - --> $DIR/ifmt-bad-arg.rs:34:14 + --> $DIR/ifmt-bad-arg.rs:34:38 | LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); - | ^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ + | ^^ ^^ ^^ | = note: positional arguments are zero-based From c55a698943c515c8028522360e42b12bbf4fb274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jul 2018 15:33:36 -0700 Subject: [PATCH 06/43] Only point at inside of string literals if they're actually string literals --- src/libsyntax_ext/format.rs | 30 +++++++++++++++---- .../ui/macros/macro-backtrace-println.stderr | 4 +-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index a320b52fb7bd9..3d22178eab05b 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -117,6 +117,8 @@ struct Context<'a, 'b: 'a> { invalid_refs: Vec<(usize, usize)>, /// Spans of all the formatting arguments, in order. arg_spans: Vec, + /// Wether this formatting string is a literal or it comes from a macro. + is_literal: bool, } /// Parses the arguments from the given list of tokens, returning None @@ -276,7 +278,11 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = MultiSpan::from_spans(self.arg_spans.clone()); + let sp = if self.is_literal { + MultiSpan::from_spans(self.arg_spans.clone()) + } else { + MultiSpan::from_span(self.fmtsp) + }; let mut refs: Vec<_> = self .invalid_refs .iter() @@ -294,7 +300,7 @@ impl<'a, 'b> Context<'a, 'b> { ), ); } else { - let (arg_list, sp) = match refs.len() { + let (arg_list, mut sp) = match refs.len() { 1 => { let (reg, pos) = refs.pop().unwrap(); ( @@ -317,11 +323,14 @@ impl<'a, 'b> Context<'a, 'b> { ) } }; + if !self.is_literal { + sp = MultiSpan::from_span(self.fmtsp); + } e = self.ecx.mut_span_err(sp, &format!("invalid reference to positional {} ({})", - arg_list, - self.describe_num_args())); + arg_list, + self.describe_num_args())); e.note("positional arguments are zero-based"); }; @@ -370,7 +379,11 @@ impl<'a, 'b> Context<'a, 'b> { Some(e) => *e, None => { let msg = format!("there is no argument named `{}`", name); - let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp); + let sp = if self.is_literal { + *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + } else { + self.fmtsp + }; let mut err = self.ecx.struct_span_err(sp, &msg[..]); err.emit(); return; @@ -721,7 +734,7 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, pub fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt, - mut sp: Span, + mut sp: Span, tts: &[tokenstream::TokenTree], ) -> Box { //if !ecx.ecfg.enable_allow_internal_unstable() { @@ -784,6 +797,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, return DummyResult::raw_expr(sp); } }; + let is_literal = match ecx.codemap().span_to_snippet(fmt_sp) { + Ok(ref s) if s.starts_with("\"") || s.starts_with("r#") => true, + _ => false, + }; let mut cx = Context { ecx, @@ -806,6 +823,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, fmtsp: fmt.span, invalid_refs: Vec::new(), arg_spans: Vec::new(), + is_literal, }; let fmt_str = &*fmt.node.0.as_str(); diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index f0ca576f652eb..8f2eb0173a499 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -1,8 +1,8 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-backtrace-println.rs:24:31 + --> $DIR/macro-backtrace-println.rs:24:30 | LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); //~ ERROR no arguments were given - | ^^ + | ^^^^^^^^^^^^^^^^^^^ ... LL | myprintln!("{}"); | ----------------- in this macro invocation From bde2be0b1c91489bc590650613fac63854568176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 23 Jul 2018 15:43:34 -0700 Subject: [PATCH 07/43] Add test for raw string --- src/test/ui/ifmt-bad-arg.rs | 7 +++++++ src/test/ui/ifmt-bad-arg.stderr | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/test/ui/ifmt-bad-arg.rs b/src/test/ui/ifmt-bad-arg.rs index afe9bc152a36c..bbd75f30d6cb1 100644 --- a/src/test/ui/ifmt-bad-arg.rs +++ b/src/test/ui/ifmt-bad-arg.rs @@ -64,4 +64,11 @@ fn main() { format!("foo }"); //~ ERROR: unmatched `}` found format!("foo %s baz", "bar"); //~ ERROR: argument never used + + format!(r##" + + {foo} + + "##); + //~^^^ ERROR: there is no argument named `foo` } diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index 4f5f37132e821..b02aa765d09a3 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -183,5 +183,11 @@ LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used = help: `%s` should be written as `{}` = note: printf formatting not supported; see the documentation for `std::fmt` -error: aborting due to 26 previous errors +error: there is no argument named `foo` + --> $DIR/ifmt-bad-arg.rs:70:9 + | +LL | {foo} + | ^^^^^ + +error: aborting due to 27 previous errors From 22d0ab0bc3627e94e953a2be981295440b52289e Mon Sep 17 00:00:00 2001 From: alecmocatta Date: Tue, 24 Jul 2018 00:47:34 +0100 Subject: [PATCH 08/43] Pass multiple linker arguments rather than concatenate with commas; -l library -> -llibrary to work with apple's ld --- src/librustc_codegen_llvm/back/linker.rs | 35 ++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index f5f486893854f..4a5de6426b2d6 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -218,8 +218,10 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { - fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); } - fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); } + fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}",lib)); } + fn link_staticlib(&mut self, lib: &str) { + self.hint_static(); self.cmd.arg(format!("-l{}",lib)); + } fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); } fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); } @@ -227,15 +229,15 @@ impl<'a> Linker for GccLinker<'a> { fn add_object(&mut self, path: &Path) { self.cmd.arg(path); } fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); } fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); } - fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); } - fn partial_relro(&mut self) { self.linker_arg("-z,relro"); } - fn no_relro(&mut self) { self.linker_arg("-z,norelro"); } + fn full_relro(&mut self) { self.linker_arg("-zrelro"); self.linker_arg("-znow"); } + fn partial_relro(&mut self) { self.linker_arg("-zrelro"); } + fn no_relro(&mut self) { self.linker_arg("-znorelro"); } fn build_static_executable(&mut self) { self.cmd.arg("-static"); } fn args(&mut self, args: &[String]) { self.cmd.args(args); } fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { self.hint_dynamic(); - self.cmd.arg("-l").arg(lib); + self.cmd.arg(format!("-l{}",lib)); } fn link_framework(&mut self, framework: &str) { @@ -253,23 +255,22 @@ impl<'a> Linker for GccLinker<'a> { self.hint_static(); let target = &self.sess.target.target; if !target.options.is_like_osx { - self.linker_arg("--whole-archive").cmd.arg("-l").arg(lib); + self.linker_arg("--whole-archive").cmd.arg(format!("-l{}",lib)); self.linker_arg("--no-whole-archive"); } else { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. - let mut v = OsString::from("-force_load,"); - v.push(&archive::find_library(lib, search_path, &self.sess)); - self.linker_arg(&v); + self.linker_arg("-force_load"); + let lib = archive::find_library(lib, search_path, &self.sess); + self.linker_arg(&lib); } } fn link_whole_rlib(&mut self, lib: &Path) { self.hint_static(); if self.sess.target.target.options.is_like_osx { - let mut v = OsString::from("-force_load,"); - v.push(lib); - self.linker_arg(&v); + self.linker_arg("-force_load"); + self.linker_arg(&lib); } else { self.linker_arg("--whole-archive").cmd.arg(lib); self.linker_arg("--no-whole-archive"); @@ -294,8 +295,7 @@ impl<'a> Linker for GccLinker<'a> { if self.sess.target.target.options.is_like_osx { self.linker_arg("-dead_strip"); } else if self.sess.target.target.options.is_like_solaris { - self.linker_arg("-z"); - self.linker_arg("ignore"); + self.linker_arg("-zignore"); // If we're building a dylib, we don't use --gc-sections because LLVM // has already done the best it can do, and we also don't want to @@ -369,7 +369,8 @@ impl<'a> Linker for GccLinker<'a> { // the right `-Wl,-install_name` with an `@rpath` in it. if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name { - let mut v = OsString::from("-install_name,@rpath/"); + self.linker_arg("-install_name"); + let mut v = OsString::from("@rpath/"); v.push(out_filename.file_name().unwrap()); self.linker_arg(&v); } @@ -448,7 +449,7 @@ impl<'a> Linker for GccLinker<'a> { } fn subsystem(&mut self, subsystem: &str) { - self.linker_arg(&format!("--subsystem,{}", subsystem)); + self.linker_arg(&format!("--subsystem={}", subsystem)); } fn finalize(&mut self) -> Command { From 5363911d8537eff55c09239a68e831f2a7bc724d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 Jul 2018 22:41:09 -0400 Subject: [PATCH 09/43] Add tests for #34784 Closes #34784 --- src/test/compile-fail/issue-34784.rs | 20 ++++++++++++++++++++ src/test/run-pass/issue-34784.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/compile-fail/issue-34784.rs create mode 100644 src/test/run-pass/issue-34784.rs diff --git a/src/test/compile-fail/issue-34784.rs b/src/test/compile-fail/issue-34784.rs new file mode 100644 index 0000000000000..5c510b4a10d83 --- /dev/null +++ b/src/test/compile-fail/issue-34784.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const C: *const [u8; 4] = b"abcd"; + +fn main() { + match C { + C => {} + //~^ ERROR this expression will panic at runtime + _ => {} + } +} + diff --git a/src/test/run-pass/issue-34784.rs b/src/test/run-pass/issue-34784.rs new file mode 100644 index 0000000000000..c9a214e0cedd0 --- /dev/null +++ b/src/test/run-pass/issue-34784.rs @@ -0,0 +1,28 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const C: *const u8 = &0; + +fn foo(x: *const u8) { + match x { + C => {} + _ => {} + } +} + +const D: *const [u8; 4] = b"abcd"; + +fn main() { + match D { + D => {} + _ => {} + } +} + From 296a179b1cf5fc79c77c79cfa56e6c57e50b4613 Mon Sep 17 00:00:00 2001 From: alecmocatta Date: Tue, 24 Jul 2018 02:11:57 +0100 Subject: [PATCH 10/43] break --subsystem=x into 2 args; closer to former presumably known-good incantation --- src/librustc_codegen_llvm/back/linker.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index 4a5de6426b2d6..f5bd31a67e5ce 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -449,7 +449,8 @@ impl<'a> Linker for GccLinker<'a> { } fn subsystem(&mut self, subsystem: &str) { - self.linker_arg(&format!("--subsystem={}", subsystem)); + self.linker_arg("--subsystem"); + self.linker_arg(&subsystem); } fn finalize(&mut self) -> Command { From 63ed6a19aa653e0264b565bad2015c3a2fe482ed Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 23 Jul 2018 21:24:18 -0400 Subject: [PATCH 11/43] Add test for #33264 Closes #33264 --- src/test/run-pass/issue-33264.rs | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/test/run-pass/issue-33264.rs diff --git a/src/test/run-pass/issue-33264.rs b/src/test/run-pass/issue-33264.rs new file mode 100644 index 0000000000000..cb4b227548aab --- /dev/null +++ b/src/test/run-pass/issue-33264.rs @@ -0,0 +1,39 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// only-x86_64 + +#![allow(dead_code, non_upper_case_globals)] +#![feature(asm)] + +#[repr(C)] +pub struct D32x4(f32,f32,f32,f32); + +impl D32x4 { + fn add(&self, vec: Self) -> Self { + unsafe { + let ret: Self; + asm!(" + movaps $1, %xmm1 + movaps $2, %xmm2 + addps %xmm1, %xmm2 + movaps $xmm1, $0 + " + : "=r"(ret) + : "1"(self), "2"(vec) + : "xmm1", "xmm2" + ); + ret + } + } +} + +fn main() { } + From bbbbf2dc323ebecae08d84249813fa8c29eec910 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 Jul 2018 23:01:34 -0400 Subject: [PATCH 12/43] Add run-pass test for #44005 Closes #44005 --- src/test/run-pass/issue-44005.rs | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/test/run-pass/issue-44005.rs diff --git a/src/test/run-pass/issue-44005.rs b/src/test/run-pass/issue-44005.rs new file mode 100644 index 0000000000000..a53026f36ab70 --- /dev/null +++ b/src/test/run-pass/issue-44005.rs @@ -0,0 +1,39 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo<'a> { + type Bar; + fn foo(&'a self) -> Self::Bar; +} + +impl<'a, 'b, T: 'a> Foo<'a> for &'b T { + type Bar = &'a T; + fn foo(&'a self) -> &'a T { + self + } +} + +pub fn uncallable(x: T, f: F) + where T: for<'a> Foo<'a>, + F: for<'a> Fn(>::Bar) +{ + f(x.foo()); +} + +pub fn catalyst(x: &i32) { + broken(x, |_| {}) +} + +pub fn broken(x: &i32, f: F) { + uncallable(x, |y| f(y)); +} + +fn main() { } + From 8c5ef0a09a55032c1b0b922b8b8ec5cc2672452e Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 Jul 2018 23:09:45 -0400 Subject: [PATCH 13/43] Add compile-fail test for #42060 Closes #42060 --- src/test/compile-fail/issue-42060.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/compile-fail/issue-42060.rs diff --git a/src/test/compile-fail/issue-42060.rs b/src/test/compile-fail/issue-42060.rs new file mode 100644 index 0000000000000..23df42d03c4e0 --- /dev/null +++ b/src/test/compile-fail/issue-42060.rs @@ -0,0 +1,22 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let thing = (); + let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant + //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516] +} + +fn f(){ + let q = 1; + ::N //~ ERROR attempt to use a non-constant value in a constant + //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516] +} + From 3290774fa999d93f3b44b6830f2ad42e06ebe43c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 Jul 2018 23:15:49 -0400 Subject: [PATCH 14/43] Add compile-fail test for #43196 Closes #43196 --- src/test/compile-fail/issue-43196.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/compile-fail/issue-43196.rs diff --git a/src/test/compile-fail/issue-43196.rs b/src/test/compile-fail/issue-43196.rs new file mode 100644 index 0000000000000..ff53c9a5a5498 --- /dev/null +++ b/src/test/compile-fail/issue-43196.rs @@ -0,0 +1,17 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + | +} +//~^ ERROR expected `|`, found `}` +| +//~^ ERROR expected item, found `|` + From 715005c1a76129f7d2c0e85f2ef0af96a8c2add6 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 19 Jul 2018 23:30:42 -0400 Subject: [PATCH 15/43] Update compile-fail tests to be ui tests --- src/test/compile-fail/issue-34784.rs | 20 -------------- src/test/{compile-fail => ui}/issue-42060.rs | 0 src/test/ui/issue-42060.stderr | 28 ++++++++++++++++++++ src/test/{compile-fail => ui}/issue-43196.rs | 0 src/test/ui/issue-43196.stderr | 16 +++++++++++ 5 files changed, 44 insertions(+), 20 deletions(-) delete mode 100644 src/test/compile-fail/issue-34784.rs rename src/test/{compile-fail => ui}/issue-42060.rs (100%) create mode 100644 src/test/ui/issue-42060.stderr rename src/test/{compile-fail => ui}/issue-43196.rs (100%) create mode 100644 src/test/ui/issue-43196.stderr diff --git a/src/test/compile-fail/issue-34784.rs b/src/test/compile-fail/issue-34784.rs deleted file mode 100644 index 5c510b4a10d83..0000000000000 --- a/src/test/compile-fail/issue-34784.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const C: *const [u8; 4] = b"abcd"; - -fn main() { - match C { - C => {} - //~^ ERROR this expression will panic at runtime - _ => {} - } -} - diff --git a/src/test/compile-fail/issue-42060.rs b/src/test/ui/issue-42060.rs similarity index 100% rename from src/test/compile-fail/issue-42060.rs rename to src/test/ui/issue-42060.rs diff --git a/src/test/ui/issue-42060.stderr b/src/test/ui/issue-42060.stderr new file mode 100644 index 0000000000000..69abac8ee7e3a --- /dev/null +++ b/src/test/ui/issue-42060.stderr @@ -0,0 +1,28 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-42060.rs:13:23 + | +LL | let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant + | ^^^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-42060.rs:19:13 + | +LL | ::N //~ ERROR attempt to use a non-constant value in a constant + | ^ non-constant value + +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-42060.rs:13:16 + | +LL | let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant + | ^^^^^^^^^^^^^ reserved keyword + +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-42060.rs:19:6 + | +LL | ::N //~ ERROR attempt to use a non-constant value in a constant + | ^^^^^^^^^ reserved keyword + +error: aborting due to 4 previous errors + +Some errors occurred: E0435, E0516. +For more information about an error, try `rustc --explain E0435`. diff --git a/src/test/compile-fail/issue-43196.rs b/src/test/ui/issue-43196.rs similarity index 100% rename from src/test/compile-fail/issue-43196.rs rename to src/test/ui/issue-43196.rs diff --git a/src/test/ui/issue-43196.stderr b/src/test/ui/issue-43196.stderr new file mode 100644 index 0000000000000..2418f517168a4 --- /dev/null +++ b/src/test/ui/issue-43196.stderr @@ -0,0 +1,16 @@ +error: expected `|`, found `}` + --> $DIR/issue-43196.rs:13:1 + | +LL | | + | - expected `|` here +LL | } + | ^ unexpected token + +error: expected item, found `|` + --> $DIR/issue-43196.rs:15:1 + | +LL | | + | ^ expected item + +error: aborting due to 2 previous errors + From 27c0d564efedef1bec06076c8c12108c0d6fd6ec Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Mon, 23 Jul 2018 22:45:37 +0800 Subject: [PATCH 16/43] Mark the suggestion applicable --- src/librustc/traits/error_reporting.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 1c502b6610302..e0dcbf520b4c6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1048,25 +1048,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_label(span, format!( "expected {} that takes {}", kind, expected_str)); if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {}", found_str)); + // Suggest to take and ignore the arguments with expected_args_length `_`s if // found arguments is empty(Suppose the user just wants to ignore args in this case). // like `|_, _|` for closure with 2 expected args. if found_args.is_empty() && is_closure { let mut underscores = "_".repeat(expected_args.len()) - .split("") - .filter(|s| !s.is_empty()) - .collect::>() - .join(", "); - err.span_suggestion( + .split("") + .filter(|s| !s.is_empty()) + .collect::>() + .join(", "); + err.span_suggestion_with_applicability( found_span, - "consider changing this to", + &format!("change the closure to take and ignore the argument{}", + if expected_args.len() < 2 { + "" + } else { + "s" + } + ), format!("|{}|", underscores), + Applicability::MachineApplicable, ); - } else { - err.span_label(found_span, format!("takes {}", found_str)); } - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { if fields.len() == expected_args.len() { let sugg = fields.iter() From a71deb2633eeaf03f64ae0ee3b389128ec06f392 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Tue, 24 Jul 2018 10:09:45 +0800 Subject: [PATCH 17/43] Fix ui test --- .../ui/mismatched_types/closure-arg-count.stderr | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 6270e79449876..73e00df21110e 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -2,8 +2,10 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:15 | LL | [1, 2, 3].sort_by(|| panic!()); - | ^^^^^^^ -- takes 0 arguments - | | + | ^^^^^^^ -- + | | | + | | takes 0 arguments + | | help: change the closure to take and ignore the arguments: `|_, _|` | expected closure that takes 2 arguments error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument @@ -42,8 +44,10 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:23:5 | LL | f(|| panic!()); - | ^ -- takes 0 arguments - | | + | ^ -- + | | | + | | takes 0 arguments + | | help: change the closure to take and ignore the argument: `|_|` | expected closure that takes 1 argument | note: required by `f` From 9808f7cb397ce681673f2c1ad4c478da64162fd3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 24 Jul 2018 11:08:11 -0500 Subject: [PATCH 18/43] update the stdsimd submodule to bring in the doc generation fix --- src/stdsimd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdsimd b/src/stdsimd index b9de11ab43090..05c2f61c384e2 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit b9de11ab43090c71ff7ab159a479394df1f968ab +Subproject commit 05c2f61c384e2097a3a4c648344114fc4ac983be From f487e39e91e7f57637243674e14e6fa48cc2e193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 09:46:41 -0700 Subject: [PATCH 19/43] Add documentation for `Parser::arg_places` --- src/libfmt_macros/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index f6dcebf8c50f5..30a3bbdc58e98 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -154,6 +154,7 @@ pub struct Parser<'a> { style: Option, /// How many newlines have been seen in the string so far, to adjust the error spans seen_newlines: usize, + /// Start and end byte offset of every successfuly parsed argument pub arg_places: Vec<(usize, usize)>, } From f9e37625e6e9d90ee8b7200313de3915e2fc15a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 09:51:04 -0700 Subject: [PATCH 20/43] Reword missing formatting arguments label --- src/libsyntax_ext/format.rs | 2 +- src/test/ui/ifmt-bad-arg.stderr | 4 ++-- src/test/ui/macros/format-foreign.stderr | 2 +- src/test/ui/macros/format-unused-lables.stderr | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 3d22178eab05b..023fe77cb3c12 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -928,7 +928,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, errs.iter().map(|&(sp, _)| sp).collect::>(), "multiple unused formatting arguments", ); - diag.span_label(cx.fmtsp, "multiple missing formatting arguments"); + diag.span_label(cx.fmtsp, "multiple missing formatting specifiers"); diag } }; diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index b02aa765d09a3..92c44cf406be7 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -80,7 +80,7 @@ error: multiple unused formatting arguments LL | format!("", 1, 2); //~ ERROR: multiple unused formatting arguments | -- ^ ^ | | - | multiple missing formatting arguments + | multiple missing formatting specifiers error: argument never used --> $DIR/ifmt-bad-arg.rs:43:22 @@ -118,7 +118,7 @@ error: multiple unused formatting arguments LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments | ------- ^ ^ | | - | multiple missing formatting arguments + | multiple missing formatting specifiers error: duplicate argument named `foo` --> $DIR/ifmt-bad-arg.rs:50:33 diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 401b2f6d67e39..83ff301dc19cf 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -4,7 +4,7 @@ error: multiple unused formatting arguments LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments | -------------- ^^^^^^^^ ^^^^^^^ ^ | | - | multiple missing formatting arguments + | multiple missing formatting specifiers | = help: `%.*3$s` should be written as `{:.2$}` = help: `%s` should be written as `{}` diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index f764190438f33..0b024facc8e38 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -4,13 +4,13 @@ error: multiple unused formatting arguments LL | println!("Test", 123, 456, 789); | ------ ^^^ ^^^ ^^^ | | - | multiple missing formatting arguments + | multiple missing formatting specifiers error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:16:9 | LL | println!("Test2", - | ------- multiple missing formatting arguments + | ------- multiple missing formatting specifiers LL | 123, //~ ERROR multiple unused formatting arguments | ^^^ LL | 456, @@ -28,7 +28,7 @@ error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:24:9 | LL | println!("Some more $STUFF", - | ------------------ multiple missing formatting arguments + | ------------------ multiple missing formatting specifiers LL | "woo!", //~ ERROR multiple unused formatting arguments | ^^^^^^ LL | STUFF= From 75d22263c92c28510a1bff2a91031d28817443d8 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 24 Jul 2018 15:33:19 -0400 Subject: [PATCH 21/43] Impl Executor for Box --- src/liballoc/boxed.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6d3bc6e79b573..2cf9b13a67a27 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -67,7 +67,7 @@ use core::marker::{Unpin, Unsize}; use core::mem::{self, PinMut}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; -use core::task::{Context, Poll}; +use core::task::{Context, Poll, Executor, SpawnErrorKind, SpawnObjError}; use raw_vec::RawVec; use str::from_boxed_utf8_unchecked; @@ -972,6 +972,19 @@ unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox } } +#[unstable(feature = "futures_api", issue = "50547")] +impl Executor for Box + where E: Executor + ?Sized +{ + fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError> { + (**self).spawn_obj(task) + } + + fn status(&self) -> Result<(), SpawnErrorKind> { + (**self).status() + } +} + #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: PinBox) -> Self { From 4d8aa5989c3ecbcee9da63fdcf4564f71ac328fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 16:01:38 -0700 Subject: [PATCH 22/43] Use suggestions for `printf` format --- src/libsyntax_ext/format.rs | 17 +++++++- src/libsyntax_ext/format_foreign.rs | 54 ++++++++++++++++++++++-- src/test/ui/ifmt-bad-arg.stderr | 5 ++- src/test/ui/macros/format-foreign.rs | 5 +++ src/test/ui/macros/format-foreign.stderr | 35 ++++++++++++--- 5 files changed, 102 insertions(+), 14 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 023fe77cb3c12..ad05db91770a3 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -948,6 +948,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, ($kind:ident) => {{ let mut show_doc_note = false; + let mut suggestions = vec![]; for sub in foreign::$kind::iter_subs(fmt_str) { let trn = match sub.translate() { Some(trn) => trn, @@ -956,6 +957,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, None => continue, }; + let pos = sub.position(); let sub = String::from(sub.as_str()); if explained.contains(&sub) { continue; @@ -967,7 +969,14 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, show_doc_note = true; } - diag.help(&format!("`{}` should be written as `{}`", sub, trn)); + if let Some((start, end)) = pos { + // account for `"` and account for raw strings `r#` + let padding = str_style.map(|i| i + 2).unwrap_or(1); + let sp = fmt_sp.from_inner_byte_pos(start + padding, end + padding); + suggestions.push((sp, trn)); + } else { + diag.help(&format!("`{}` should be written as `{}`", sub, trn)); + } } if show_doc_note { @@ -976,6 +985,12 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, " formatting not supported; see the documentation for `std::fmt`", )); } + if suggestions.len() > 0 { + diag.multipart_suggestion( + "format specifiers in Rust are written using `{}`", + suggestions, + ); + } }}; } diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index ff9663cdd3cc5..115f51c5e813a 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -14,7 +14,7 @@ pub mod printf { /// Represents a single `printf`-style substitution. #[derive(Clone, PartialEq, Debug)] pub enum Substitution<'a> { - /// A formatted output substitution. + /// A formatted output substitution with its internal byte offset. Format(Format<'a>), /// A literal `%%` escape. Escape, @@ -28,6 +28,23 @@ pub mod printf { } } + pub fn position(&self) -> Option<(usize, usize)> { + match *self { + Substitution::Format(ref fmt) => Some(fmt.position), + _ => None, + } + } + + pub fn set_position(&mut self, start: usize, end: usize) { + match self { + Substitution::Format(ref mut fmt) => { + fmt.position = (start, end); + } + _ => {} + } + } + + /// Translate this substitution into an equivalent Rust formatting directive. /// /// This ignores cases where the substitution does not have an exact equivalent, or where @@ -57,6 +74,8 @@ pub mod printf { pub length: Option<&'a str>, /// Type of parameter being converted. pub type_: &'a str, + /// Byte offset for the start and end of this formatting directive. + pub position: (usize, usize), } impl<'a> Format<'a> { @@ -257,19 +276,28 @@ pub mod printf { pub fn iter_subs(s: &str) -> Substitutions { Substitutions { s, + pos: 0, } } /// Iterator over substitutions in a string. pub struct Substitutions<'a> { s: &'a str, + pos: usize, } impl<'a> Iterator for Substitutions<'a> { type Item = Substitution<'a>; fn next(&mut self) -> Option { - let (sub, tail) = parse_next_substitution(self.s)?; + let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; + match sub { + Substitution::Format(_) => if let Some((start, end)) = sub.position() { + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; + } + Substitution::Escape => self.pos += 2, + } Some(sub) } @@ -301,7 +329,9 @@ pub mod printf { _ => {/* fall-through */}, } - Cur::new_at_start(&s[start..]) + //let _ = Cur::new_at_start_with_pos(&s[..], start); + //Cur::new_at_start(&s[start..]) + Cur::new_at_start_with_pos(&s[..], start) }; // This is meant to be a translation of the following regex: @@ -355,6 +385,7 @@ pub mod printf { precision: None, length: None, type_: at.slice_between(next).unwrap(), + position: (start.at, next.at), }), next.slice_after() )); @@ -541,6 +572,7 @@ pub mod printf { drop(next); end = at; + let position = (start.at, end.at); let f = Format { span: start.slice_between(end).unwrap(), @@ -550,6 +582,7 @@ pub mod printf { precision, length, type_, + position, }; Some((Substitution::Format(f), end.slice_after())) } @@ -755,6 +788,12 @@ pub mod shell { } } + pub fn position(&self) -> Option<(usize, usize)> { + match *self { + _ => None, + } + } + pub fn translate(&self) -> Option { match *self { Substitution::Ordinal(n) => Some(format!("{{{}}}", n)), @@ -918,7 +957,7 @@ mod strcursor { pub struct StrCursor<'a> { s: &'a str, - at: usize, + pub at: usize, } impl<'a> StrCursor<'a> { @@ -929,6 +968,13 @@ mod strcursor { } } + pub fn new_at_start_with_pos(s: &'a str, at: usize) -> StrCursor<'a> { + StrCursor { + s, + at, + } + } + pub fn at_next_cp(mut self) -> Option> { match self.try_seek_right_cp() { true => Some(self), diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index 92c44cf406be7..a126998355e0c 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -178,9 +178,10 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:66:27 | LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used - | ^^^^^ + | -- ^^^^^ + | | + | help: format specifiers in Rust are written using `{}`: `{}` | - = help: `%s` should be written as `{}` = note: printf formatting not supported; see the documentation for `std::fmt` error: there is no argument named `foo` diff --git a/src/test/ui/macros/format-foreign.rs b/src/test/ui/macros/format-foreign.rs index ec0eaed43aea6..33401424c9ada 100644 --- a/src/test/ui/macros/format-foreign.rs +++ b/src/test/ui/macros/format-foreign.rs @@ -11,6 +11,11 @@ fn main() { println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments println!("%1$*2$.*3$f", 123.456); //~ ERROR never used + println!(r###"%.*3$s + %s!\n +"###, "Hello,", "World", 4); + //~^ ERROR multiple unused formatting arguments + // correctly account for raw strings in inline suggestions // This should *not* produce hints, on the basis that there's equally as // many "correct" format specifiers. It's *probably* just an actual typo. diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 83ff301dc19cf..93e68183b140e 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -6,27 +6,48 @@ LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unus | | | multiple missing formatting specifiers | - = help: `%.*3$s` should be written as `{:.2$}` - = help: `%s` should be written as `{}` = note: printf formatting not supported; see the documentation for `std::fmt` +help: format specifiers in Rust are written using `{}` + | +LL | println!("{:.2$} {}!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments + | ^^^^^^ ^^ error: argument never used --> $DIR/format-foreign.rs:13:29 | LL | println!("%1$*2$.*3$f", 123.456); //~ ERROR never used - | ^^^^^^^ + | ----------- ^^^^^^^ + | | + | help: format specifiers in Rust are written using `{}`: `{0:1$.2$}` + | + = note: printf formatting not supported; see the documentation for `std::fmt` + +error: multiple unused formatting arguments + --> $DIR/format-foreign.rs:16:7 + | +LL | println!(r###"%.*3$s + | ______________- +LL | | %s!/n +LL | | "###, "Hello,", "World", 4); + | | - ^^^^^^^^ ^^^^^^^ ^ + | |____| + | multiple missing formatting specifiers | - = help: `%1$*2$.*3$f` should be written as `{0:1$.2$}` = note: printf formatting not supported; see the documentation for `std::fmt` +help: format specifiers in Rust are written using `{}` + | +LL | println!(r###"{:.2$} +LL | {}!/n + | error: argument never used - --> $DIR/format-foreign.rs:17:30 + --> $DIR/format-foreign.rs:22:30 | LL | println!("{} %f", "one", 2.0); //~ ERROR never used | ^^^ error: named argument never used - --> $DIR/format-foreign.rs:19:39 + --> $DIR/format-foreign.rs:24:39 | LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used | ^^^^^ @@ -34,5 +55,5 @@ LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used = help: `$NAME` should be written as `{NAME}` = note: shell formatting not supported; see the documentation for `std::fmt` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors From 94921768ea30fb74889d7a0e7b96989358573c63 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 25 Jul 2018 08:06:45 +0800 Subject: [PATCH 23/43] Suggest in separate line --- src/librustc/traits/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e0dcbf520b4c6..72ca6a4af1776 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1061,7 +1061,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .join(", "); err.span_suggestion_with_applicability( found_span, - &format!("change the closure to take and ignore the argument{}", + &format!("change the closure to take and ignore the expected argument{}", if expected_args.len() < 2 { "" } else { From e8bc064c5ecf7775999beef233e2d82c9a534362 Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Sun, 22 Jul 2018 20:33:04 -0400 Subject: [PATCH 24/43] Add regression test for issue #18804 Signed-off-by: Gabriel Smith --- .../run-pass/issue-18804/auxiliary/lib.rs | 20 +++++++++++++++++++ src/test/run-pass/issue-18804/main.rs | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/run-pass/issue-18804/auxiliary/lib.rs create mode 100644 src/test/run-pass/issue-18804/main.rs diff --git a/src/test/run-pass/issue-18804/auxiliary/lib.rs b/src/test/run-pass/issue-18804/auxiliary/lib.rs new file mode 100644 index 0000000000000..06d454b2c890a --- /dev/null +++ b/src/test/run-pass/issue-18804/auxiliary/lib.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +#![feature(linkage)] + +pub fn foo() -> *const() { + extern { + #[linkage = "extern_weak"] + static FOO: *const(); + } + unsafe { FOO } +} diff --git a/src/test/run-pass/issue-18804/main.rs b/src/test/run-pass/issue-18804/main.rs new file mode 100644 index 0000000000000..de7967e8d3490 --- /dev/null +++ b/src/test/run-pass/issue-18804/main.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for issue #18804, #[linkage] does not propagate thorugh generic +// functions. Failure results in a linker error. + +// aux-build:lib.rs + +extern crate lib; + +fn main() { + lib::foo::(); +} From a20262c06986acb98150913e2c43cb13cead92a7 Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Sun, 22 Jul 2018 19:30:52 -0400 Subject: [PATCH 25/43] Properly set the linkage type on non-local statics Fixes issue #18804 Signed-off-by: Gabriel Smith --- src/librustc_codegen_llvm/consts.rs | 59 ++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 5a2d958038422..1d42c84e2befb 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -119,6 +119,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { let ty = instance.ty(cx.tcx); let sym = cx.tcx.symbol_name(instance).as_str(); + debug!("get_static: sym={} instance={:?}", sym, instance); + let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) { let llty = cx.layout_of(ty).llvm_type(cx); @@ -145,6 +147,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { ref attrs, span, node: hir::ForeignItemKind::Static(..), .. }) => { let g = if let Some(linkage) = cx.tcx.codegen_fn_attrs(def_id).linkage { + debug!("get_static: sym={} linkage={:?}", sym, linkage); + // If this is a static with a linkage specified, then we need to handle // it a little specially. The typesystem prevents things like &T and // extern "C" fn() from being non-null, so we can't just declare a @@ -188,6 +192,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { item => bug!("get_static: expected static, found {:?}", item) }; + debug!("get_static: sym={} attrs={:?}", sym, attrs); + for attr in attrs { if attr.check_name("thread_local") { llvm::set_thread_local_mode(g, cx.tls_model); @@ -197,19 +203,60 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { g } else { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? - // FIXME(nagisa): investigate whether it can be changed into define_global - let g = declare::declare_global(cx, &sym, cx.layout_of(ty).llvm_type(cx)); + debug!("get_static: sym={} item_attr={:?}", sym, cx.tcx.item_attrs(def_id)); + + let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(def_id); + let llty = cx.layout_of(ty).llvm_type(cx); + let g = if let Some(linkage) = codegen_fn_attrs.linkage { + debug!("get_static: sym={} linkage={:?}", sym, linkage); + + // If this is a static with a linkage specified, then we need to handle + // it a little specially. The typesystem prevents things like &T and + // extern "C" fn() from being non-null, so we can't just declare a + // static and call it a day. Some linkages (like weak) will make it such + // that the static actually has a null value. + let llty2 = match ty.sty { + ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), + _ => { + bug!("must have type `*const T` or `*mut T`") + } + }; + unsafe { + // Declare a symbol `foo` with the desired linkage. + let g1 = declare::declare_global(cx, &sym, llty2); + llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); + + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let mut real_name = "_rust_extern_with_linkage_".to_string(); + real_name.push_str(&sym); + let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{ + bug!("symbol `{}` is already defined", &sym) + }); + llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); + llvm::LLVMSetInitializer(g2, g1); + g2 + } + } else { + // Generate an external declaration. + // FIXME(nagisa): investigate whether it can be changed into define_global + declare::declare_global(cx, &sym, llty) + }; + // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the // thread-local attribute locally if it was present remotely. If we // don't do this then linker errors can be generated where the linker // complains that one object files has a thread local version of the // symbol and another one doesn't. - for attr in cx.tcx.get_attrs(def_id).iter() { - if attr.check_name("thread_local") { - llvm::set_thread_local_mode(g, cx.tls_model); - } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { + llvm::set_thread_local_mode(g, cx.tls_model); } + if cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) { // This item is external but not foreign, i.e. it originates from an external Rust // crate. Since we don't know whether this crate will be linked dynamically or From 0bcbe91b487ea933aba9a9e079f01133574fc98f Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Mon, 23 Jul 2018 08:43:22 -0400 Subject: [PATCH 26/43] Deduplicate linkage checking code for statics Signed-off-by: Gabriel Smith --- src/librustc_codegen_llvm/consts.rs | 154 +++++++++++++--------------- 1 file changed, 69 insertions(+), 85 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 1d42c84e2befb..f0b5f4b887971 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -20,12 +20,14 @@ use monomorphize::MonoItem; use common::{CodegenCx, val_ty}; use declare; use monomorphize::Instance; +use syntax_pos::Span; +use syntax_pos::symbol::LocalInternedString; use type_::Type; use type_of::LayoutLlvmExt; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc::ty::layout::{Align, LayoutOf}; -use rustc::hir::{self, CodegenFnAttrFlags}; +use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; use std::ffi::{CStr, CString}; @@ -146,47 +148,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { hir_map::NodeForeignItem(&hir::ForeignItem { ref attrs, span, node: hir::ForeignItemKind::Static(..), .. }) => { - let g = if let Some(linkage) = cx.tcx.codegen_fn_attrs(def_id).linkage { - debug!("get_static: sym={} linkage={:?}", sym, linkage); - - // If this is a static with a linkage specified, then we need to handle - // it a little specially. The typesystem prevents things like &T and - // extern "C" fn() from being non-null, so we can't just declare a - // static and call it a day. Some linkages (like weak) will make it such - // that the static actually has a null value. - let llty2 = match ty.sty { - ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), - _ => { - cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`"); - } - }; - unsafe { - // Declare a symbol `foo` with the desired linkage. - let g1 = declare::declare_global(cx, &sym, llty2); - llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); - - // Declare an internal global `extern_with_linkage_foo` which - // is initialized with the address of `foo`. If `foo` is - // discarded during linking (for example, if `foo` has weak - // linkage and there are no definitions), then - // `extern_with_linkage_foo` will instead be initialized to - // zero. - let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&sym); - let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{ - cx.sess().span_fatal(span, - &format!("symbol `{}` is already defined", &sym)) - }); - llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); - llvm::LLVMSetInitializer(g2, g1); - g2 - } - } else { - // Generate an external declaration. - declare::declare_global(cx, &sym, llty) - }; - - (g, attrs) + let fn_attrs = cx.tcx.codegen_fn_attrs(def_id); + (check_and_apply_linkage(cx, &fn_attrs, ty, sym, Some(span)), attrs) } item => bug!("get_static: expected static, found {:?}", item) @@ -205,47 +168,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? debug!("get_static: sym={} item_attr={:?}", sym, cx.tcx.item_attrs(def_id)); - let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(def_id); - let llty = cx.layout_of(ty).llvm_type(cx); - let g = if let Some(linkage) = codegen_fn_attrs.linkage { - debug!("get_static: sym={} linkage={:?}", sym, linkage); - - // If this is a static with a linkage specified, then we need to handle - // it a little specially. The typesystem prevents things like &T and - // extern "C" fn() from being non-null, so we can't just declare a - // static and call it a day. Some linkages (like weak) will make it such - // that the static actually has a null value. - let llty2 = match ty.sty { - ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), - _ => { - bug!("must have type `*const T` or `*mut T`") - } - }; - unsafe { - // Declare a symbol `foo` with the desired linkage. - let g1 = declare::declare_global(cx, &sym, llty2); - llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); - - // Declare an internal global `extern_with_linkage_foo` which - // is initialized with the address of `foo`. If `foo` is - // discarded during linking (for example, if `foo` has weak - // linkage and there are no definitions), then - // `extern_with_linkage_foo` will instead be initialized to - // zero. - let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&sym); - let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{ - bug!("symbol `{}` is already defined", &sym) - }); - llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); - llvm::LLVMSetInitializer(g2, g1); - g2 - } - } else { - // Generate an external declaration. - // FIXME(nagisa): investigate whether it can be changed into define_global - declare::declare_global(cx, &sym, llty) - }; + let attrs = cx.tcx.codegen_fn_attrs(def_id); + let g = check_and_apply_linkage(cx, &attrs, ty, sym, None); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the @@ -253,7 +177,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { // don't do this then linker errors can be generated where the linker // complains that one object files has a thread local version of the // symbol and another one doesn't. - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { + if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { llvm::set_thread_local_mode(g, cx.tls_model); } @@ -289,6 +213,66 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { g } +fn check_and_apply_linkage<'tcx>( + cx: &CodegenCx<'_, 'tcx>, + attrs: &CodegenFnAttrs, + ty: Ty<'tcx>, + sym: LocalInternedString, + span: Option +) -> ValueRef { + let llty = cx.layout_of(ty).llvm_type(cx); + if let Some(linkage) = attrs.linkage { + debug!("get_static: sym={} linkage={:?}", sym, linkage); + + // If this is a static with a linkage specified, then we need to handle + // it a little specially. The typesystem prevents things like &T and + // extern "C" fn() from being non-null, so we can't just declare a + // static and call it a day. Some linkages (like weak) will make it such + // that the static actually has a null value. + let llty2 = match ty.sty { + ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), + _ => { + if span.is_some() { + cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`") + } else { + bug!("must have type `*const T` or `*mut T`") + } + } + }; + unsafe { + // Declare a symbol `foo` with the desired linkage. + let g1 = declare::declare_global(cx, &sym, llty2); + llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); + + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let mut real_name = "_rust_extern_with_linkage_".to_string(); + real_name.push_str(&sym); + let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{ + if span.is_some() { + cx.sess().span_fatal( + span.unwrap(), + &format!("symbol `{}` is already defined", &sym) + ) + } else { + bug!("symbol `{}` is already defined", &sym) + } + }); + llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); + llvm::LLVMSetInitializer(g2, g1); + g2 + } + } else { + // Generate an external declaration. + // FIXME(nagisa): investigate whether it can be changed into define_global + declare::declare_global(cx, &sym, llty) + } +} + pub fn codegen_static<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, def_id: DefId, From e58e7b045c7c66a11e2b451ea48e763f6685699e Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Tue, 24 Jul 2018 08:51:57 -0400 Subject: [PATCH 27/43] Disable regression test for issue #18804 on Emscripten and Asmjs The Emscripten compiler does not support weak symbols at the moment. Signed-off-by: Gabriel Smith --- src/test/run-pass/issue-18804/auxiliary/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/run-pass/issue-18804/auxiliary/lib.rs b/src/test/run-pass/issue-18804/auxiliary/lib.rs index 06d454b2c890a..43434766362ff 100644 --- a/src/test/run-pass/issue-18804/auxiliary/lib.rs +++ b/src/test/run-pass/issue-18804/auxiliary/lib.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-asmjs no weak symbol support +// ignore-emscripten no weak symbol support + #![crate_type = "rlib"] #![feature(linkage)] From 40c0339cf689f74b62b90297f21c4176af1193fc Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 25 Jul 2018 09:09:13 +0800 Subject: [PATCH 28/43] Fix test --- .../mismatched_types/closure-arg-count.stderr | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 73e00df21110e..5660ff4c792ea 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -2,11 +2,13 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:15 | LL | [1, 2, 3].sort_by(|| panic!()); - | ^^^^^^^ -- - | | | - | | takes 0 arguments - | | help: change the closure to take and ignore the arguments: `|_, _|` + | ^^^^^^^ -- takes 0 arguments + | | | expected closure that takes 2 arguments +help: change the closure to take and ignore the expected arguments + | +LL | [1, 2, 3].sort_by(|_, _| panic!()); + | ^^^^^^ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument --> $DIR/closure-arg-count.rs:17:15 @@ -44,10 +46,8 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:23:5 | LL | f(|| panic!()); - | ^ -- - | | | - | | takes 0 arguments - | | help: change the closure to take and ignore the argument: `|_|` + | ^ -- takes 0 arguments + | | | expected closure that takes 1 argument | note: required by `f` @@ -55,6 +55,10 @@ note: required by `f` | LL | fn f>(_: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: change the closure to take and ignore the expected argument + | +LL | f(|_| panic!()); + | ^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:26:53 From d5256b75dfca78e257748ec01947e7327ea627bd Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 25 Jul 2018 09:30:10 +0800 Subject: [PATCH 29/43] Update comment and do suggest --- src/librustc/traits/error_reporting.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 72ca6a4af1776..8300f98fb1cd5 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1051,8 +1051,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_label(found_span, format!("takes {}", found_str)); // Suggest to take and ignore the arguments with expected_args_length `_`s if - // found arguments is empty(Suppose the user just wants to ignore args in this case). - // like `|_, _|` for closure with 2 expected args. + // found arguments is empty (assume the user just wants to ignore args in this case). + // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { let mut underscores = "_".repeat(expected_args.len()) .split("") @@ -1061,12 +1061,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .join(", "); err.span_suggestion_with_applicability( found_span, - &format!("change the closure to take and ignore the expected argument{}", - if expected_args.len() < 2 { - "" - } else { - "s" - } + &format!( + "consider changing the closure to take and ignore the expected argument{}", + if expected_args.len() < 2 { + "" + } else { + "s" + } ), format!("|{}|", underscores), Applicability::MachineApplicable, From 1d79588994ca773fa80938021729dbff4679d78b Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 25 Jul 2018 09:30:53 +0800 Subject: [PATCH 30/43] Update ui test --- src/test/ui/mismatched_types/closure-arg-count.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 5660ff4c792ea..057cf6efa1dea 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -5,7 +5,7 @@ LL | [1, 2, 3].sort_by(|| panic!()); | ^^^^^^^ -- takes 0 arguments | | | expected closure that takes 2 arguments -help: change the closure to take and ignore the expected arguments +help: consider changing the closure to take and ignore the expected arguments | LL | [1, 2, 3].sort_by(|_, _| panic!()); | ^^^^^^ @@ -55,7 +55,7 @@ note: required by `f` | LL | fn f>(_: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: change the closure to take and ignore the expected argument +help: consider changing the closure to take and ignore the expected argument | LL | f(|_| panic!()); | ^^^ From 3298b9f8c74cd859c6b6a3bb6f41c022f5605393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 18:44:34 -0700 Subject: [PATCH 31/43] Fix unittest --- src/libsyntax_ext/format_foreign.rs | 50 +++++++++++++++-------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 115f51c5e813a..136aedeb71d06 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -649,6 +649,7 @@ pub mod printf { ($in_:expr, { $param:expr, $flags:expr, $width:expr, $prec:expr, $len:expr, $type_:expr, + $pos:expr, }) => { assert_eq!( pns(concat!($in_, "!")), @@ -661,6 +662,7 @@ pub mod printf { precision: $prec, length: $len, type_: $type_, + position: $pos, }), "!" )) @@ -669,53 +671,53 @@ pub mod printf { } assert_pns_eq_sub!("%!", - { None, "", None, None, None, "!", }); + { None, "", None, None, None, "!", (0, 2), }); assert_pns_eq_sub!("%c", - { None, "", None, None, None, "c", }); + { None, "", None, None, None, "c", (0, 2), }); assert_pns_eq_sub!("%s", - { None, "", None, None, None, "s", }); + { None, "", None, None, None, "s", (0, 2), }); assert_pns_eq_sub!("%06d", - { None, "0", Some(N::Num(6)), None, None, "d", }); + { None, "0", Some(N::Num(6)), None, None, "d", (0, 4), }); assert_pns_eq_sub!("%4.2f", - { None, "", Some(N::Num(4)), Some(N::Num(2)), None, "f", }); + { None, "", Some(N::Num(4)), Some(N::Num(2)), None, "f", (0, 5), }); assert_pns_eq_sub!("%#x", - { None, "#", None, None, None, "x", }); + { None, "#", None, None, None, "x", (0, 3), }); assert_pns_eq_sub!("%-10s", - { None, "-", Some(N::Num(10)), None, None, "s", }); + { None, "-", Some(N::Num(10)), None, None, "s", (0, 5), }); assert_pns_eq_sub!("%*s", - { None, "", Some(N::Next), None, None, "s", }); + { None, "", Some(N::Next), None, None, "s", (0, 3), }); assert_pns_eq_sub!("%-10.*s", - { None, "-", Some(N::Num(10)), Some(N::Next), None, "s", }); + { None, "-", Some(N::Num(10)), Some(N::Next), None, "s", (0, 7), }); assert_pns_eq_sub!("%-*.*s", - { None, "-", Some(N::Next), Some(N::Next), None, "s", }); + { None, "-", Some(N::Next), Some(N::Next), None, "s", (0, 6), }); assert_pns_eq_sub!("%.6i", - { None, "", None, Some(N::Num(6)), None, "i", }); + { None, "", None, Some(N::Num(6)), None, "i", (0, 4), }); assert_pns_eq_sub!("%+i", - { None, "+", None, None, None, "i", }); + { None, "+", None, None, None, "i", (0, 3), }); assert_pns_eq_sub!("%08X", - { None, "0", Some(N::Num(8)), None, None, "X", }); + { None, "0", Some(N::Num(8)), None, None, "X", (0, 4), }); assert_pns_eq_sub!("%lu", - { None, "", None, None, Some("l"), "u", }); + { None, "", None, None, Some("l"), "u", (0, 3), }); assert_pns_eq_sub!("%Iu", - { None, "", None, None, Some("I"), "u", }); + { None, "", None, None, Some("I"), "u", (0, 3), }); assert_pns_eq_sub!("%I32u", - { None, "", None, None, Some("I32"), "u", }); + { None, "", None, None, Some("I32"), "u", (0, 5), }); assert_pns_eq_sub!("%I64u", - { None, "", None, None, Some("I64"), "u", }); + { None, "", None, None, Some("I64"), "u", (0, 5), }); assert_pns_eq_sub!("%'d", - { None, "'", None, None, None, "d", }); + { None, "'", None, None, None, "d", (0, 3), }); assert_pns_eq_sub!("%10s", - { None, "", Some(N::Num(10)), None, None, "s", }); + { None, "", Some(N::Num(10)), None, None, "s", (0, 4), }); assert_pns_eq_sub!("%-10.10s", - { None, "-", Some(N::Num(10)), Some(N::Num(10)), None, "s", }); + { None, "-", Some(N::Num(10)), Some(N::Num(10)), None, "s", (0, 8), }); assert_pns_eq_sub!("%1$d", - { Some(1), "", None, None, None, "d", }); + { Some(1), "", None, None, None, "d", (0, 4), }); assert_pns_eq_sub!("%2$.*3$d", - { Some(2), "", None, Some(N::Arg(3)), None, "d", }); + { Some(2), "", None, Some(N::Arg(3)), None, "d", (0, 8), }); assert_pns_eq_sub!("%1$*2$.*3$d", - { Some(1), "", Some(N::Arg(2)), Some(N::Arg(3)), None, "d", }); + { Some(1), "", Some(N::Arg(2)), Some(N::Arg(3)), None, "d", (0, 11), }); assert_pns_eq_sub!("%-8ld", - { None, "-", Some(N::Num(8)), None, Some("l"), "d", }); + { None, "-", Some(N::Num(8)), None, Some("l"), "d", (0, 5), }); } #[test] From 7bd94e0738dfaa91fe9fc16085969a7c9c3f8129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 20:37:38 -0700 Subject: [PATCH 32/43] Rename method and remove commented out code --- src/libsyntax_ext/format_foreign.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 136aedeb71d06..1613f193351fb 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -329,9 +329,7 @@ pub mod printf { _ => {/* fall-through */}, } - //let _ = Cur::new_at_start_with_pos(&s[..], start); - //Cur::new_at_start(&s[start..]) - Cur::new_at_start_with_pos(&s[..], start) + Cur::new_at(&s[..], start) }; // This is meant to be a translation of the following regex: @@ -970,7 +968,7 @@ mod strcursor { } } - pub fn new_at_start_with_pos(s: &'a str, at: usize) -> StrCursor<'a> { + pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { StrCursor { s, at, From 9a893cc2b82ac6259aead1319758404b80b8a959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Jul 2018 20:46:22 -0700 Subject: [PATCH 33/43] Add span label for format str missing specifier --- src/libsyntax_ext/format.rs | 19 +++++++----- src/test/ui/ifmt-bad-arg.stderr | 30 ++++++++++++++----- src/test/ui/macros/format-foreign.stderr | 10 ++++--- .../ui/macros/format-unused-lables.stderr | 4 ++- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index ad05db91770a3..98de3d80b1e1f 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -915,12 +915,13 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, errs.push((cx.args[i].span, msg)); } } - if errs.len() > 0 { - let args_used = cx.arg_types.len() - errs.len(); - let args_unused = errs.len(); + let errs_len = errs.len(); + if errs_len > 0 { + let args_used = cx.arg_types.len() - errs_len; + let args_unused = errs_len; let mut diag = { - if errs.len() == 1 { + if errs_len == 1 { let (sp, msg) = errs.into_iter().next().unwrap(); cx.ecx.struct_span_err(sp, msg) } else { @@ -933,6 +934,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } }; + // Used to ensure we only report translations for *one* kind of foreign format. + let mut found_foreign = false; // Decide if we want to look for foreign formatting directives. if args_used < args_unused { use super::format_foreign as foreign; @@ -941,9 +944,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, // with `%d should be written as {}` over and over again. let mut explained = HashSet::new(); - // Used to ensure we only report translations for *one* kind of foreign format. - let mut found_foreign = false; - macro_rules! check_foreign { ($kind:ident) => {{ let mut show_doc_note = false; @@ -987,7 +987,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } if suggestions.len() > 0 { diag.multipart_suggestion( - "format specifiers in Rust are written using `{}`", + "format specifiers use curly braces", suggestions, ); } @@ -999,6 +999,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, check_foreign!(shell); } } + if !found_foreign && errs_len == 1 { + diag.span_label(cx.fmtsp, "formatting specifier missing"); + } diag.emit(); } diff --git a/src/test/ui/ifmt-bad-arg.stderr b/src/test/ui/ifmt-bad-arg.stderr index a126998355e0c..c8fd8bad19ba5 100644 --- a/src/test/ui/ifmt-bad-arg.stderr +++ b/src/test/ui/ifmt-bad-arg.stderr @@ -16,7 +16,9 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:19:20 | LL | format!("{1}", 1); - | ^ + | ----- ^ + | | + | formatting specifier missing error: 2 positional arguments in format string, but no arguments were given --> $DIR/ifmt-bad-arg.rs:23:14 @@ -86,31 +88,41 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:43:22 | LL | format!("{}", 1, 2); //~ ERROR: argument never used - | ^ + | ---- ^ + | | + | formatting specifier missing error: argument never used --> $DIR/ifmt-bad-arg.rs:44:20 | LL | format!("{1}", 1, 2); //~ ERROR: argument never used - | ^ + | ----- ^ + | | + | formatting specifier missing error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:26 | LL | format!("{}", 1, foo=2); //~ ERROR: named argument never used - | ^ + | ---- ^ + | | + | formatting specifier missing error: argument never used --> $DIR/ifmt-bad-arg.rs:46:22 | LL | format!("{foo}", 1, foo=2); //~ ERROR: argument never used - | ^ + | ------- ^ + | | + | formatting specifier missing error: named argument never used --> $DIR/ifmt-bad-arg.rs:47:21 | LL | format!("", foo=2); //~ ERROR: named argument never used - | ^ + | -- ^ + | | + | formatting specifier missing error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:48:32 @@ -148,7 +160,9 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:55:51 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^ + | ------------------- ^ + | | + | formatting specifier missing error: invalid format string: expected `'}'` but string was terminated --> $DIR/ifmt-bad-arg.rs:61:15 @@ -180,7 +194,7 @@ error: argument never used LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used | -- ^^^^^ | | - | help: format specifiers in Rust are written using `{}`: `{}` + | help: format specifiers use curly braces: `{}` | = note: printf formatting not supported; see the documentation for `std::fmt` diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 93e68183b140e..5e76c0a322e51 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -7,7 +7,7 @@ LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unus | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` -help: format specifiers in Rust are written using `{}` +help: format specifiers use curly braces | LL | println!("{:.2$} {}!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments | ^^^^^^ ^^ @@ -18,7 +18,7 @@ error: argument never used LL | println!("%1$*2$.*3$f", 123.456); //~ ERROR never used | ----------- ^^^^^^^ | | - | help: format specifiers in Rust are written using `{}`: `{0:1$.2$}` + | help: format specifiers use curly braces: `{0:1$.2$}` | = note: printf formatting not supported; see the documentation for `std::fmt` @@ -34,7 +34,7 @@ LL | | "###, "Hello,", "World", 4); | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` -help: format specifiers in Rust are written using `{}` +help: format specifiers use curly braces | LL | println!(r###"{:.2$} LL | {}!/n @@ -44,7 +44,9 @@ error: argument never used --> $DIR/format-foreign.rs:22:30 | LL | println!("{} %f", "one", 2.0); //~ ERROR never used - | ^^^ + | ------- ^^^ + | | + | formatting specifier missing error: named argument never used --> $DIR/format-foreign.rs:24:39 diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index 0b024facc8e38..81171a1ed01de 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -22,7 +22,9 @@ error: named argument never used --> $DIR/format-unused-lables.rs:21:35 | LL | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used - | ^^^^^^ + | ------------ ^^^^^^ + | | + | formatting specifier missing error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:24:9 From 580f437ff2c7911662e2cc436b477d63b803c07c Mon Sep 17 00:00:00 2001 From: Paolo Teti Date: Wed, 25 Jul 2018 09:27:55 +0200 Subject: [PATCH 34/43] ARM: expose `rclass` and `dsp` target features - `dsp`: the subtarget supports the DSP (saturating arith. and such) instructions - `rclass`: target is a Cortex-R Both features are useful to support ARM MCUs on `coresimd`. Note: Cortex-R52 is the first Armv8-R with `neon` support --- src/librustc_codegen_llvm/llvm_util.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 87ee9ef5adb23..e941998098d00 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -85,6 +85,8 @@ unsafe fn configure_llvm(sess: &Session) { const ARM_WHITELIST: &[(&str, Option<&str>)] = &[ ("mclass", Some("arm_target_feature")), + ("rclass", Some("arm_target_feature")), + ("dsp", Some("arm_target_feature")), ("neon", Some("arm_target_feature")), ("v7", Some("arm_target_feature")), ("vfp2", Some("arm_target_feature")), From f653bf4fba40c6415b6f580c30fbcfe2e82cce62 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 25 Jul 2018 10:36:57 +0200 Subject: [PATCH 35/43] Improve readability in a few sorts --- src/librustc_driver/lib.rs | 5 +---- src/librustc_driver/profile/trace.rs | 5 ++--- src/librustc_errors/emitter.rs | 8 +++----- src/librustc_mir/monomorphize/mod.rs | 4 +--- src/librustc_mir/util/patch.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 6 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2100ceea22849..000025c49a698 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1229,10 +1229,7 @@ Available lint options: fn sort_lint_groups(lints: Vec<(&'static str, Vec, bool)>) -> Vec<(&'static str, Vec)> { let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect(); - lints.sort_by(|&(x, _): &(&'static str, Vec), - &(y, _): &(&'static str, Vec)| { - x.cmp(y) - }); + lints.sort_by_key(|ref l| l.0); lints } diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs index 5f10c56e8e214..4aaf5eb47f61c 100644 --- a/src/librustc_driver/profile/trace.rs +++ b/src/librustc_driver/profile/trace.rs @@ -202,14 +202,13 @@ fn compute_counts_rec(counts: &mut HashMap, traces: &Vec) { use rustc::util::common::duration_to_secs_str; - use std::cmp::Ordering; + use std::cmp::Reverse; let mut data = vec![]; for (ref cons, ref qm) in counts.iter() { data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())); }; - data.sort_by(|&(_,_,_,self1),&(_,_,_,self2)| - if self1 > self2 { Ordering::Less } else { Ordering::Greater } ); + data.sort_by_key(|&k| Reverse(k.3)); for (cons, count, dur_total, dur_self) in data { write!(count_file, "{}, {}, {}, {}\n", cons, count, diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index c9b6818d5c158..6bcf0d9eff6c5 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -22,7 +22,7 @@ use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::collections::HashMap; -use std::cmp::min; +use std::cmp::{min, Reverse}; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter}; use termcolor::{WriteColor, Color, Buffer}; use unicode_width; @@ -265,9 +265,7 @@ impl EmitterWriter { } // Find overlapping multiline annotations, put them at different depths - multiline_annotations.sort_by(|a, b| { - (a.1.line_start, a.1.line_end).cmp(&(b.1.line_start, b.1.line_end)) - }); + multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end)); for item in multiline_annotations.clone() { let ann = item.1; for item in multiline_annotations.iter_mut() { @@ -403,7 +401,7 @@ impl EmitterWriter { // otherwise the lines would end up needing to go over a message. let mut annotations = line.annotations.clone(); - annotations.sort_by(|a,b| b.start_col.cmp(&a.start_col)); + annotations.sort_by_key(|a| Reverse(a.start_col)); // First, figure out where each label will be positioned. // diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index bf544e5120cd8..e148bc3d9460c 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -29,9 +29,7 @@ pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mon (mono_item, mono_item.symbol_name(tcx)) }).collect(); - (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{ - sym1.cmp(sym2) - }); + (&mut symbols[..]).sort_by_key(|&sym| sym.1); for pair in (&symbols[..]).windows(2) { let sym1 = &pair[0].1; diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 21ff7eaa72d9d..c2a56adc18f5c 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -156,7 +156,7 @@ impl<'tcx> MirPatch<'tcx> { } let mut new_statements = self.new_statements; - new_statements.sort_by(|u,v| u.0.cmp(&v.0)); + new_statements.sort_by_key(|s| s.0); let mut delta = 0; let mut last_bb = START_BLOCK; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5193113d82c8a..60f8928255174 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1746,7 +1746,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &dyn AstConv<'gcx, 'tcx>, astconv.ast_region_to_region(r, None) }).collect(); - trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id())); + trait_bounds.sort_by_key(|t| t.def_id()); let implicitly_sized = if let SizedByDefault::Yes = sized_by_default { !is_unsized(astconv, ast_bounds, span) From ef5fba0067d35bf287476401671111c1f189e4bc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 25 Jul 2018 13:05:05 +0200 Subject: [PATCH 36/43] Hide some lints which are not quite right the way they are reported to the user --- src/librustc_mir/transform/const_prop.rs | 104 +++++++++++++++++--- src/test/ui/const-eval/const_prop_errors.rs | 24 +++++ 2 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/const-eval/const_prop_errors.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 94f96d46996d8..c8d4ce88f27c1 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -144,18 +144,100 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { }; let r = match f(self) { Ok(val) => Some(val), - Err(err) => { - match err.kind { + Err(error) => { + let (stacktrace, span) = self.ecx.generate_stacktrace(None); + let diagnostic = ConstEvalErr { span, error, stacktrace }; + use rustc::mir::interpret::EvalErrorKind::*; + match diagnostic.error.kind { // don't report these, they make no sense in a const prop context - EvalErrorKind::MachineError(_) => {}, - _ => { - let (frames, span) = self.ecx.generate_stacktrace(None); - let err = ConstEvalErr { - span, - error: err, - stacktrace: frames, - }; - err.report_as_lint( + | MachineError(_) + // at runtime these transformations might make sense + // FIXME: figure out the rules and start linting + | FunctionPointerTyMismatch(..) + // fine at runtime, might be a register address or sth + | ReadBytesAsPointer + // fine at runtime + | ReadForeignStatic + | Unimplemented(_) + // don't report const evaluator limits + | StackFrameLimitReached + | NoMirFor(..) + | InlineAsm + => {}, + + | InvalidMemoryAccess + | DanglingPointerDeref + | DoubleFree + | InvalidFunctionPointer + | InvalidBool + | InvalidDiscriminant + | PointerOutOfBounds { .. } + | InvalidNullPointerUsage + | MemoryLockViolation { .. } + | MemoryAcquireConflict { .. } + | ValidationFailure(..) + | InvalidMemoryLockRelease { .. } + | DeallocatedLockedMemory { .. } + | InvalidPointerMath + | ReadUndefBytes + | DeadLocal + | InvalidBoolOp(_) + | DerefFunctionPointer + | ExecuteMemory + | Intrinsic(..) + | InvalidChar(..) + | AbiViolation(_) + | AlignmentCheckFailed{..} + | CalledClosureAsFunction + | VtableForArgumentlessMethod + | ModifiedConstantMemory + | AssumptionNotHeld + // FIXME: should probably be removed and turned into a bug! call + | TypeNotPrimitive(_) + | ReallocatedWrongMemoryKind(_, _) + | DeallocatedWrongMemoryKind(_, _) + | ReallocateNonBasePtr + | DeallocateNonBasePtr + | IncorrectAllocationInformation(..) + | UnterminatedCString(_) + | HeapAllocZeroBytes + | HeapAllocNonPowerOfTwoAlignment(_) + | Unreachable + | ReadFromReturnPointer + | GeneratorResumedAfterReturn + | GeneratorResumedAfterPanic + | ReferencedConstant(_) + | InfiniteLoop + => { + // FIXME: report UB here + }, + + | OutOfTls + | TlsOutOfBounds + | PathNotFound(_) + => bug!("these should not be in rustc, but in miri's machine errors"), + + | Layout(_) + | UnimplementedTraitSelection + | TypeckError + | TooGeneric + | CheckMatchError + // these are just noise + => {}, + + // non deterministic + | ReadPointerAsBytes + // FIXME: implement + => {}, + + | Panic + | BoundsCheck{..} + | Overflow(_) + | OverflowNeg + | DivisionByZero + | RemainderByZero + => { + diagnostic.report_as_lint( self.ecx.tcx, "this expression will panic at runtime", lint_root, diff --git a/src/test/ui/const-eval/const_prop_errors.rs b/src/test/ui/const-eval/const_prop_errors.rs new file mode 100644 index 0000000000000..bea4fb76ed166 --- /dev/null +++ b/src/test/ui/const-eval/const_prop_errors.rs @@ -0,0 +1,24 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +pub trait Foo { + fn foo(self) -> u32; +} + +impl Foo for T { + fn foo(self) -> u32 { + fn bar() { loop {} } + bar:: as u32 + } +} + +fn main() {} From eacfd7252252fac66b9354cdd861f054cc678373 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sun, 22 Jul 2018 11:08:31 +0200 Subject: [PATCH 37/43] Clarify what a task is --- src/libcore/task/executor.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/libcore/task/executor.rs b/src/libcore/task/executor.rs index f1db5093e9880..affcbf464da22 100644 --- a/src/libcore/task/executor.rs +++ b/src/libcore/task/executor.rs @@ -17,21 +17,27 @@ use future::{FutureObj, LocalFutureObj}; /// A task executor. /// -/// A *task* is a `()`-producing async value that runs at the top level, and will -/// be `poll`ed until completion. It's also the unit at which wake-up -/// notifications occur. Executors, such as thread pools, allow tasks to be -/// spawned and are responsible for putting tasks onto ready queues when -/// they are woken up, and polling them when they are ready. +/// Futures are polled until completion by tasks, a kind of lightweight +/// "thread". A *task executor* is responsible for the creation of these tasks +/// and the coordination of their execution on real operating system threads. In +/// particular, whenever a task signals that it can make further progress via a +/// wake-up notification, it is the responsibility of the task executor to put +/// the task into a queue to continue executing it, i.e. polling the future in +/// it, later. pub trait Executor { - /// Spawn the given task, polling it until completion. + /// Spawns a new task with the given future. The future will be polled until + /// completion. /// /// # Errors /// /// The executor may be unable to spawn tasks, either because it has /// been shut down or is resource-constrained. - fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError>; + fn spawn_obj( + &mut self, + future: FutureObj<'static, ()>, + ) -> Result<(), SpawnObjError>; - /// Determine whether the executor is able to spawn new tasks. + /// Determines whether the executor is able to spawn new tasks. /// /// # Returns /// @@ -75,8 +81,8 @@ pub struct SpawnObjError { /// The kind of error pub kind: SpawnErrorKind, - /// The task for which spawning was attempted - pub task: FutureObj<'static, ()>, + /// The future for which spawning inside a task was attempted + pub future: FutureObj<'static, ()>, } /// The result of a failed spawn @@ -85,6 +91,6 @@ pub struct SpawnLocalObjError { /// The kind of error pub kind: SpawnErrorKind, - /// The task for which spawning was attempted - pub task: LocalFutureObj<'static, ()>, + /// The future for which spawning inside a task was attempted + pub future: LocalFutureObj<'static, ()>, } From be5b668a2e892c4c892986809b0a7d119980037a Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Wed, 25 Jul 2018 07:51:32 -0400 Subject: [PATCH 38/43] Place the ignore comments in the correct file for test issue-18804 Signed-off-by: Gabriel Smith --- src/test/run-pass/issue-18804/auxiliary/lib.rs | 3 --- src/test/run-pass/issue-18804/main.rs | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/run-pass/issue-18804/auxiliary/lib.rs b/src/test/run-pass/issue-18804/auxiliary/lib.rs index 43434766362ff..06d454b2c890a 100644 --- a/src/test/run-pass/issue-18804/auxiliary/lib.rs +++ b/src/test/run-pass/issue-18804/auxiliary/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-asmjs no weak symbol support -// ignore-emscripten no weak symbol support - #![crate_type = "rlib"] #![feature(linkage)] diff --git a/src/test/run-pass/issue-18804/main.rs b/src/test/run-pass/issue-18804/main.rs index de7967e8d3490..b5aa052034936 100644 --- a/src/test/run-pass/issue-18804/main.rs +++ b/src/test/run-pass/issue-18804/main.rs @@ -11,6 +11,9 @@ // Test for issue #18804, #[linkage] does not propagate thorugh generic // functions. Failure results in a linker error. +// ignore-asmjs no weak symbol support +// ignore-emscripten no weak symbol support + // aux-build:lib.rs extern crate lib; From abb704ec78bd69c0911c5f7711646d443da4c84d Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Thu, 26 Jul 2018 00:42:59 +0100 Subject: [PATCH 39/43] State default capacity for BufReader/BufWriter --- src/libstd/io/buffered.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 189569683a9cf..2babf508fdcc3 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -61,7 +61,8 @@ pub struct BufReader { } impl BufReader { - /// Creates a new `BufReader` with a default buffer capacity. + /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. /// /// # Examples /// @@ -454,7 +455,8 @@ pub struct BufWriter { pub struct IntoInnerError(W, Error); impl BufWriter { - /// Creates a new `BufWriter` with a default buffer capacity. + /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, + /// but may change in the future. /// /// # Examples /// From bce8a91f34e63a4ed87a6d6351bf67a82306afbd Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 25 Jul 2018 17:10:05 -0700 Subject: [PATCH 40/43] std::ops::Try impl for std::task::Poll --- src/libcore/task/poll.rs | 54 +++++++++++++++++++++++++++++++++++ src/test/ui/try-poll.rs | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 src/test/ui/try-poll.rs diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs index 10c954f0e80ec..fb027efc6dca0 100644 --- a/src/libcore/task/poll.rs +++ b/src/libcore/task/poll.rs @@ -12,6 +12,9 @@ reason = "futures in libcore are unstable", issue = "50547")] +use ops::Try; +use result::Result; + /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] @@ -39,6 +42,7 @@ impl Poll { } /// Returns whether this is `Poll::Ready` + #[inline] pub fn is_ready(&self) -> bool { match *self { Poll::Ready(_) => true, @@ -47,6 +51,7 @@ impl Poll { } /// Returns whether this is `Poll::Pending` + #[inline] pub fn is_pending(&self) -> bool { !self.is_ready() } @@ -81,3 +86,52 @@ impl From for Poll { Poll::Ready(t) } } + +impl Try for Poll> { + type Ok = Poll; + type Error = E; + + #[inline] + fn into_result(self) -> Result { + match self { + Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)), + Poll::Ready(Err(e)) => Err(e), + Poll::Pending => Ok(Poll::Pending), + } + } + + #[inline] + fn from_error(e: Self::Error) -> Self { + Poll::Ready(Err(e)) + } + + #[inline] + fn from_ok(x: Self::Ok) -> Self { + x.map(Ok) + } +} + +impl Try for Poll>> { + type Ok = Poll>; + type Error = E; + + #[inline] + fn into_result(self) -> Result { + match self { + Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))), + Poll::Ready(Some(Err(e))) => Err(e), + Poll::Ready(None) => Ok(Poll::Ready(None)), + Poll::Pending => Ok(Poll::Pending), + } + } + + #[inline] + fn from_error(e: Self::Error) -> Self { + Poll::Ready(Some(Err(e))) + } + + #[inline] + fn from_ok(x: Self::Ok) -> Self { + x.map(|x| x.map(Ok)) + } +} diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-poll.rs new file mode 100644 index 0000000000000..0cb058c2b0b6e --- /dev/null +++ b/src/test/ui/try-poll.rs @@ -0,0 +1,61 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![allow(dead_code, unused)] +#![feature(futures_api)] + +use std::task::Poll; + +struct K; +struct E; + +fn as_result() -> Result<(), E> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Ok(()) +} + +fn as_poll_result() -> Poll> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Poll::Ready(Ok(())) +} + +fn as_poll_option_result() -> Poll>> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Poll::Ready(Some(Ok(()))) +} + +fn main() { +} From f069a57bb1fb4f4aae4e42a6ee75ad277bcf9f7f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Jul 2018 18:02:03 -0700 Subject: [PATCH 41/43] rustc: Register crates under their real names Whenever we register a crate into the crate store, make sure to use the real name mentioned in the metadata instead of the name mentioned in the `extern crate` statement, as the statement can be wrong! Closes #51796 --- src/librustc_metadata/creader.rs | 7 +++---- .../extern-flag-rename-transitive/Makefile | 7 +++++++ .../extern-flag-rename-transitive/bar.rs | 13 +++++++++++++ .../extern-flag-rename-transitive/baz.rs | 14 ++++++++++++++ .../extern-flag-rename-transitive/foo.rs | 11 +++++++++++ 5 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile create mode 100644 src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 1e227b8a1a659..f434da3f88d6c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -188,13 +188,12 @@ impl<'a> CrateLoader<'a> { fn register_crate(&mut self, root: &Option, ident: Symbol, - name: Symbol, span: Span, lib: Library, dep_kind: DepKind) -> (CrateNum, Lrc) { - info!("register crate `extern crate {} as {}`", name, ident); let crate_root = lib.metadata.get_root(); + info!("register crate `extern crate {} as {}`", crate_root.name, ident); self.verify_no_symbol_conflicts(span, &crate_root); // Claim this crate number and cache it @@ -233,7 +232,7 @@ impl<'a> CrateLoader<'a> { .collect(); let cmeta = cstore::CrateMetadata { - name, + name: crate_root.name, extern_crate: Lock::new(None), def_path_table: Lrc::new(def_path_table), trait_impls, @@ -328,7 +327,7 @@ impl<'a> CrateLoader<'a> { (cnum, data) } LoadResult::Loaded(library) => { - self.register_crate(root, ident, name, span, library, dep_kind) + self.register_crate(root, ident, span, library, dep_kind) } } } diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile b/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile new file mode 100644 index 0000000000000..4354209a72202 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(RUSTC) baz.rs --extern a=$(TMPDIR)/libfoo.rlib + diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs new file mode 100644 index 0000000000000..a14f3ba05b066 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/bar.rs @@ -0,0 +1,13 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate foo; diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs new file mode 100644 index 0000000000000..a96c9f61c666c --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/baz.rs @@ -0,0 +1,14 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate a; +extern crate bar; diff --git a/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs b/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs new file mode 100644 index 0000000000000..b18ce024718f4 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-rename-transitive/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] From 051eddd9a9067dcbdccef6bfd86301453bae42ad Mon Sep 17 00:00:00 2001 From: Petr Sumbera Date: Thu, 26 Jul 2018 03:58:00 -0700 Subject: [PATCH 42/43] sparc ABI issue - structure returning from function is returned in 64bit registers Fixes: #52638 --- src/librustc_target/abi/call/sparc64.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc_target/abi/call/sparc64.rs b/src/librustc_target/abi/call/sparc64.rs index 987f56e6f9851..a58aebc2ff063 100644 --- a/src/librustc_target/abi/call/sparc64.rs +++ b/src/librustc_target/abi/call/sparc64.rs @@ -57,16 +57,7 @@ fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>) let size = ret.layout.size; let bits = size.bits(); if bits <= 256 { - let unit = if bits <= 8 { - Reg::i8() - } else if bits <= 16 { - Reg::i16() - } else if bits <= 32 { - Reg::i32() - } else { - Reg::i64() - }; - + let unit = Reg::i64(); ret.cast_to(Uniform { unit, total: size From cc2bd71269f9c54fed3849141e29204a5f353693 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 26 Jul 2018 17:55:25 +0300 Subject: [PATCH 43/43] Add a test for sparc64 ABI issue --- src/test/codegen/sparc-struct-abi.rs | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/test/codegen/sparc-struct-abi.rs diff --git a/src/test/codegen/sparc-struct-abi.rs b/src/test/codegen/sparc-struct-abi.rs new file mode 100644 index 0000000000000..d3b7a5cd59882 --- /dev/null +++ b/src/test/codegen/sparc-struct-abi.rs @@ -0,0 +1,36 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Checks that we correctly codegen extern "C" functions returning structs. +// See issue #52638. + +// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + +#[repr(C)] +pub struct Bool { + b: bool, +} + +// CHECK: define i64 @structbool() +// CHECK-NEXT: start: +// CHECK-NEXT: ret i64 72057594037927936 +#[no_mangle] +pub extern "C" fn structbool() -> Bool { + Bool { b: true } +}