Auto merge of #93173 - matthiaskrgr:rollup-49bj7ta, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #91965 (Add more granular `--exclude` in `x.py`)
 - #92467 (Ensure that early-bound function lifetimes are always 'local')
 - #92586 (Set the allocation MIN_ALIGN for espidf to 4.)
 - #92835 (Improve error message for key="value" cfg arguments.)
 - #92843 (Improve string concatenation suggestion)
 - #92963 (Implement tuple array diagnostic)
 - #93046 (Use let_else in even more places)
 - #93109 (Improve `Arc` and `Rc` documentation)
 - #93134 (delete `Stdin::split` forwarder)
 - #93139 (rustdoc: fix overflow-wrap for table layouts)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-01-21 23:52:58 +00:00
commit ecf72996ed
77 changed files with 644 additions and 510 deletions

View File

@ -180,8 +180,9 @@ pub enum RegionClassification {
/// anywhere. There is only one, `'static`.
Global,
/// An **external** region is only relevant for closures. In that
/// case, it refers to regions that are free in the closure type
/// An **external** region is only relevant for
/// closures, generators, and inline consts. In that
/// case, it refers to regions that are free in the type
/// -- basically, something bound in the surrounding context.
///
/// Consider this example:
@ -198,8 +199,8 @@ pub enum RegionClassification {
/// Here, the lifetimes `'a` and `'b` would be **external** to the
/// closure.
///
/// If we are not analyzing a closure, there are no external
/// lifetimes.
/// If we are not analyzing a closure/generator/inline-const,
/// there are no external lifetimes.
External,
/// A **local** lifetime is one about which we know the full set
@ -424,22 +425,30 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
// If this is a closure or generator, then the late-bound regions from the enclosing
// function are actually external regions to us. For example, here, 'a is not local
// to the closure c (although it is local to the fn foo):
// fn foo<'a>() {
// let c = || { let x: &'a u32 = ...; }
// }
if self.mir_def.did.to_def_id() != typeck_root_def_id {
// If this is is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
first_extern_index
} else {
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
// function are actually external regions to us. For example, here, 'a is not local
// to the closure c (although it is local to the fn foo):
// fn foo<'a>() {
// let c = || { let x: &'a u32 = ...; }
// }
self.infcx
.replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
}
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
.replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
// Any regions created during the execution of `defining_ty` or during the above
// late-bound region replacement are all considered 'extern' regions
self.infcx.num_region_vars()
};
// "Liberate" the late-bound regions. These correspond to
// "local" free regions.
let first_local_index = self.infcx.num_region_vars();
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
FR,
self.mir_def.did,

View File

@ -1493,7 +1493,7 @@ fn generator_layout_and_saved_local_names<'tcx>(
let state_arg = mir::Local::new(1);
for var in &body.var_debug_info {
let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue };
let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
if place.local != state_arg {
continue;
}

View File

@ -7,6 +7,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(let_else)]
#![feature(extern_types)]
#![feature(nll)]
#![recursion_limit = "256"]

View File

@ -124,7 +124,16 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
Err(errs) => errs.into_iter().for_each(|mut err| err.cancel()),
}
error!(r#"expected `key` or `key="value"`"#);
// If the user tried to use a key="value" flag, but is missing the quotes, provide
// a hint about how to resolve this.
if s.contains("=") && !s.contains("=\"") && !s.ends_with("\"") {
error!(concat!(
r#"expected `key` or `key="value"`, ensure escaping is appropriate"#,
r#" for your shell, try 'key="value"' or key=\"value\""#
));
} else {
error!(r#"expected `key` or `key="value"`"#);
}
})
.collect::<CrateConfig>();
cfg.into_iter().map(|(a, b)| (a.to_string(), b.map(|b| b.to_string()))).collect()

View File

@ -1,5 +1,6 @@
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(let_else)]
#![feature(internal_output_capture)]
#![feature(thread_spawn_unchecked)]
#![feature(nll)]

View File

