ENV TARGETS=$TARGETS,thumbv7em-none-eabi
ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
-# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271
-# get fixed and cc update
ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
- CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
- CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \
- CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" \
- CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \
- CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft"
+ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc
ENV RUST_CONFIGURE_ARGS \
--musl-root-armv5te=/musl-armv5te \
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;
}
}
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<E> Executor for Box<E>
+ 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<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
fn from(boxed: PinBox<F>) -> Self {
/// 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
///
/// 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
/// 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, ()>,
}
style: Option<usize>,
/// 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)>,
}
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))
}
}
'}' => {
curarg: 0,
style,
seen_newlines: 0,
+ arg_places: vec![],
}
}
/// 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<usize> {
self.ws();
let raw = self.style.unwrap_or(0);
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);
} else {
self.err(msg, format!("expected `{:?}`", c), pos, pos);
}
+ None
}
}
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 (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("")
+ .filter(|s| !s.is_empty())
+ .collect::<Vec<_>>()
+ .join(", ");
+ err.span_suggestion_with_applicability(
+ found_span,
+ &format!(
+ "consider changing the closure to take and ignore the expected argument{}",
+ if expected_args.len() < 2 {
+ ""
+ } else {
+ "s"
+ }
+ ),
+ format!("|{}|", underscores),
+ Applicability::MachineApplicable,
+ );
+ }
+
if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
if fields.len() == expected_args.len() {
let sugg = fields.iter()
}
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); }
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) {
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");
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
// 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);
}
}
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 {
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};
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);
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 {
- // 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)
};
+ 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);
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 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
// 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 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
g
}
+fn check_and_apply_linkage<'tcx>(
+ cx: &CodegenCx<'_, 'tcx>,
+ attrs: &CodegenFnAttrs,
+ ty: Ty<'tcx>,
+ sym: LocalInternedString,
+ span: Option<Span>
+) -> 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,
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")),
fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
-> Vec<(&'static str, Vec<lint::LintId>)> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
- lints.sort_by(|&(x, _): &(&'static str, Vec<lint::LintId>),
- &(y, _): &(&'static str, Vec<lint::LintId>)| {
- x.cmp(y)
- });
+ lints.sort_by_key(|ref l| l.0);
lints
}
pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
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,
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;
}
// 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() {
// 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.
//
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;
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,
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,
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<ScopeTree>,
- 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<ScopeTree>,
- 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,
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
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<ScopeTree>,
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
(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;
}
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;
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)
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, 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 {
/// still existed in this phase of processing.
/// Used only for `all_pieces_simple` tracking in `build_piece`.
curarg: usize,
- /// Keep track of invalid references to positional arguments
- invalid_refs: Vec<usize>,
+ /// Current piece being evaluated, used for error reporting.
+ curpiece: usize,
+ /// Keep track of invalid references to positional arguments.
+ invalid_refs: Vec<(usize, usize)>,
+ /// Spans of all the formatting arguments, in order.
+ arg_spans: Vec<Span>,
+ /// 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
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;
}
};
let ty = Placeholder(arg.format.ty.to_string());
self.verify_arg_type(pos, ty);
+ self.curpiece += 1;
}
}
}
/// format string.
fn report_invalid_references(&self, numbered_position_args: bool) {
let mut e;
- let mut refs: Vec<String> = self.invalid_refs
- .iter()
- .map(|r| r.to_string())
- .collect();
+ 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()
+ .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(self.fmtsp,
- &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() {
- 1 => format!("argument {}", refs.pop().unwrap()),
- _ => format!("arguments {head} and {tail}",
- tail=refs.pop().unwrap(),
- head=refs.join(", "))
+ let (arg_list, mut sp) = match refs.len() {
+ 1 => {
+ 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<String> = refs.iter().map(|(s, _)| s.to_owned()).collect();
+ let reg = refs.pop().unwrap();
+ (
+ format!(
+ "arguments {head} and {tail}",
+ tail = reg,
+ head = refs.join(", ")
+ ),
+ pos,
+ )
+ }
};
+ if !self.is_literal {
+ sp = MultiSpan::from_span(self.fmtsp);
+ }
- 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()));
+ arg_list,
+ self.describe_num_args()));
e.note("positional arguments are zero-based");
};
match arg {
Exact(arg) => {
if self.args.len() <= arg {
- self.invalid_refs.push(arg);
+ self.invalid_refs.push((arg, self.curpiece));
return;
}
match ty {
Some(e) => *e,
None => {
let msg = format!("there is no argument named `{}`", name);
- self.ecx.span_err(self.fmtsp, &msg[..]);
+ 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;
}
};
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),
+ ],
+ ))
}
}
}
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"
}
}
-pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt,
- mut sp: Span,
- tts: &[tokenstream::TokenTree])
- -> Box<dyn base::MacResult + 'cx> {
+pub fn expand_format_args_nl<'cx>(
+ ecx: &'cx mut ExtCtxt,
+ mut sp: Span,
+ tts: &[tokenstream::TokenTree],
+) -> Box<dyn base::MacResult + 'cx> {
//if !ecx.ecfg.enable_allow_internal_unstable() {
// For some reason, the only one that actually works for `println` is the first check
let sugg_fmt = match args.len() {
0 => "{}".to_string(),
_ => format!("{}{{}}", "{} ".repeat(args.len())),
-
};
err.span_suggestion(
fmt_sp.shrink_to_lo(),
);
err.emit();
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 {
arg_unique_types,
names,
curarg: 0,
+ curpiece: 0,
arg_index_map: Vec::new(),
count_args: Vec::new(),
count_positions: HashMap::new(),
macsp,
fmtsp: fmt.span,
invalid_refs: Vec::new(),
+ arg_spans: Vec::new(),
+ is_literal,
};
let fmt_str = &*fmt.node.0.as_str();
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);
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 {
let mut diag = cx.ecx.struct_span_err(
errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
- "multiple unused formatting arguments"
+ "multiple unused formatting arguments",
);
- diag.span_label(cx.fmtsp, "multiple missing formatting arguments");
+ diag.span_label(cx.fmtsp, "multiple missing formatting specifiers");
diag
}
};
+ // 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;
// 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;
+ let mut suggestions = vec![];
for sub in foreign::$kind::iter_subs(fmt_str) {
let trn = match sub.translate() {
Some(trn) => trn,
None => continue,
};
+ let pos = sub.position();
let sub = String::from(sub.as_str());
if explained.contains(&sub) {
continue;
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 {
" formatting not supported; see the documentation for `std::fmt`",
));
}
+ if suggestions.len() > 0 {
+ diag.multipart_suggestion(
+ "format specifiers use curly braces",
+ suggestions,
+ );
+ }
}};
}
check_foreign!(shell);
}
}
+ if !found_foreign && errs_len == 1 {
+ diag.span_label(cx.fmtsp, "formatting specifier missing");
+ }
diag.emit();
}
/// 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,
}
}
+ 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
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> {
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<Self::Item> {
- 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)
}
_ => {/* fall-through */},
}
- Cur::new_at_start(&s[start..])
+ Cur::new_at(&s[..], start)
};
// This is meant to be a translation of the following regex:
precision: None,
length: None,
type_: at.slice_between(next).unwrap(),
+ position: (start.at, next.at),
}),
next.slice_after()
));
drop(next);
end = at;
+ let position = (start.at, end.at);
let f = Format {
span: start.slice_between(end).unwrap(),
precision,
length,
type_,
+ position,
};
Some((Substitution::Format(f), end.slice_after()))
}
($in_:expr, {
$param:expr, $flags:expr,
$width:expr, $prec:expr, $len:expr, $type_:expr,
+ $pos:expr,
}) => {
assert_eq!(
pns(concat!($in_, "!")),
precision: $prec,
length: $len,
type_: $type_,
+ position: $pos,
}),
"!"
))
}
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]
}
}
+ pub fn position(&self) -> Option<(usize, usize)> {
+ match *self {
+ _ => None,
+ }
+ }
+
pub fn translate(&self) -> Option<String> {
match *self {
Substitution::Ordinal(n) => Some(format!("{{{}}}", n)),
pub struct StrCursor<'a> {
s: &'a str,
- at: usize,
+ pub at: usize,
}
impl<'a> StrCursor<'a> {
}
}
+ pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> {
+ StrCursor {
+ s,
+ at,
+ }
+ }
+
pub fn at_next_cp(mut self) -> Option<StrCursor<'a>> {
match self.try_seek_right_cp() {
true => Some(self),
-Subproject commit b9de11ab43090c71ff7ab159a479394df1f968ab
+Subproject commit 05c2f61c384e2097a3a4c648344114fc4ac983be
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- // bad arguments to the format! call
-
- // bad number of arguments, see #44954 (originally #15780)
-
- format!("{}");
- //~^ ERROR: 1 positional argument in format string, but no arguments were given
-
- format!("{1}", 1);
- //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
- //~^^ ERROR: argument never used
-
- format!("{} {}");
- //~^ ERROR: 2 positional arguments in format string, but no arguments were given
-
- format!("{0} {1}", 1);
- //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
-
- format!("{0} {1} {2}", 1, 2);
- //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
-
- format!("{} {value} {} {}", 1, value=2);
- //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
- format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
- //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
-
- format!("{} {foo} {} {bar} {}", 1, 2, 3);
- //~^ ERROR: there is no argument named `foo`
- //~^^ ERROR: there is no argument named `bar`
-
- format!("{foo}"); //~ ERROR: no argument named `foo`
- format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
- format!("{}", 1, 2); //~ ERROR: argument never used
- format!("{1}", 1, 2); //~ ERROR: argument never used
- format!("{}", 1, foo=2); //~ ERROR: named argument never used
- format!("{foo}", 1, foo=2); //~ ERROR: argument never used
- format!("", foo=2); //~ ERROR: named argument never used
- format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
-
- format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
- format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
-
- // bad named arguments, #35082
-
- format!("{valuea} {valueb}", valuea=5, valuec=7);
- //~^ ERROR there is no argument named `valueb`
- //~^^ ERROR named argument never used
-
- // bad syntax of the format string
-
- format!("{"); //~ ERROR: expected `'}'` but string was terminated
-
- format!("foo } bar"); //~ ERROR: unmatched `}` found
- format!("foo }"); //~ ERROR: unmatched `}` found
-
- format!("foo %s baz", "bar"); //~ ERROR: argument never used
-}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+#![feature(linkage)]
+
+pub fn foo<T>() -> *const() {
+ extern {
+ #[linkage = "extern_weak"]
+ static FOO: *const();
+ }
+ unsafe { FOO }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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;
+
+fn main() {
+ lib::foo::<i32>();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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() { }
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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 => {}
+ _ => {}
+ }
+}
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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<T, F>(x: T, f: F)
+ where T: for<'a> Foo<'a>,
+ F: for<'a> Fn(<T as Foo<'a>>::Bar)
+{
+ f(x.foo());
+}
+
+pub fn catalyst(x: &i32) {
+ broken(x, |_| {})
+}
+
+pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
+ uncallable(x, |y| f(y));
+}
+
+fn main() { }
+
| ^^^^^^^^^^^^^^^^ 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...
| ^^^^^^^^^^^^^^^^ 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
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
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
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
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
| ^^^^^^^^^^^^^ 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
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
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
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
| ^^ 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
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ // bad arguments to the format! call
+
+ // bad number of arguments, see #44954 (originally #15780)
+
+ format!("{}");
+ //~^ ERROR: 1 positional argument in format string, but no arguments were given
+
+ format!("{1}", 1);
+ //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+ //~^^ ERROR: argument never used
+
+ format!("{} {}");
+ //~^ ERROR: 2 positional arguments in format string, but no arguments were given
+
+ format!("{0} {1}", 1);
+ //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+
+ format!("{0} {1} {2}", 1, 2);
+ //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+
+ format!("{} {value} {} {}", 1, value=2);
+ //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+ format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+ //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+
+ format!("{} {foo} {} {bar} {}", 1, 2, 3);
+ //~^ ERROR: there is no argument named `foo`
+ //~^^ ERROR: there is no argument named `bar`
+
+ format!("{foo}"); //~ ERROR: no argument named `foo`
+ format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
+ format!("{}", 1, 2); //~ ERROR: argument never used
+ format!("{1}", 1, 2); //~ ERROR: argument never used
+ format!("{}", 1, foo=2); //~ ERROR: named argument never used
+ format!("{foo}", 1, foo=2); //~ ERROR: argument never used
+ format!("", foo=2); //~ ERROR: named argument never used
+ format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
+
+ format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
+ format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
+
+ // bad named arguments, #35082
+
+ format!("{valuea} {valueb}", valuea=5, valuec=7);
+ //~^ ERROR there is no argument named `valueb`
+ //~^^ ERROR named argument never used
+
+ // bad syntax of the format string
+
+ format!("{"); //~ ERROR: expected `'}'` but string was terminated
+
+ format!("foo } bar"); //~ ERROR: unmatched `}` found
+ format!("foo }"); //~ ERROR: unmatched `}` found
+
+ format!("foo %s baz", "bar"); //~ ERROR: argument never used
+
+ format!(r##"
+
+ {foo}
+
+ "##);
+ //~^^^ ERROR: there is no argument named `foo`
+}
--- /dev/null
+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);
+ | ----- ^
+ | |
+ | formatting specifier missing
+
+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: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: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: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:38
+ |
+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:17
+ |
+LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
+ | ^^^^^
+
+error: there is no argument named `bar`
+ --> $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:14
+ |
+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 specifiers
+
+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
+ |
+LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
+ | ------- ^ ^
+ | |
+ | multiple missing formatting specifiers
+
+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:23
+ |
+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);
+ | ------------------- ^
+ | |
+ | formatting specifier missing
+
+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: format specifiers use curly braces: `{}`
+ |
+ = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: there is no argument named `foo`
+ --> $DIR/ifmt-bad-arg.rs:70:9
+ |
+LL | {foo}
+ | ^^^^^
+
+error: aborting due to 27 previous errors
+
| ^^^ 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
--- /dev/null
+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`.
| ^^^^ 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...
| ^^^^ 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...
println!("{}", a);
});
}
-//[mir]~^ borrowed value only lives until here
+//[mir]~^ `FOO` dropped here while still borrowed
//[ast]~^^ temporary value only lives until here
| ^^ 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...
| ^^ 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let 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;
+ <typeof(q)>::N //~ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516]
+}
+
--- /dev/null
+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 | <typeof(q)>::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 | <typeof(q)>::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`.
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ |
+}
+//~^ ERROR expected `|`, found `}`
+|
+//~^ ERROR expected item, found `|`
+
--- /dev/null
+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
+
| ^^^^^ 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
| ^^ 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...
LL | | };
| | -
| | |
- | |_____borrowed value only lives until here
+ | |_____`z` dropped here while still borrowed
| borrow later used here
error: aborting due to 2 previous errors
| ^^ 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...
| ------- borrow later used here
...
LL | }
- | - borrowed value only lives until here
+ | - `line` dropped here while still borrowed
error: aborting due to previous error
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.
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 `{}`
= note: printf formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+ |
+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 use curly braces: `{0:1$.2$}`
|
- = help: `%1$*2$.*3$f` should be written as `{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
+ |
+ = note: printf formatting not supported; see the documentation for `std::fmt`
+help: format specifiers use curly braces
+ |
+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
- | ^^^
+ | ------- ^^^
+ | |
+ | formatting specifier missing
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
| ^^^^^
= 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
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,
--> $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
|
LL | println!("Some more $STUFF",
- | ------------------ multiple missing formatting arguments
+ | ------------------ multiple missing formatting specifiers
LL | "woo!", //~ ERROR multiple unused formatting arguments
| ^^^^^^
LL | STUFF=
| ^^^^^^^ -- takes 0 arguments
| |
| expected closure that takes 2 arguments
+help: consider changing 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
|
LL | fn f<F: Fn<usize>>(_: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing 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
LL | | });
| |_____-- borrow later used here
| |
- | borrowed value only lives until here
+ | `v` dropped here while still borrowed
error: aborting due to previous error
| ^^ 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
| ^^ 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
| ^^ 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
| |_________^ 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
| ^^^^^^^^^ 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
| ^^ 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...
| ^^^^^ 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
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
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...
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
| ^^^^^^ 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
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
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
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
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
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
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
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
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
| ^^ 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
LL | | };
| | -
| | |
- | |_____borrowed value only lives until here
+ | |_____`tmp0` dropped here while still borrowed
| borrow later used here
error: aborting due to previous error
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
| borrow later used here
...
LL | }
- | - borrowed value only lives until here
+ | - `z` dropped here while still borrowed
error: aborting due to 4 previous errors
| ^^^ 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
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
| ^^ 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
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
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
| ^^ 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
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
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
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
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
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
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
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
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