@ -717,57 +717,57 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
}
fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool {
if let ast::FnRetTy::Ty(ref ty) = ret_ty {
fn involves_impl_trait(ty: &ast::Ty) -> bool {
match ty.kind {
ast::TyKind::ImplTrait(..) => true,
ast::TyKind::Slice(ref subty)
| ast::TyKind::Array(ref subty, _)
| ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. })
| ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. })
| ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
ast::TyKind::Path(_, ref path) => {
path.segments.iter().any(|seg| match seg.args.as_deref() {
None => false,
Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
data.args.iter().any(|arg| match arg {
ast::AngleBracketedArg::Arg(arg) => match arg {
ast::GenericArg::Type(ty) => involves_impl_trait(ty),
ast::GenericArg::Lifetime(_)
| ast::GenericArg::Const(_) => false,
},
ast::AngleBracketedArg::Constraint(c) => match c.kind {
ast::AssocConstraintKind::Bound { .. } => true,
ast::AssocConstraintKind::Equality { ref term } => {
match term {
Term::Ty(ty) => involves_impl_trait(ty),
// FIXME(...): This should check if the constant
// involves a trait impl, but for now ignore.
Term::Const(_) => false,
}
let ast::FnRetTy::Ty(ref ty) = ret_ty else {
return false;
};
fn involves_impl_trait(ty: &ast::Ty) -> bool {
match ty.kind {
ast::TyKind::ImplTrait(..) => true,
ast::TyKind::Slice(ref subty)
| ast::TyKind::Array(ref subty, _)
| ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. })
| ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. })
| ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
ast::TyKind::Path(_, ref path) => {
path.segments.iter().any(|seg| match seg.args.as_deref() {
None => false,
Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
data.args.iter().any(|arg| match arg {
ast::AngleBracketedArg::Arg(arg) => match arg {
ast::GenericArg::Type(ty) => involves_impl_trait(ty),
ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => {
false
}
},
ast::AngleBracketedArg::Constraint(c) => match c.kind {
ast::AssocConstraintKind::Bound { .. } => true,
ast::AssocConstraintKind::Equality { ref term } => {
match term {
Term::Ty(ty) => involves_impl_trait(ty),
// FIXME(...): This should check if the constant
// involves a trait impl, but for now ignore.
Term::Const(_) => false,
}
},
})
}
Some(&ast::GenericArgs::Parenthesized(ref data)) => {
any_involves_impl_trait(data.inputs.iter())
|| ReplaceBodyWithLoop::should_ignore_fn(&data.output)
}
})
}
_ => false,
}
},
})
}
Some(&ast::GenericArgs::Parenthesized(ref data)) => {
any_involves_impl_trait(data.inputs.iter())
|| ReplaceBodyWithLoop::should_ignore_fn(&data.output)
}
})
}
_ => false,
}
fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
it.any(|subty| involves_impl_trait(subty))
}
involves_impl_trait(ty)
} else {
false
}
fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
it.any(|subty| involves_impl_trait(subty))
}
involves_impl_trait(ty)
}
fn is_sig_const(sig: &ast::FnSig) -> bool {

View File

@ -1347,23 +1347,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut otherwise = None;
for match_pair in match_pairs {
if let PatKind::Or { ref pats } = *match_pair.pattern.kind {
let or_span = match_pair.pattern.span;
let place = match_pair.place;
first_candidate.visit_leaves(|leaf_candidate| {
self.test_or_pattern(
leaf_candidate,
&mut otherwise,
pats,
or_span,
place.clone(),
fake_borrows,
);
});
} else {
let PatKind::Or { ref pats } = &*match_pair.pattern.kind else {
bug!("Or-patterns should have been sorted to the end");
}
};
let or_span = match_pair.pattern.span;
let place = match_pair.place;
first_candidate.visit_leaves(|leaf_candidate| {
self.test_or_pattern(
leaf_candidate,
&mut otherwise,
pats,
or_span,
place.clone(),
fake_borrows,
);
});
}
let remainder_start = otherwise.unwrap_or_else(|| self.cfg.start_new_block());

View File

@ -88,11 +88,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
switch_ty: Ty<'tcx>,
options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
) -> bool {
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
Some(match_pair) => match_pair,
_ => {
return false;
}
let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else {
return false;
};
match *match_pair.pattern.kind {

View File

@ -1171,9 +1171,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
ident: Symbol,
kind: &AssocItemKind,
) -> Option<Symbol> {
let module = if let Some((module, _)) = self.current_trait_ref {
module
} else {
let Some((module, _)) = &self.current_trait_ref else {
return None;
};
if ident == kw::Underscore {

View File

@ -1000,46 +1000,45 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// `fn foo<'a>() -> MyAnonTy<'a> { ... }`
// ^ ^this gets resolved in the current scope
for lifetime in lifetimes {
if let hir::GenericArg::Lifetime(lifetime) = lifetime {
self.visit_lifetime(lifetime);
let hir::GenericArg::Lifetime(lifetime) = lifetime else {
continue
};
self.visit_lifetime(lifetime);
// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
// and ban them. Type variables instantiated inside binders aren't
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
if let Some(Region::LateBound(_, _, def_id, _)) = def {
if let Some(def_id) = def_id.as_local() {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.tcx.hir().get_parent_node(hir_id);
// FIXME(cjgillot) Can this check be replaced by
// `let parent_is_item = parent_id.is_owner();`?
let parent_is_item =
if let Some(parent_def_id) = parent_id.as_owner() {
matches!(
self.tcx.hir().krate().owners.get(parent_def_id),
Some(Some(_)),
)
} else {
false
};
// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
// and ban them. Type variables instantiated inside binders aren't
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
let Some(Region::LateBound(_, _, def_id, _)) = def else {
continue
};
let Some(def_id) = def_id.as_local() else {
continue
};
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.tcx.hir().get_parent_node(hir_id);
// FIXME(cjgillot) Can this check be replaced by
// `let parent_is_item = parent_id.is_owner();`?
let parent_is_item = if let Some(parent_def_id) = parent_id.as_owner() {
matches!(self.tcx.hir().krate().owners.get(parent_def_id), Some(Some(_)),)
} else {
false
};
if !parent_is_item {
if !self.trait_definition_only {
struct_span_err!(
self.tcx.sess,
lifetime.span,
E0657,
"`impl Trait` can only capture lifetimes \
bound at the fn or impl level"
)
.emit();
}
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
}
if !parent_is_item {
if !self.trait_definition_only {
struct_span_err!(
self.tcx.sess,
lifetime.span,
E0657,
"`impl Trait` can only capture lifetimes \
bound at the fn or impl level"
)
.emit();
}
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
}

View File

@ -840,39 +840,38 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
};
for refs_remaining in 0..refs_number {
if let ty::Ref(_, inner_ty, _) = suggested_ty.kind() {
suggested_ty = inner_ty;
let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else {
break;
};
suggested_ty = inner_ty;
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
trait_ref,
suggested_ty,
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env,
trait_ref,
suggested_ty,
);
if self.predicate_may_hold(&new_obligation) {
let sp = self
.tcx
.sess
.source_map()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
let remove_refs = refs_remaining + 1;
let msg = if remove_refs == 1 {
"consider removing the leading `&`-reference".to_string()
} else {
format!("consider removing {} leading `&`-references", remove_refs)
};
err.span_suggestion_short(
sp,
&msg,
String::new(),
Applicability::MachineApplicable,
);
if self.predicate_may_hold(&new_obligation) {
let sp = self
.tcx
.sess
.source_map()
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
let remove_refs = refs_remaining + 1;
let msg = if remove_refs == 1 {
"consider removing the leading `&`-reference".to_string()
} else {
format!("consider removing {} leading `&`-references", remove_refs)
};
err.span_suggestion_short(
sp,
&msg,
String::new(),
Applicability::MachineApplicable,
);
break;
}
} else {
break;
}
}

View File

@ -307,6 +307,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
/// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the
/// likely intention is to create an array containing tuples.
fn maybe_suggest_bad_array_definition(
&self,
err: &mut DiagnosticBuilder<'a>,
call_expr: &'tcx hir::Expr<'tcx>,
callee_expr: &'tcx hir::Expr<'tcx>,
) -> bool {
let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id);
let parent_node = self.tcx.hir().get(hir_id);
if let (
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
hir::ExprKind::Tup(exp),
hir::ExprKind::Call(_, args),
) = (parent_node, &callee_expr.kind, &call_expr.kind)
{
if args.len() == exp.len() {
let start = callee_expr.span.shrink_to_hi();
err.span_suggestion(
start,
"consider separating array elements with a comma",
",".to_string(),
Applicability::MaybeIncorrect,
);
return true;
}
}
false
}
fn confirm_builtin_call(
&self,
call_expr: &'tcx hir::Expr<'tcx>,
@ -422,7 +452,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => Res::Err,
};
err.span_label(call_expr.span, "call expression requires function");
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
err.span_label(call_expr.span, "call expression requires function");
}
if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string();

View File

@ -549,16 +549,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
is_assign: IsAssign,
op: hir::BinOp,
) -> bool {
let source_map = self.tcx.sess.source_map();
let remove_borrow_msg = "String concatenation appends the string on the right to the \
string on the left and may require reallocation. This \
requires ownership of the string on the left";
let msg = "`to_owned()` can be used to create an owned `String` \
from a string reference. String concatenation \
appends the string on the right to the string \
on the left and may require reallocation. This \
requires ownership of the string on the left";
let str_concat_note = "string concatenation requires an owned `String` on the left";
let rm_borrow_msg = "remove the borrow to obtain an owned `String`";
let to_owned_msg = "create an owned `String` from a string reference";
let string_type = self.tcx.get_diagnostic_item(sym::String);
let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() {
@ -574,31 +567,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) =>
{
if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str`
err.span_label(
op.span,
"`+` cannot be used to concatenate two `&str` strings",
);
match source_map.span_to_snippet(lhs_expr.span) {
Ok(lstring) => {
err.span_suggestion(
lhs_expr.span,
if lstring.starts_with('&') {
remove_borrow_msg
} else {
msg
},
if let Some(stripped) = lstring.strip_prefix('&') {
// let a = String::new();
// let _ = &a + "bar";
stripped.to_string()
} else {
format!("{}.to_owned()", lstring)
},
Applicability::MachineApplicable,
)
}
_ => err.help(msg),
};
err.span_label(op.span, "`+` cannot be used to concatenate two `&str` strings");
err.note(str_concat_note);
if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind {
err.span_suggestion_verbose(
lhs_expr.span.until(lhs_inner_expr.span),
rm_borrow_msg,
"".to_owned(),
Applicability::MachineApplicable
);
} else {
err.span_suggestion_verbose(
lhs_expr.span.shrink_to_hi(),
to_owned_msg,
".to_owned()".to_owned(),
Applicability::MachineApplicable
);
}
}
true
}
@ -609,32 +594,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
op.span,
"`+` cannot be used to concatenate a `&str` with a `String`",
);
match (
source_map.span_to_snippet(lhs_expr.span),
source_map.span_to_snippet(rhs_expr.span),
is_assign,
) {
(Ok(l), Ok(r), IsAssign::No) => {
let to_string = if let Some(stripped) = l.strip_prefix('&') {
// let a = String::new(); let b = String::new();
// let _ = &a + b;
stripped.to_string()
match is_assign {
IsAssign::No => {
let sugg_msg;
let lhs_sugg = if let hir::ExprKind::AddrOf(_, _, lhs_inner_expr) = lhs_expr.kind {
sugg_msg = "remove the borrow on the left and add one on the right";
(lhs_expr.span.until(lhs_inner_expr.span), "".to_owned())
} else {
format!("{}.to_owned()", l)
sugg_msg = "create an owned `String` on the left and add a borrow on the right";
(lhs_expr.span.shrink_to_hi(), ".to_owned()".to_owned())
};
err.multipart_suggestion(
msg,
vec![
(lhs_expr.span, to_string),
(rhs_expr.span, format!("&{}", r)),
],
let suggestions = vec![
lhs_sugg,
(rhs_expr.span.shrink_to_lo(), "&".to_owned()),
];
err.multipart_suggestion_verbose(
sugg_msg,
suggestions,
Applicability::MachineApplicable,
);
}
_ => {
err.help(msg);
IsAssign::Yes => {
err.note(str_concat_note);
}
};
}
true
}
_ => false,

View File

@ -451,12 +451,10 @@ impl<T> Rc<T> {
///
/// let mut five = Rc::<u32>::new_uninit();
///
/// let five = unsafe {
/// // Deferred initialization:
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Rc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5)
/// ```
@ -543,12 +541,10 @@ impl<T> Rc<T> {
///
/// let mut five = Rc::<u32>::try_new_uninit()?;
///
/// let five = unsafe {
/// // Deferred initialization:
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Rc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5);
/// # Ok::<(), std::alloc::AllocError>(())
@ -660,14 +656,13 @@ impl<T> Rc<[T]> {
///
/// let mut values = Rc::<[u32]>::new_uninit_slice(3);
///
/// let values = unsafe {
/// // Deferred initialization:
/// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
/// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
/// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
/// // Deferred initialization:
/// let data = Rc::get_mut(&mut values).unwrap();
/// data[0].write(1);
/// data[1].write(2);
/// data[2].write(3);
///
/// values.assume_init()
/// };
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [1, 2, 3])
/// ```
@ -738,12 +733,10 @@ impl<T> Rc<mem::MaybeUninit<T>> {
///
/// let mut five = Rc::<u32>::new_uninit();
///
/// let five = unsafe {
/// // Deferred initialization:
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Rc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5)
/// ```
@ -777,14 +770,13 @@ impl<T> Rc<[mem::MaybeUninit<T>]> {
///
/// let mut values = Rc::<[u32]>::new_uninit_slice(3);
///
/// let values = unsafe {
/// // Deferred initialization:
/// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
/// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
/// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
/// // Deferred initialization:
/// let data = Rc::get_mut(&mut values).unwrap();
/// data[0].write(1);
/// data[1].write(2);
/// data[2].write(3);
///
/// values.assume_init()
/// };
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [1, 2, 3])
/// ```

View File

@ -437,12 +437,10 @@ impl<T> Arc<T> {
///
/// let mut five = Arc::<u32>::new_uninit();
///
/// let five = unsafe {
/// // Deferred initialization:
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Arc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5)
/// ```
@ -545,12 +543,10 @@ impl<T> Arc<T> {
///
/// let mut five = Arc::<u32>::try_new_uninit()?;
///
/// let five = unsafe {
/// // Deferred initialization:
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Arc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5);
/// # Ok::<(), std::alloc::AllocError>(())
@ -652,14 +648,13 @@ impl<T> Arc<[T]> {
///
/// let mut values = Arc::<[u32]>::new_uninit_slice(3);
///
/// let values = unsafe {
/// // Deferred initialization:
/// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
/// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
/// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
/// // Deferred initialization:
/// let data = Arc::get_mut(&mut values).unwrap();
/// data[0].write(1);
/// data[1].write(2);
/// data[2].write(3);
///
/// values.assume_init()
/// };
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [1, 2, 3])
/// ```
@ -730,12 +725,10 @@ impl<T> Arc<mem::MaybeUninit<T>> {
///
/// let mut five = Arc::<u32>::new_uninit();
///
/// let five = unsafe {
/// // Deferred initialization:
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
/// // Deferred initialization:
/// Arc::get_mut(&mut five).unwrap().write(5);
///
/// five.assume_init()
/// };
/// let five = unsafe { five.assume_init() };
///
/// assert_eq!(*five, 5)
/// ```
@ -770,14 +763,13 @@ impl<T> Arc<[mem::MaybeUninit<T>]> {
///
/// let mut values = Arc::<[u32]>::new_uninit_slice(3);
///
/// let values = unsafe {
/// // Deferred initialization:
/// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
/// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
/// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
/// // Deferred initialization:
/// let data = Arc::get_mut(&mut values).unwrap();
/// data[0].write(1);
/// data[1].write(2);
/// data[2].write(3);
///
/// values.assume_init()
/// };
/// let values = unsafe { values.assume_init() };
///
/// assert_eq!(*values, [1, 2, 3])
/// ```

View File

@ -973,7 +973,8 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
/// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> without copying or allocating.
/// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> by moving the [`CString`]
/// data into a new [`Arc`] buffer.
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
@ -992,7 +993,8 @@ impl From<&CStr> for Arc<CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
/// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> without copying or allocating.
/// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
/// data into a new [`Arc`] buffer.
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());

View File

@ -989,7 +989,8 @@ impl Clone for Box<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
/// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> without copying or allocating.
/// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`]
/// data into a new [`Arc`] buffer.
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
@ -1008,7 +1009,8 @@ impl From<&OsStr> for Arc<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
/// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> without copying or allocating.
/// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`]
/// data into a new [`Rc`] buffer.
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();

View File

@ -7,7 +7,7 @@ use crate::io::prelude::*;
use crate::cell::{Cell, RefCell};
use crate::fmt;
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, Split};
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
use crate::lazy::SyncOnceCell;
use crate::pin::Pin;
use crate::sync::atomic::{AtomicBool, Ordering};
@ -465,29 +465,6 @@ impl Stdin {
pub fn lines(self) -> Lines<StdinLock<'static>> {
self.into_locked().lines()
}
/// Consumes this handle and returns an iterator over input bytes,
/// split at the specified byte value.
///
/// For detailed semantics of this method, see the documentation on
/// [`BufRead::split`].
///
/// # Examples
///
/// ```no_run
/// #![feature(stdin_forwarders)]
/// use std::io;
///
/// let splits = io::stdin().split(b'-');
/// for split in splits {
/// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap()));
/// }
/// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[unstable(feature = "stdin_forwarders", issue = "87096")]
pub fn split(self, byte: u8) -> Split<StdinLock<'static>> {
self.into_locked().split(byte)
}
}
#[stable(feature = "std_debug", since = "1.16.0")]

View File

@ -1766,7 +1766,8 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
/// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer.
/// Converts a [`PathBuf`] into an <code>[Arc]<[Path]></code> by moving the [`PathBuf`] data
/// into a new [`Arc`] buffer.
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@ -1786,7 +1787,8 @@ impl From<&Path> for Arc<Path> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
/// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer.
/// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into
/// a new [`Rc`] buffer.
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
@ -1796,7 +1798,7 @@ impl From<PathBuf> for Rc<Path> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Rc<Path> {
/// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer.
/// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());

View File

@ -14,8 +14,8 @@ use crate::ptr;
target_arch = "asmjs",
target_arch = "wasm32",
target_arch = "hexagon",
target_arch = "riscv32",
target_arch = "xtensa"
all(target_arch = "riscv32", not(target_os = "espidf")),
all(target_arch = "xtensa", not(target_os = "espidf")),
)))]
pub const MIN_ALIGN: usize = 8;
#[cfg(all(any(
@ -28,6 +28,12 @@ pub const MIN_ALIGN: usize = 8;
target_arch = "wasm64",
)))]
pub const MIN_ALIGN: usize = 16;
// The allocator on the esp-idf platform guarentees 4 byte alignment.
#[cfg(all(any(
all(target_arch = "riscv32", target_os = "espidf"),
all(target_arch = "xtensa", target_os = "espidf"),
)))]
pub const MIN_ALIGN: usize = 4;
pub unsafe fn realloc_fallback(
alloc: &System,

View File

@ -7,7 +7,7 @@ use std::fmt::Debug;
use std::fs;
use std::hash::Hash;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::path::{Component, Path, PathBuf};
use std::process::Command;
use std::time::{Duration, Instant};
@ -105,6 +105,44 @@ struct StepDescription {
should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>,
make_run: fn(RunConfig<'_>),
name: &'static str,
kind: Kind,
}
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct TaskPath {
pub path: PathBuf,
pub kind: Option<Kind>,
}
impl TaskPath {
pub fn parse(path: impl Into<PathBuf>) -> TaskPath {
let mut kind = None;
let mut path = path.into();
let mut components = path.components();
if let Some(Component::Normal(os_str)) = components.next() {
if let Some(str) = os_str.to_str() {
if let Some((found_kind, found_prefix)) = str.split_once("::") {
if found_kind.is_empty() {
panic!("empty kind in task path {}", path.display());
}
kind = Some(Kind::parse(found_kind));
path = Path::new(found_prefix).join(components.as_path());
}
}
}
TaskPath { path, kind }
}
}
impl Debug for TaskPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(kind) = &self.kind {
write!(f, "{}::", kind.as_str())?;
}
write!(f, "{}", self.path.display())
}
}
/// Collection of paths used to match a task rule.
@ -115,14 +153,14 @@ pub enum PathSet {
/// These are generally matched as a path suffix. For example, a
/// command-line value of `libstd` will match if `src/libstd` is in the
/// set.
Set(BTreeSet<PathBuf>),
Set(BTreeSet<TaskPath>),
/// A "suite" of paths.
///
/// These can match as a path suffix (like `Set`), or as a prefix. For
/// example, a command-line value of `src/test/ui/abi/variadic-ffi.rs`
/// will match `src/test/ui`. A command-line value of `ui` would also
/// match `src/test/ui`.
Suite(PathBuf),
Suite(TaskPath),
}
impl PathSet {
@ -130,35 +168,46 @@ impl PathSet {
PathSet::Set(BTreeSet::new())
}
fn one<P: Into<PathBuf>>(path: P) -> PathSet {
fn one<P: Into<PathBuf>>(path: P, kind: Kind) -> PathSet {
let mut set = BTreeSet::new();
set.insert(path.into());
set.insert(TaskPath { path: path.into(), kind: Some(kind.into()) });
PathSet::Set(set)
}
fn has(&self, needle: &Path) -> bool {
fn has(&self, needle: &Path, module: Option<Kind>) -> bool {
let check = |p: &TaskPath| {
if let (Some(p_kind), Some(kind)) = (&p.kind, module) {
p.path.ends_with(needle) && *p_kind == kind
} else {
p.path.ends_with(needle)
}
};
match self {
PathSet::Set(set) => set.iter().any(|p| p.ends_with(needle)),
PathSet::Suite(suite) => suite.ends_with(needle),
PathSet::Set(set) => set.iter().any(check),
PathSet::Suite(suite) => check(suite),
}
}
fn path(&self, builder: &Builder<'_>) -> PathBuf {
match self {
PathSet::Set(set) => set.iter().next().unwrap_or(&builder.build.src).to_path_buf(),
PathSet::Suite(path) => PathBuf::from(path),
PathSet::Set(set) => {
set.iter().next().map(|p| &p.path).unwrap_or(&builder.build.src).clone()
}
PathSet::Suite(path) => path.path.clone(),
}
}
}
impl StepDescription {
fn from<S: Step>() -> StepDescription {
fn from<S: Step>(kind: Kind) -> StepDescription {
StepDescription {
default: S::DEFAULT,
only_hosts: S::ONLY_HOSTS,
should_run: S::should_run,
make_run: S::make_run,
name: std::any::type_name::<S>(),
kind,
}
}
@ -177,7 +226,7 @@ impl StepDescription {
}
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
if builder.config.exclude.iter().any(|e| pathset.has(e)) {
if builder.config.exclude.iter().any(|e| pathset.has(&e.path, e.kind)) {
eprintln!("Skipping {:?} because it is excluded", pathset);
return true;
}
@ -192,8 +241,10 @@ impl StepDescription {
}
fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
let should_runs =
v.iter().map(|desc| (desc.should_run)(ShouldRun::new(builder))).collect::<Vec<_>>();
let should_runs = v
.iter()
.map(|desc| (desc.should_run)(ShouldRun::new(builder, desc.kind)))
.collect::<Vec<_>>();
// sanity checks on rules
for (desc, should_run) in v.iter().zip(&should_runs) {
@ -226,7 +277,7 @@ impl StepDescription {
if let Some(suite) = should_run.is_suite_path(path) {
attempted_run = true;
desc.maybe_run(builder, suite);
} else if let Some(pathset) = should_run.pathset_for_path(path) {
} else if let Some(pathset) = should_run.pathset_for_path(path, desc.kind) {
attempted_run = true;
desc.maybe_run(builder, pathset);
}
@ -246,6 +297,8 @@ enum ReallyDefault<'a> {
pub struct ShouldRun<'a> {
pub builder: &'a Builder<'a>,
kind: Kind,
// use a BTreeSet to maintain sort order
paths: BTreeSet<PathSet>,
@ -255,9 +308,10 @@ pub struct ShouldRun<'a> {
}
impl<'a> ShouldRun<'a> {
fn new(builder: &'a Builder<'_>) -> ShouldRun<'a> {
fn new(builder: &'a Builder<'_>, kind: Kind) -> ShouldRun<'a> {
ShouldRun {
builder,
kind,
paths: BTreeSet::new(),
is_really_default: ReallyDefault::Bool(true), // by default no additional conditions
}
@ -293,7 +347,7 @@ impl<'a> ShouldRun<'a> {
let mut set = BTreeSet::new();
for krate in self.builder.in_tree_crates(name, None) {
let path = krate.local_path(self.builder);
set.insert(path);
set.insert(TaskPath { path, kind: Some(self.kind) });
}
self.paths.insert(PathSet::Set(set));
self
@ -306,7 +360,7 @@ impl<'a> ShouldRun<'a> {
pub fn krate(mut self, name: &str) -> Self {
for krate in self.builder.in_tree_crates(name, None) {
let path = krate.local_path(self.builder);
self.paths.insert(PathSet::one(path));
self.paths.insert(PathSet::one(path, self.kind));
}
self
}
@ -318,19 +372,25 @@ impl<'a> ShouldRun<'a> {
// multiple aliases for the same job
pub fn paths(mut self, paths: &[&str]) -> Self {
self.paths.insert(PathSet::Set(paths.iter().map(PathBuf::from).collect()));
self.paths.insert(PathSet::Set(
paths
.iter()
.map(|p| TaskPath { path: p.into(), kind: Some(self.kind.into()) })
.collect(),
));
self
}
pub fn is_suite_path(&self, path: &Path) -> Option<&PathSet> {
self.paths.iter().find(|pathset| match pathset {
PathSet::Suite(p) => path.starts_with(p),
PathSet::Suite(p) => path.starts_with(&p.path),
PathSet::Set(_) => false,
})
}
pub fn suite_path(mut self, suite: &str) -> Self {
self.paths.insert(PathSet::Suite(PathBuf::from(suite)));
self.paths
.insert(PathSet::Suite(TaskPath { path: suite.into(), kind: Some(self.kind.into()) }));
self
}
@ -340,12 +400,12 @@ impl<'a> ShouldRun<'a> {
self
}
fn pathset_for_path(&self, path: &Path) -> Option<&PathSet> {
self.paths.iter().find(|pathset| pathset.has(path))
fn pathset_for_path(&self, path: &Path, kind: Kind) -> Option<&PathSet> {
self.paths.iter().find(|pathset| pathset.has(path, Some(kind)))
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Kind {
Build,
Check,
@ -359,11 +419,44 @@ pub enum Kind {
Run,
}
impl Kind {
fn parse(string: &str) -> Kind {
match string {
"build" => Kind::Build,
"check" => Kind::Check,
"clippy" => Kind::Clippy,
"fix" => Kind::Fix,
"test" => Kind::Test,
"bench" => Kind::Bench,
"dist" => Kind::Dist,
"doc" => Kind::Doc,
"install" => Kind::Install,
"run" => Kind::Run,
other => panic!("unknown kind: {}", other),
}
}
fn as_str(&self) -> &'static str {
match self {
Kind::Build => "build",
Kind::Check => "check",
Kind::Clippy => "clippy",
Kind::Fix => "fix",
Kind::Test => "test",
Kind::Bench => "bench",
Kind::Dist => "dist",
Kind::Doc => "doc",
Kind::Install => "install",
Kind::Run => "run",
}
}
}
impl<'a> Builder<'a> {
fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
macro_rules! describe {
($($rule:ty),+ $(,)?) => {{
vec![$(StepDescription::from::<$rule>()),+]
vec![$(StepDescription::from::<$rule>(kind)),+]
}};
}
match kind {
@ -540,8 +633,11 @@ impl<'a> Builder<'a> {
let builder = Self::new_internal(build, kind, vec![]);
let builder = &builder;
let mut should_run = ShouldRun::new(builder);
// The "build" kind here is just a placeholder, it will be replaced with something else in
// the following statement.
let mut should_run = ShouldRun::new(builder, Kind::Build);
for desc in Builder::get_step_descriptions(builder.kind) {
should_run.kind = desc.kind;
should_run = (desc.should_run)(should_run);
}
let mut help = String::from("Available paths:\n");
@ -552,11 +648,11 @@ impl<'a> Builder<'a> {
match pathset {
PathSet::Set(set) => {
for path in set {
add_path(&path);
add_path(&path.path);
}
}
PathSet::Suite(path) => {
add_path(&path.join("..."));
add_path(&path.path.join("..."));
}
}
}
@ -1626,9 +1722,10 @@ impl<'a> Builder<'a> {
pub(crate) fn ensure_if_default<T, S: Step<Output = Option<T>>>(
&'a self,
step: S,
kind: Kind,
) -> S::Output {
let desc = StepDescription::from::<S>();
let should_run = (desc.should_run)(ShouldRun::new(self));
let desc = StepDescription::from::<S>(kind);
let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
// Avoid running steps contained in --exclude
for pathset in &should_run.paths {
@ -1642,13 +1739,16 @@ impl<'a> Builder<'a> {
}
/// Checks if any of the "should_run" paths is in the `Builder` paths.
pub(crate) fn was_invoked_explicitly<S: Step>(&'a self) -> bool {
let desc = StepDescription::from::<S>();
let should_run = (desc.should_run)(ShouldRun::new(self));
pub(crate) fn was_invoked_explicitly<S: Step>(&'a self, kind: Kind) -> bool {
let desc = StepDescription::from::<S>(kind);
let should_run = (desc.should_run)(ShouldRun::new(self, desc.kind));
for path in &self.paths {
if should_run.paths.iter().any(|s| s.has(path))
&& !desc.is_excluded(self, &PathSet::Suite(path.clone()))
if should_run.paths.iter().any(|s| s.has(path, Some(desc.kind)))
&& !desc.is_excluded(
self,
&PathSet::Suite(TaskPath { path: path.clone(), kind: Some(desc.kind.into()) }),
)
{
return true;
}

View File

@ -499,7 +499,7 @@ mod dist {
let host = TargetSelection::from_user("A");
builder.run_step_descriptions(
&[StepDescription::from::<test::Crate>()],
&[StepDescription::from::<test::Crate>(Kind::Test)],
&["library/std".into()],
);
@ -520,7 +520,7 @@ mod dist {
#[test]
fn test_exclude() {
let mut config = configure(&["A"], &["A"]);
config.exclude = vec!["src/tools/tidy".into()];
config.exclude = vec![TaskPath::parse("src/tools/tidy")];
config.cmd = Subcommand::Test {
paths: Vec::new(),
test_args: Vec::new(),

View File

@ -12,6 +12,7 @@ use std::fs;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use crate::builder::TaskPath;
use crate::cache::{Interned, INTERNER};
use crate::channel::GitInfo;
pub use crate::flags::Subcommand;
@ -62,7 +63,7 @@ pub struct Config {
pub sanitizers: bool,
pub profiler: bool,
pub ignore_git: bool,
pub exclude: Vec<PathBuf>,
pub exclude: Vec<TaskPath>,
pub include_default_paths: bool,
pub rustc_error_format: Option<String>,
pub json_output: bool,
@ -635,7 +636,7 @@ impl Config {
let flags = Flags::parse(&args);
let mut config = Config::default_opts();
config.exclude = flags.exclude;
config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect();
config.include_default_paths = flags.include_default_paths;
config.rustc_error_format = flags.rustc_error_format;
config.json_output = flags.json_output;

View File

@ -16,7 +16,7 @@ use std::process::Command;
use build_helper::{output, t};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::compile;
use crate::config::TargetSelection;
@ -1368,7 +1368,7 @@ impl Step for Extended {
let mut built_tools = HashSet::new();
macro_rules! add_component {
($name:expr => $step:expr) => {
if let Some(tarball) = builder.ensure_if_default($step) {
if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
tarballs.push(tarball);
built_tools.insert($name);
}

View File

@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
use crate::Mode;
use build_helper::{t, up_to_date};
use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::compile;
use crate::config::{Config, TargetSelection};
@ -240,7 +240,7 @@ impl Step for TheBook {
invoke_rustdoc(builder, compiler, target, path);
}
if builder.was_invoked_explicitly::<Self>() {
if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
let out = builder.doc_out(target);
let index = out.join("book").join("index.html");
open(builder, &index);
@ -400,7 +400,7 @@ impl Step for Standalone {
// We open doc/index.html as the default if invoked as `x.py doc --open`
// with no particular explicit doc requested (e.g. library/core).
if builder.paths.is_empty() || builder.was_invoked_explicitly::<Self>() {
if builder.paths.is_empty() || builder.was_invoked_explicitly::<Self>(Kind::Doc) {
let index = out.join("index.html");
open(builder, &index);
}
@ -902,7 +902,7 @@ impl Step for RustcBook {
name: INTERNER.intern_str("rustc"),
src: INTERNER.intern_path(out_base),
});
if builder.was_invoked_explicitly::<Self>() {
if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
let out = builder.doc_out(self.target);
let index = out.join("rustc").join("index.html");
open(builder, &index);

View File

@ -671,7 +671,6 @@ nav.sub {
margin: .5em 0;
width: calc(100% - 2px);
overflow-x: auto;
overflow-wrap: normal;
display: block;
}
@ -858,6 +857,31 @@ h2.small-section-header > .anchor {
.block a.current.crate { font-weight: 500; }
/* In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap
as much as needed on mobile (see
src/test/rustdoc-gui/type-declaration-overflow.goml for an example of why
this matters). The `anywhere` value means:
"Soft wrap opportunities introduced by the word break are considered when
calculating min-content intrinsic sizes."
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap#values
For table layouts, that becomes a problem: the browser tries to make each
column as narrow as possible, and `overflow-wrap: anywhere` means it can do
so by breaking words - even if some other column could be shrunk without
breaking words! This shows up, for instance, in the `Structs` / `Modules` /
`Functions` (etcetera) sections of a module page, and when a docblock
contains a table.
So, for table layouts, override the default with break-word, which does
_not_ affect min-content intrinsic sizes.
*/
table,
.item-table {
overflow-wrap: break-word;
}
.item-table {
display: table;
}
@ -2058,10 +2082,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
overflow-wrap: anywhere;
}
.docblock table code {
overflow-wrap: normal;
}
.sub-container {
flex-direction: column;
}

View File

@ -2,8 +2,8 @@
| Free Region Mapping
| '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#4r, '_#3r]
| '_#1r | External | ['_#1r, '_#4r]
| '_#2r | External | ['_#2r, '_#1r, '_#4r]
| '_#1r | Local | ['_#1r, '_#4r]
| '_#2r | Local | ['_#2r, '_#1r, '_#4r]
| '_#3r | Local | ['_#4r, '_#3r]
| '_#4r | Local | ['_#4r]
|

View File

@ -39,7 +39,6 @@ impl Trait for Foo {
const Y: u32 = 0;
}
impl implementors::Whatever for Foo {
type Foo = u32;
}
@ -58,8 +57,10 @@ pub mod sub_mod {
pub mod long_trait {
use std::ops::DerefMut;
pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem: DerefMut<Target = u32>
+ From<u128> + Send + Sync + AsRef<str> + 'static {}
pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem:
DerefMut<Target = u32> + From<u128> + Send + Sync + AsRef<str> + 'static
{
}
}
pub mod long_table {
@ -88,18 +89,28 @@ pub mod summary_table {
}
pub mod too_long {
pub type ReallyLongTypeNameLongLongLong = Option<unsafe extern "C" fn(a: *const u8, b: *const u8) -> *const u8>;
pub type ReallyLongTypeNameLongLongLong =
Option<unsafe extern "C" fn(a: *const u8, b: *const u8) -> *const u8>;
pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0;
pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0;
pub struct SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
pub a: u32,
}
/// This also has a really long doccomment. Lorem ipsum dolor sit amet,
/// consectetur adipiscing elit. Suspendisse id nibh malesuada, hendrerit
/// massa vel, tincidunt est. Nulla interdum, sem ac efficitur ornare, arcu
/// nunc dignissim nibh, at rutrum diam augue ac mauris. Fusce tincidunt et
/// ligula sed viverra. Aenean sed facilisis dui, non volutpat felis. In
/// vitae est dui. Donec felis nibh, blandit at nibh eu, tempor suscipit
/// nisl. Vestibulum ornare porta libero, eu faucibus purus iaculis ut. Ut
/// quis tincidunt nunc, in mollis purus. Nulla sed interdum quam. Nunc
/// vitae cursus ex.
pub struct SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
pub a: u32,
}
impl SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
/// ```
/// let x = SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { a: 0 };
/// ```
impl SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName {
/// ```
/// let x = SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName { a: 0 };
/// ```
pub fn foo(&self) {}
}
}

View File

@ -7,6 +7,10 @@ assert-property: ("body", {"scrollWidth": "1100"})
// However, since there is overflow in the type declaration, its scroll width is bigger.
assert-property: (".item-decl pre", {"scrollWidth": "1324"})
// In the table-ish view on the module index, the name should not be wrapped more than necessary.
goto: file://|DOC_PATH|/lib2/too_long/index.html
assert-property: (".item-table .struct", {"offsetWidth": "684"})
// We now make the same check on type declaration...
goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html
assert-property: ("body", {"scrollWidth": "1100"})

View File

@ -20,7 +20,7 @@ LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f
| |
| lifetime `'f` defined here
LL | ap
| ^^ returning this value requires that `'1` must outlive `'f`
| ^^ function was supposed to return data with lifetime `'f` but it is returning data with lifetime `'1`
|
= note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant
= note: the struct VaListImpl<'f> is invariant over the parameter 'f

View File

@ -1,3 +1,3 @@
// compile-flags: --cfg a(b=c)
// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`)
// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
fn main() {}

View File

@ -1,2 +1,2 @@
error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`)
error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")

View File

@ -0,0 +1,4 @@
// Test for missing quotes around value, issue #66450.
// compile-flags: --cfg key=value
// error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
fn main() {}

View File

@ -0,0 +1,2 @@
error: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")

View File

@ -6,7 +6,7 @@ LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
| |
| lifetime `'a` defined here
LL | s
| ^ returning this value requires that `'b` must outlive `'a`
| ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`

View File

@ -1,20 +1,13 @@
error[E0521]: borrowed data escapes outside of associated function
error: lifetime may not live long enough
--> $DIR/issue-16683.rs:4:9
|
LL | trait T<'a> {
| -- lifetime `'a` defined here
LL | fn a(&'a self) -> &'a bool;
LL | fn b(&self) {
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
| - let's call the lifetime of this reference `'1`
LL | self.a();
| ^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
| ^^^^^^^^ argument requires that `'1` must outlive `'a`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.

View File

@ -1,20 +1,13 @@
error[E0521]: borrowed data escapes outside of associated function
error: lifetime may not live long enough
--> $DIR/issue-17758.rs:7:9
|
LL | trait Foo<'a> {
| -- lifetime `'a` defined here
LL | fn foo(&'a self);
LL | fn bar(&self) {
| -----
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
| - let's call the lifetime of this reference `'1`
LL | self.foo();
| ^^^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
| ^^^^^^^^^^ argument requires that `'1` must outlive `'a`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.

View File

@ -7,10 +7,11 @@ LL | let _a = b + ", World!";
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _a = b.to_owned() + ", World!";
| ~~~~~~~~~~~~
| +++++++++++
error: aborting due to previous error

View File

@ -7,10 +7,11 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!";
| ~~~~~~~~~~~~
| +++++++++++
error: aborting due to previous error

View File

@ -59,10 +59,8 @@ LL | &(true, false) => ()
error[E0618]: expected function, found `(char, char)`
--> $DIR/issue-5100.rs:48:14
|
LL | let v = [('a', 'b')
| ______________-^^^^^^^^^
LL | | ('c', 'd'),
| |_______________________- call expression requires function
LL | let v = [('a', 'b')
| ^^^^^^^^^^- help: consider separating array elements with a comma: `,`
error[E0308]: mismatched types
--> $DIR/issue-5100.rs:55:19

View File

@ -7,7 +7,7 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
| lifetime `'a` defined here
LL | match (&t,) {
LL | ((u,),) => u,
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -6,7 +6,7 @@ LL | impl<'b> S<'b> {
LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
| -- lifetime `'a` defined here
LL | match self.0 { ref mut x => x }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to &i32

View File

@ -7,7 +7,7 @@ LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
| -- lifetime `'a` defined here
LL | let ref mut x = self.0;
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to &i32

View File

@ -7,7 +7,7 @@ LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> i
| lifetime `'a` defined here
...
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -6,7 +6,7 @@ LL | fn new(bar: &mut Bar) -> Self {
| |
| let's call the lifetime of this reference `'1`
LL | Foo { bar }
| ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| ^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: aborting due to previous error

View File

@ -14,7 +14,7 @@ struct Consumer<'tcx>(&'tcx ());
impl<'tcx> Consumer<'tcx> {
fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
let other = self.use_fcx(fcx); //~ ERROR borrowed data
let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough
fcx.use_it(other);
}

View File

@ -1,21 +1,14 @@
error[E0521]: borrowed data escapes outside of associated function
error: lifetime may not live long enough
--> $DIR/issue-67007-escaping-data.rs:17:21
|
LL | impl<'tcx> Consumer<'tcx> {
| ---- lifetime `'tcx` defined here
LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
| -- ----- --- `fcx` is a reference that is only valid in the associated function body
| | |
| | `self` declared here, outside of the associated function body
| lifetime `'a` defined here
| -- lifetime `'a` defined here
LL | let other = self.use_fcx(fcx);
| ^^^^^^^^^^^^^^^^^
| |
| `fcx` escapes the associated function body here
| argument requires that `'a` must outlive `'tcx`
| ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx`
|
= help: consider adding the following bound: `'a: 'tcx`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.

View File

@ -7,7 +7,7 @@ LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
| lifetime `'a` defined here
LL | let g: fn(_, _) -> _ = |_x, y| y;
LL | g
| ^ returning this value requires that `'b` must outlive `'a`
| ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`

View File

@ -6,7 +6,7 @@ LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usiz
| |
| lifetime `'a` defined here
LL | (x, y)
| ^^^^^^ returning this value requires that `'a` must outlive `'c`
| ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'c`
@ -18,7 +18,7 @@ LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usiz
| |
| lifetime `'b` defined here
LL | (x, y)
| ^^^^^^ returning this value requires that `'b` must outlive `'d`
| ^^^^^^ function was supposed to return data with lifetime `'d` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'd`
@ -35,7 +35,7 @@ LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usi
| |
| lifetime `'a` defined here
LL | (x, y)
| ^^^^^^ returning this value requires that `'a` must outlive `'c`
| ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'c`

View File

@ -70,7 +70,7 @@ pub struct Foo2<'a> {
impl<'a> Foo2<'a> {
// should not produce outlives suggestions to name 'self
fn get_bar(&self) -> Bar2 {
Bar2::new(&self) //~ERROR borrowed data escapes outside of associated function
Bar2::new(&self) //~ERROR lifetime may not live long enough
}
}

View File

@ -6,7 +6,7 @@ LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize {
| |
| lifetime `'a` defined here
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -53,7 +53,7 @@ LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) {
| lifetime `'a` defined here
...
LL | (x, x)
| ^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -73,7 +73,7 @@ LL | impl<'a> Bar<'a> {
LL | pub fn get<'b>(&self) -> &'b usize {
| -- lifetime `'b` defined here
LL | self.x
| ^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -85,28 +85,20 @@ LL | impl<'a> Baz<'a> {
LL | fn get<'b>(&'b self) -> &'a i32 {
| -- lifetime `'b` defined here
LL | self.x
| ^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
error[E0521]: borrowed data escapes outside of associated function
error: lifetime may not live long enough
--> $DIR/outlives-suggestion-simple.rs:73:9
|
LL | impl<'a> Foo2<'a> {
| -- lifetime `'a` defined here
LL | // should not produce outlives suggestions to name 'self
LL | fn get_bar(&self) -> Bar2 {
| -----
| |
| `self` declared here, outside of the associated function body
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
| - let's call the lifetime of this reference `'1`
LL | Bar2::new(&self)
| ^^^^^^^^^^^^^^^^
| |
| `self` escapes the associated function body here
| argument requires that `'1` must outlive `'a`
| ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0521`.

View File

@ -6,7 +6,7 @@ LL | impl<'a> FromBox<'a> for C<'a> {
LL | fn from_box(b: Box<B>) -> Self {
| - has type `Box<Box<&'1 isize>>`
LL | C { f: b }
| ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
| ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
--> $DIR/type-alias-free-regions.rs:27:9
@ -16,7 +16,7 @@ LL | impl<'a> FromTuple<'a> for C<'a> {
LL | fn from_tuple(b: (B,)) -> Self {
| - has type `(Box<&'1 isize>,)`
LL | C { f: Box::new(b.0) }
| ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
| ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
error: aborting due to 2 previous errors

View File

@ -6,7 +6,7 @@ LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
| |
| lifetime `'a` defined here
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -18,7 +18,7 @@ LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
| |
| lifetime `'a` defined here
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -47,7 +47,7 @@ LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
| lifetime `'a` defined here
LL | // Two errors because *mut is invariant
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable pointer to &i32
@ -64,7 +64,7 @@ LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
| |
| lifetime `'a` defined here
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -77,7 +77,7 @@ LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
| lifetime `'a` defined here
...
LL | y
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -90,7 +90,7 @@ LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
| lifetime `'a` defined here
...
LL | y
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -103,7 +103,7 @@ LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
| lifetime `'a` defined here
...
LL | y
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -6,7 +6,7 @@ LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
| |
| lifetime `'a` defined here
LL | Foo::xmute(u)
| ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`

View File

@ -7,7 +7,7 @@ LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| lifetime `'a` defined here
...
LL | ss
| ^^ returning this value requires that `'a` must outlive `'b`
| ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -6,7 +6,7 @@ LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| |
| lifetime `'a` defined here
LL | x.borrowed()
| ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -31,7 +31,7 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| |
| lifetime `'a` defined here
LL | Box::new(v)
| ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -1,18 +1,13 @@
error[E0521]: borrowed data escapes outside of function
error: lifetime may not live long enough
--> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5
|
LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) {
| -- -- - - `b` is a reference that is only valid in the function body
| | | |
| | | `a` declared here, outside of the function body
| | lifetime `'b` defined here
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
LL | f.method(b);
| ^^^^^^^^^^^
| |
| `b` escapes the function body here
| argument requires that `'b` must outlive `'a`
| ^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant
@ -21,4 +16,3 @@ LL | f.method(b);
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.

View File

@ -6,7 +6,7 @@ LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> {
| |
| lifetime `'a` defined here
LL | return e;
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@ -18,7 +18,7 @@ LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> {
| |
| lifetime `'a` defined here
LL | return e;
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -7,7 +7,7 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait +
| lifetime `'a` defined here
LL | // A outlives 'a AND 'b...but not 'c.
LL | Box::new(v) as Box<dyn SomeTrait + 'a>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'c`

View File

@ -6,7 +6,7 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
| |
| lifetime `'a` defined here
LL | Ast::Add(x, y)
| ^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
| ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -6,7 +6,7 @@ LL | impl<'a> Box<'a> {
LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
| -- lifetime `'b` defined here
LL | g2.get()
| ^^^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`

View File

@ -9,7 +9,7 @@ LL | / match self.next {
LL | | Some(ref next) => next.get(),
LL | | None => &self.val
LL | | }
| |_________^ returning this value requires that `'a` must outlive `'b`
| |_________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

View File

@ -2,7 +2,7 @@ error: lifetime may not live long enough
--> $DIR/regions-infer-not-param.rs:15:54
|
LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p }
| -- -- lifetime `'b` defined here ^ returning this value requires that `'a` must outlive `'b`
| -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
| |
| lifetime `'a` defined here
|
@ -25,7 +25,7 @@ error: lifetime may not live long enough
--> $DIR/regions-infer-not-param.rs:19:63
|
LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p }
| -- -- lifetime `'b` defined here ^ returning this value requires that `'a` must outlive `'b`
| -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
| |
| lifetime `'a` defined here
|

View File

@ -7,7 +7,7 @@ LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| lifetime `'a` defined here
LL | // Without knowing 'a:'b, we can't coerce
LL | x
| ^ returning this value requires that `'a` must outlive `'b`
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to dyn Dummy
@ -23,7 +23,7 @@ LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dum
| lifetime `'a` defined here
LL | // We can't coerce because it is packed in `Wrapper`
LL | x
| ^ returning this value requires that `'b` must outlive `'a`
| ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to dyn Dummy

View File

@ -7,10 +7,11 @@ LL | let x = "Hello " + "World!";
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let x = "Hello ".to_owned() + "World!";
| ~~~~~~~~~~~~~~~~~~~
| +++++++++++
error[E0369]: cannot add `World` to `World`
--> $DIR/issue-39018.rs:8:26
@ -46,10 +47,10 @@ LL | let x = "Hello " + "World!".to_owned();
| | `+` cannot be used to concatenate a `&str` with a `String`
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
help: create an owned `String` on the left and add a borrow on the right
|
LL | let x = "Hello ".to_owned() + &"World!".to_owned();
| ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
| +++++++++++ +
error[E0369]: cannot add `&String` to `&String`
--> $DIR/issue-39018.rs:26:16
@ -60,10 +61,12 @@ LL | let _ = &a + &b;
| | `+` cannot be used to concatenate two `&str` strings
| &String
|
help: String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: remove the borrow to obtain an owned `String`
|
LL | let _ = a + &b;
| ~
LL - let _ = &a + &b;
LL + let _ = a + &b;
|
error[E0369]: cannot add `String` to `&String`
--> $DIR/issue-39018.rs:27:16
@ -74,10 +77,11 @@ LL | let _ = &a + b;
| | `+` cannot be used to concatenate a `&str` with a `String`
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
help: remove the borrow on the left and add one on the right
|
LL | let _ = a + &b;
| ~ ~~
LL - let _ = &a + b;
LL + let _ = a + &b;
|
error[E0308]: mismatched types
--> $DIR/issue-39018.rs:29:17
@ -97,10 +101,10 @@ LL | let _ = e + b;
| | `+` cannot be used to concatenate a `&str` with a `String`
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
help: create an owned `String` on the left and add a borrow on the right
|
LL | let _ = e.to_owned() + &b;
| ~~~~~~~~~~~~ ~~
| +++++++++++ +
error[E0369]: cannot add `&String` to `&String`
--> $DIR/issue-39018.rs:31:15
@ -111,10 +115,11 @@ LL | let _ = e + &b;
| | `+` cannot be used to concatenate two `&str` strings
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = e.to_owned() + &b;
| ~~~~~~~~~~~~
| +++++++++++
error[E0369]: cannot add `&str` to `&String`
--> $DIR/issue-39018.rs:32:15
@ -125,10 +130,11 @@ LL | let _ = e + d;
| | `+` cannot be used to concatenate two `&str` strings
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = e.to_owned() + d;
| ~~~~~~~~~~~~
| +++++++++++
error[E0369]: cannot add `&&str` to `&String`
--> $DIR/issue-39018.rs:33:15
@ -139,10 +145,11 @@ LL | let _ = e + &d;
| | `+` cannot be used to concatenate two `&str` strings
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = e.to_owned() + &d;
| ~~~~~~~~~~~~
| +++++++++++
error[E0369]: cannot add `&&str` to `&&str`
--> $DIR/issue-39018.rs:34:16
@ -169,10 +176,11 @@ LL | let _ = c + &d;
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = c.to_owned() + &d;
| ~~~~~~~~~~~~
| +++++++++++
error[E0369]: cannot add `&str` to `&str`
--> $DIR/issue-39018.rs:37:15
@ -183,10 +191,11 @@ LL | let _ = c + d;
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = c.to_owned() + d;
| ~~~~~~~~~~~~
| +++++++++++
error: aborting due to 14 previous errors

View File

@ -7,10 +7,11 @@ LL | let c = a + b;
| | `+` cannot be used to concatenate two `&str` strings
| &String
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let c = a.to_owned() + b;
| ~~~~~~~~~~~~
| +++++++++++
error: aborting due to previous error

View File

@ -7,10 +7,11 @@ LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔ
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
= note: string concatenation requires an owned `String` on the left
help: create an owned `String` from a string reference
|
LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!";
| ~~~~~~~~~~~~~~~~~~~~~~~~~
| +++++++++++
error: aborting due to previous error

View File

@ -0,0 +1,7 @@
fn main() {
let _tmp = [
("C200B40A82", 3),
("C200B40A83", 4) //~ ERROR: expected function, found `(&'static str, {integer})` [E0618]
("C200B40A8537", 5),
];
}

View File

@ -0,0 +1,9 @@
error[E0618]: expected function, found `(&'static str, {integer})`
--> $DIR/array-diagnostics.rs:4:9
|
LL | ("C200B40A83", 4)
| ^^^^^^^^^^^^^^^^^- help: consider separating array elements with a comma: `,`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0618`.

View File

@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`
@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`

View File

@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`
@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`

View File

@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`
@ -20,7 +20,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`

View File

@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`

View File

@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`

View File

@ -7,7 +7,7 @@ LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`
= note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant
@ -23,7 +23,7 @@ LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>)
| lifetime `'min` defined here
...
LL | v
| ^ returning this value requires that `'min` must outlive `'max`
| ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min`
|
= help: consider adding the following bound: `'min: 'max`
= note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant

View File

@ -7,7 +7,7 @@ LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
| lifetime `'a` defined here
...
LL | u
| ^ returning this value requires that `'b` must outlive `'a`
| ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
@ -33,7 +33,7 @@ LL | impl<'a, 'b> Evil<'a, 'b> {
| lifetime `'a` defined here
LL | fn inherent_evil(u: &'b u32) -> &'a u32 {
LL | u
| ^ returning this value requires that `'b` must outlive `'a`
| ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
@ -45,7 +45,7 @@ LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
| |
| lifetime `'a` defined here
LL | <()>::static_evil(b)
| ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
@ -57,7 +57,7 @@ LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
| |
| lifetime `'a` defined here
LL | <IndirectEvil>::static_evil(b)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
@ -69,7 +69,7 @@ LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
| |
| lifetime `'a` defined here
LL | <Evil>::inherent_evil(b)
| ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`