mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #78127 - JohnTitor:rollup-p1bxtqq, r=JohnTitor
Rollup of 10 pull requests Successful merges: - #77612 (BTreeMap: test invariants more thoroughly and more readably) - #77761 (Assert that pthread mutex initialization succeeded) - #77778 ([x.py setup] Allow setting up git hooks from other worktrees) - #77838 (const keyword: brief paragraph on 'const fn') - #77923 ([net] apply clippy lints) - #77931 (Fix false positive for `unused_parens` lint) - #77959 (Tweak ui-tests structure) - #78105 (change name in .mailmap) - #78111 (Trait predicate ambiguities are not always in `Self`) - #78121 (Do not ICE on pattern that uses a binding multiple times in generator) Failed merges: r? `@ghost`
This commit is contained in:
commit
c9b52100d5
2
.mailmap
2
.mailmap
@ -29,7 +29,6 @@ Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> arielb1 <arielb1@mail.tau.ac.il>
|
||||
Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org>
|
||||
Aydin Kim <ladinjin@hanmail.net> aydin.kim <aydin.kim@samsung.com>
|
||||
Barosl Lee <vcs@barosl.com> Barosl LEE <github@barosl.com>
|
||||
Bastian Kauschke <bastian_kauschke@hotmail.de>
|
||||
Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com>
|
||||
Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@bsago.me>
|
||||
Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@users.noreply.github.com>
|
||||
@ -161,6 +160,7 @@ Kyle J Strand <batmanaod@gmail.com> <kyle.j.strand@gmail.com>
|
||||
Kyle J Strand <batmanaod@gmail.com> <kyle.strand@pieinsurance.com>
|
||||
Kyle J Strand <batmanaod@gmail.com> <kyle.strand@rms.com>
|
||||
Laurențiu Nicola <lnicola@dend.ro>
|
||||
lcnr <bastian_kauschke@hotmail.de>
|
||||
Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <lee@leejeffery.co.uk>
|
||||
Lee Wondong <wdlee91@gmail.com>
|
||||
Lennart Kudling <github@kudling.de>
|
||||
|
@ -91,17 +91,6 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
|
||||
if let (None, Some(ty)) =
|
||||
(self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
|
||||
{
|
||||
// FIXME: There's a trade-off here - we can either check that our target span
|
||||
// is contained in `local.span` or not. If we choose to check containment
|
||||
// we can avoid some spurious suggestions (see #72690), but we lose
|
||||
// the ability to report on things like:
|
||||
//
|
||||
// ```
|
||||
// let x = vec![];
|
||||
// ```
|
||||
//
|
||||
// because the target span will be in the macro expansion of `vec![]`.
|
||||
// At present we choose not to check containment.
|
||||
self.found_local_pattern = Some(&*local.pat);
|
||||
self.found_node_ty = Some(ty);
|
||||
}
|
||||
@ -113,10 +102,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
|
||||
if let (None, Some(ty)) =
|
||||
(self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
|
||||
{
|
||||
if self.target_span.contains(param.pat.span) {
|
||||
self.found_arg_pattern = Some(&*param.pat);
|
||||
self.found_node_ty = Some(ty);
|
||||
}
|
||||
self.found_arg_pattern = Some(&*param.pat);
|
||||
self.found_node_ty = Some(ty);
|
||||
}
|
||||
}
|
||||
intravisit::walk_body(self, body);
|
||||
|
@ -751,13 +751,20 @@ impl UnusedDelimLint for UnusedParens {
|
||||
if !Self::is_expr_delims_necessary(inner, followed_by_block)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
&& (ctx != UnusedDelimsCtx::LetScrutineeExpr
|
||||
|| match inner.kind {
|
||||
ast::ExprKind::Binary(
|
||||
rustc_span::source_map::Spanned { node, .. },
|
||||
_,
|
||||
_,
|
||||
) if node.lazy() => false,
|
||||
_ => true,
|
||||
})
|
||||
{
|
||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Let(_, ref expr) => {
|
||||
// FIXME(#60336): Properly handle `let true = (false && true)`
|
||||
// actually needing the parenthesis.
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
expr,
|
||||
|
@ -1462,9 +1462,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
let bound_predicate = predicate.bound_atom();
|
||||
let mut err = match bound_predicate.skip_binder() {
|
||||
ty::PredicateAtom::Trait(data, _) => {
|
||||
let self_ty = data.trait_ref.self_ty();
|
||||
let trait_ref = bound_predicate.rebind(data.trait_ref);
|
||||
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind(), trait_ref);
|
||||
debug!("trait_ref {:?}", trait_ref);
|
||||
|
||||
if predicate.references_error() {
|
||||
return;
|
||||
@ -1479,6 +1478,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// known, since we don't dispatch based on region
|
||||
// relationships.
|
||||
|
||||
// Pick the first substitution that still contains inference variables as the one
|
||||
// we're going to emit an error for. If there are none (see above), fall back to
|
||||
// the substitution for `Self`.
|
||||
let subst = {
|
||||
let substs = data.trait_ref.substs;
|
||||
substs
|
||||
.iter()
|
||||
.find(|s| s.has_infer_types_or_consts())
|
||||
.unwrap_or_else(|| substs[0])
|
||||
};
|
||||
|
||||
// This is kind of a hack: it frequently happens that some earlier
|
||||
// error prevents types from being fully inferred, and then we get
|
||||
// a bunch of uninteresting errors saying something like "<generic
|
||||
@ -1495,21 +1505,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// check upstream for type errors and don't add the obligations to
|
||||
// begin with in those cases.
|
||||
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
|
||||
self.emit_inference_failure_err(
|
||||
body_id,
|
||||
span,
|
||||
self_ty.into(),
|
||||
ErrorCode::E0282,
|
||||
)
|
||||
.emit();
|
||||
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0282).emit();
|
||||
return;
|
||||
}
|
||||
let mut err = self.emit_inference_failure_err(
|
||||
body_id,
|
||||
span,
|
||||
self_ty.into(),
|
||||
ErrorCode::E0283,
|
||||
);
|
||||
let mut err =
|
||||
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283);
|
||||
err.note(&format!("cannot satisfy `{}`", predicate));
|
||||
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
|
||||
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
|
||||
|
@ -250,10 +250,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||
let mut scope_var_ids =
|
||||
self.guard_bindings.pop().expect("should have pushed at least one earlier");
|
||||
for var_id in scope_var_ids.drain(..) {
|
||||
assert!(
|
||||
self.guard_bindings_set.remove(&var_id),
|
||||
"variable should be placed in scope earlier"
|
||||
);
|
||||
self.guard_bindings_set.remove(&var_id);
|
||||
}
|
||||
}
|
||||
self.visit_expr(body);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::super::{navigate::Position, node, DeterministicRng};
|
||||
use super::super::{node, DeterministicRng};
|
||||
use super::Entry::{Occupied, Vacant};
|
||||
use super::*;
|
||||
use crate::boxed::Box;
|
||||
@ -7,7 +7,7 @@ use crate::rc::Rc;
|
||||
use crate::string::{String, ToString};
|
||||
use crate::vec::Vec;
|
||||
use std::convert::TryFrom;
|
||||
use std::iter::FromIterator;
|
||||
use std::iter::{self, FromIterator};
|
||||
use std::mem;
|
||||
use std::ops::Bound::{self, Excluded, Included, Unbounded};
|
||||
use std::ops::RangeBounds;
|
||||
@ -42,19 +42,6 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>
|
||||
}
|
||||
}
|
||||
|
||||
struct SeriesChecker<T> {
|
||||
previous: Option<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy + Debug + Ord> SeriesChecker<T> {
|
||||
fn is_ascending(&mut self, next: T) {
|
||||
if let Some(previous) = self.previous {
|
||||
assert!(previous < next, "{:?} >= {:?}", previous, next);
|
||||
}
|
||||
self.previous = Some(next);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
|
||||
/// Panics if the map (or the code navigating it) is corrupted.
|
||||
fn check(&self)
|
||||
@ -63,44 +50,10 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
|
||||
{
|
||||
if let Some(root) = &self.root {
|
||||
let root_node = root.node_as_ref();
|
||||
let mut checker = SeriesChecker { previous: None };
|
||||
let mut internal_length = 0;
|
||||
let mut internal_kv_count = 0;
|
||||
let mut leaf_length = 0;
|
||||
root_node.visit_nodes_in_order(|pos| match pos {
|
||||
Position::Leaf(node) => {
|
||||
let is_root = root_node.height() == 0;
|
||||
let min_len = if is_root { 0 } else { node::MIN_LEN };
|
||||
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
|
||||
|
||||
for idx in 0..node.len() {
|
||||
let key = *unsafe { node.key_at(idx) };
|
||||
checker.is_ascending(key);
|
||||
}
|
||||
leaf_length += node.len();
|
||||
}
|
||||
Position::Internal(node) => {
|
||||
let is_root = root_node.height() == node.height();
|
||||
let min_len = if is_root { 1 } else { node::MIN_LEN };
|
||||
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
|
||||
|
||||
for idx in 0..=node.len() {
|
||||
let edge = unsafe { node::Handle::new_edge(node, idx) };
|
||||
assert!(edge.descend().ascend().ok().unwrap() == edge);
|
||||
}
|
||||
|
||||
internal_length += node.len();
|
||||
}
|
||||
Position::InternalKV(kv) => {
|
||||
let key = *kv.into_kv().0;
|
||||
checker.is_ascending(key);
|
||||
|
||||
internal_kv_count += 1;
|
||||
}
|
||||
});
|
||||
assert_eq!(internal_length, internal_kv_count);
|
||||
assert_eq!(root_node.calc_length(), internal_length + leaf_length);
|
||||
assert_eq!(self.length, internal_length + leaf_length);
|
||||
assert!(root_node.ascend().is_err());
|
||||
root_node.assert_back_pointers();
|
||||
root_node.assert_ascending();
|
||||
assert_eq!(self.length, root_node.assert_and_add_lengths());
|
||||
} else {
|
||||
assert_eq!(self.length, 0);
|
||||
}
|
||||
@ -116,28 +69,7 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
|
||||
K: Debug,
|
||||
{
|
||||
if let Some(root) = self.root.as_ref() {
|
||||
let mut result = String::new();
|
||||
let root_node = root.node_as_ref();
|
||||
root_node.visit_nodes_in_order(|pos| match pos {
|
||||
Position::Leaf(leaf) => {
|
||||
let depth = root_node.height();
|
||||
let indent = " ".repeat(depth);
|
||||
result += &format!("\n{}", indent);
|
||||
for idx in 0..leaf.len() {
|
||||
if idx > 0 {
|
||||
result += ", ";
|
||||
}
|
||||
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
|
||||
}
|
||||
}
|
||||
Position::Internal(_) => {}
|
||||
Position::InternalKV(kv) => {
|
||||
let depth = root_node.height() - kv.into_node().height();
|
||||
let indent = " ".repeat(depth);
|
||||
result += &format!("\n{}{:?}", indent, kv.into_kv().0);
|
||||
}
|
||||
});
|
||||
result
|
||||
root.node_as_ref().dump_keys()
|
||||
} else {
|
||||
String::from("not yet allocated")
|
||||
}
|
||||
@ -170,7 +102,6 @@ fn test_levels() {
|
||||
let last_key = *map.last_key_value().unwrap().0;
|
||||
map.insert(last_key + 1, ());
|
||||
}
|
||||
println!("{}", map.dump_keys());
|
||||
map.check();
|
||||
// Structure:
|
||||
// - 1 element in internal root node with 2 children
|
||||
@ -372,7 +303,7 @@ fn test_iter_rev() {
|
||||
fn do_test_iter_mut_mutation<T>(size: usize)
|
||||
where
|
||||
T: Copy + Debug + Ord + TryFrom<usize>,
|
||||
<T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
|
||||
<T as TryFrom<usize>>::Error: Debug,
|
||||
{
|
||||
let zero = T::try_from(0).unwrap();
|
||||
let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
|
||||
@ -857,7 +788,7 @@ mod test_drain_filter {
|
||||
fn consuming_nothing() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
let mut map: BTreeMap<_, _> = pairs.collect();
|
||||
assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
|
||||
assert!(map.drain_filter(|_, _| false).eq(iter::empty()));
|
||||
map.check();
|
||||
}
|
||||
|
||||
@ -878,7 +809,7 @@ mod test_drain_filter {
|
||||
*v += 6;
|
||||
false
|
||||
})
|
||||
.eq(std::iter::empty())
|
||||
.eq(iter::empty())
|
||||
);
|
||||
assert!(map.keys().copied().eq(0..3));
|
||||
assert!(map.values().copied().eq(6..9));
|
||||
|
@ -1,6 +1,111 @@
|
||||
use super::super::navigate;
|
||||
use super::*;
|
||||
use crate::fmt::Debug;
|
||||
use crate::string::String;
|
||||
use core::cmp::Ordering::*;
|
||||
|
||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
|
||||
pub fn assert_back_pointers(self) {
|
||||
match self.force() {
|
||||
ForceResult::Leaf(_) => {}
|
||||
ForceResult::Internal(node) => {
|
||||
for idx in 0..=node.len() {
|
||||
let edge = unsafe { Handle::new_edge(node, idx) };
|
||||
let child = edge.descend();
|
||||
assert!(child.ascend().ok() == Some(edge));
|
||||
child.assert_back_pointers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assert_ascending(self)
|
||||
where
|
||||
K: Copy + Debug + Ord,
|
||||
{
|
||||
struct SeriesChecker<T> {
|
||||
previous: Option<T>,
|
||||
}
|
||||
impl<T: Copy + Debug + Ord> SeriesChecker<T> {
|
||||
fn is_ascending(&mut self, next: T) {
|
||||
if let Some(previous) = self.previous {
|
||||
assert!(previous < next, "{:?} >= {:?}", previous, next);
|
||||
}
|
||||
self.previous = Some(next);
|
||||
}
|
||||
}
|
||||
|
||||
let mut checker = SeriesChecker { previous: None };
|
||||
self.visit_nodes_in_order(|pos| match pos {
|
||||
navigate::Position::Leaf(node) => {
|
||||
for idx in 0..node.len() {
|
||||
let key = *unsafe { node.key_at(idx) };
|
||||
checker.is_ascending(key);
|
||||
}
|
||||
}
|
||||
navigate::Position::InternalKV(kv) => {
|
||||
let key = *kv.into_kv().0;
|
||||
checker.is_ascending(key);
|
||||
}
|
||||
navigate::Position::Internal(_) => {}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn assert_and_add_lengths(self) -> usize {
|
||||
let mut internal_length = 0;
|
||||
let mut internal_kv_count = 0;
|
||||
let mut leaf_length = 0;
|
||||
self.visit_nodes_in_order(|pos| match pos {
|
||||
navigate::Position::Leaf(node) => {
|
||||
let is_root = self.height() == 0;
|
||||
let min_len = if is_root { 0 } else { MIN_LEN };
|
||||
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
|
||||
leaf_length += node.len();
|
||||
}
|
||||
navigate::Position::Internal(node) => {
|
||||
let is_root = self.height() == node.height();
|
||||
let min_len = if is_root { 1 } else { MIN_LEN };
|
||||
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
|
||||
internal_length += node.len();
|
||||
}
|
||||
navigate::Position::InternalKV(_) => {
|
||||
internal_kv_count += 1;
|
||||
}
|
||||
});
|
||||
assert_eq!(internal_length, internal_kv_count);
|
||||
let total = internal_length + leaf_length;
|
||||
assert_eq!(self.calc_length(), total);
|
||||
total
|
||||
}
|
||||
|
||||
pub fn dump_keys(self) -> String
|
||||
where
|
||||
K: Debug,
|
||||
{
|
||||
let mut result = String::new();
|
||||
self.visit_nodes_in_order(|pos| match pos {
|
||||
navigate::Position::Leaf(leaf) => {
|
||||
let depth = self.height();
|
||||
let indent = " ".repeat(depth);
|
||||
result += &format!("\n{}", indent);
|
||||
for idx in 0..leaf.len() {
|
||||
if idx > 0 {
|
||||
result += ", ";
|
||||
}
|
||||
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
|
||||
}
|
||||
}
|
||||
navigate::Position::Internal(_) => {}
|
||||
navigate::Position::InternalKV(kv) => {
|
||||
let depth = self.height() - kv.into_node().height();
|
||||
let indent = " ".repeat(depth);
|
||||
result += &format!("\n{}{:?}", indent, kv.into_kv().0);
|
||||
}
|
||||
});
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_splitpoint() {
|
||||
for idx in 0..=CAPACITY {
|
||||
|
@ -102,7 +102,9 @@ mod break_keyword {}
|
||||
|
||||
#[doc(keyword = "const")]
|
||||
//
|
||||
/// Compile-time constants and deterministic functions.
|
||||
/// Compile-time constants and compile-time evaluable functions.
|
||||
///
|
||||
/// ## Compile-time constants
|
||||
///
|
||||
/// Sometimes a certain value is used many times throughout a program, and it can become
|
||||
/// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
|
||||
@ -145,15 +147,28 @@ mod break_keyword {}
|
||||
///
|
||||
/// Constants, like statics, should always be in `SCREAMING_SNAKE_CASE`.
|
||||
///
|
||||
/// For more detail on `const`, see the [Rust Book] or the [Reference].
|
||||
///
|
||||
/// ## Compile-time evaluable functions
|
||||
///
|
||||
/// The other main use of the `const` keyword is in `const fn`. This marks a function as being
|
||||
/// callable in the body of a `const` or `static` item and in array initializers (commonly called
|
||||
/// "const contexts"). `const fn` are restricted in the set of operations they can perform, to
|
||||
/// ensure that they can be evaluated at compile-time. See the [Reference][const-eval] for more
|
||||
/// detail.
|
||||
///
|
||||
/// Turning a `fn` into a `const fn` has no effect on run-time uses of that function.
|
||||
///
|
||||
/// ## Other uses of `const`
|
||||
///
|
||||
/// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
|
||||
/// T` and `*mut T`. More about `const` as used in raw pointers can be read at the Rust docs for the [pointer primitive].
|
||||
///
|
||||
/// For more detail on `const`, see the [Rust Book] or the [Reference].
|
||||
///
|
||||
/// [pointer primitive]: primitive.pointer.html
|
||||
/// [Rust Book]:
|
||||
/// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
|
||||
/// [Reference]: ../reference/items/constant-items.html
|
||||
/// [const-eval]: ../reference/const_eval.html
|
||||
mod const_keyword {}
|
||||
|
||||
#[doc(keyword = "continue")]
|
||||
|
@ -456,10 +456,7 @@ impl Ipv4Addr {
|
||||
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||
#[stable(since = "1.7.0", feature = "ip_17")]
|
||||
pub const fn is_link_local(&self) -> bool {
|
||||
match self.octets() {
|
||||
[169, 254, ..] => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.octets(), [169, 254, ..])
|
||||
}
|
||||
|
||||
/// Returns [`true`] if the address appears to be globally routable.
|
||||
@ -1262,10 +1259,7 @@ impl Ipv6Addr {
|
||||
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
|
||||
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
|
||||
pub const fn is_unicast_link_local_strict(&self) -> bool {
|
||||
(self.segments()[0] & 0xffff) == 0xfe80
|
||||
&& (self.segments()[1] & 0xffff) == 0
|
||||
&& (self.segments()[2] & 0xffff) == 0
|
||||
&& (self.segments()[3] & 0xffff) == 0
|
||||
matches!(self.segments(), [0xfe80, 0, 0, 0, ..])
|
||||
}
|
||||
|
||||
/// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
|
||||
|
@ -220,6 +220,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
|
||||
if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
|
||||
}
|
||||
|
||||
// On Unix-like platforms, libc::abort will unregister signal handlers
|
||||
// including the SIGABRT handler, preventing the abort from being blocked, and
|
||||
// fclose streams, with the side effect of flushing them so libc buffered
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::sys::cvt_nz;
|
||||
|
||||
pub struct Mutex {
|
||||
inner: UnsafeCell<libc::pthread_mutex_t>,
|
||||
@ -51,14 +52,11 @@ impl Mutex {
|
||||
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
|
||||
// re-lock it from the same thread, thus avoiding undefined behavior.
|
||||
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
|
||||
let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
|
||||
debug_assert_eq!(r, 0);
|
||||
let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
|
||||
debug_assert_eq!(r, 0);
|
||||
let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
|
||||
debug_assert_eq!(r, 0);
|
||||
let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
|
||||
debug_assert_eq!(r, 0);
|
||||
cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
|
||||
let attr = PthreadMutexAttr(&mut attr);
|
||||
cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL))
|
||||
.unwrap();
|
||||
cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn lock(&self) {
|
||||
@ -106,15 +104,11 @@ impl ReentrantMutex {
|
||||
|
||||
pub unsafe fn init(&self) {
|
||||
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
|
||||
let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
|
||||
debug_assert_eq!(result, 0);
|
||||
let result =
|
||||
libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE);
|
||||
debug_assert_eq!(result, 0);
|
||||
let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
|
||||
debug_assert_eq!(result, 0);
|
||||
let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
|
||||
debug_assert_eq!(result, 0);
|
||||
cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
|
||||
let attr = PthreadMutexAttr(&mut attr);
|
||||
cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE))
|
||||
.unwrap();
|
||||
cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
|
||||
}
|
||||
|
||||
pub unsafe fn lock(&self) {
|
||||
@ -137,3 +131,14 @@ impl ReentrantMutex {
|
||||
debug_assert_eq!(result, 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct PthreadMutexAttr<'a>(&'a mut MaybeUninit<libc::pthread_mutexattr_t>);
|
||||
|
||||
impl Drop for PthreadMutexAttr<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr());
|
||||
debug_assert_eq!(result, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ impl Command {
|
||||
envp: Option<&CStringArray>,
|
||||
) -> io::Result<Option<Process>> {
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::sys;
|
||||
use crate::sys::{self, cvt_nz};
|
||||
|
||||
if self.get_gid().is_some()
|
||||
|| self.get_uid().is_some()
|
||||
@ -343,10 +343,6 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
fn cvt_nz(error: libc::c_int) -> io::Result<()> {
|
||||
if error == 0 { Ok(()) } else { Err(io::Error::from_raw_os_error(error)) }
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut attrs = MaybeUninit::uninit();
|
||||
cvt_nz(libc::posix_spawnattr_init(attrs.as_mut_ptr()))?;
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{t, VERSION};
|
||||
use std::fmt::Write as _;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::{
|
||||
env, fmt, fs,
|
||||
@ -196,10 +197,17 @@ simply delete the `pre-commit` file from .git/hooks."
|
||||
|
||||
Ok(if should_install {
|
||||
let src = src_path.join("src").join("etc").join("pre-commit.sh");
|
||||
let dst = src_path.join(".git").join("hooks").join("pre-commit");
|
||||
match fs::hard_link(src, dst) {
|
||||
let git = t!(Command::new("git").args(&["rev-parse", "--git-common-dir"]).output().map(
|
||||
|output| {
|
||||
assert!(output.status.success(), "failed to run `git`");
|
||||
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
|
||||
}
|
||||
));
|
||||
let dst = git.join("hooks").join("pre-commit");
|
||||
match fs::hard_link(src, &dst) {
|
||||
Err(e) => println!(
|
||||
"x.py encountered an error -- do you already have the git hook installed?\n{}",
|
||||
"error: could not create hook {}: do you already have the git hook installed?\n{}",
|
||||
dst.display(),
|
||||
e
|
||||
),
|
||||
Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"),
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:5
|
||||
--> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27
|
||||
|
|
||||
LL | with_closure(|x: u32, y| {});
|
||||
| ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure`
|
||||
| ^ consider giving this closure parameter a type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ex = |x| {
|
||||
let_(add(x,x), |y| { //~ ERROR type annotations needed
|
||||
let ex = |x| { //~ ERROR type annotations needed
|
||||
let_(add(x,x), |y| {
|
||||
let_(add(x, x), |x|x)})};
|
||||
}
|
||||
|
@ -1,13 +1,8 @@
|
||||
error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>`
|
||||
--> $DIR/issue-23046.rs:18:9
|
||||
error[E0282]: type annotations needed for `Expr<'_, VAR>`
|
||||
--> $DIR/issue-23046.rs:17:15
|
||||
|
|
||||
LL | let_(add(x,x), |y| {
|
||||
| ^^^^ cannot infer type for type parameter `VAR` declared on the function `let_`
|
||||
|
|
||||
help: give this closure an explicit return type without `_` placeholders
|
||||
|
|
||||
LL | let_(add(x, x), |x|-> Expr<'_, _> { x })})};
|
||||
| ^^^^^^^^^^^^^^^^ ^
|
||||
LL | let ex = |x| {
|
||||
| ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:7:5
|
||||
|
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
@ -13,11 +13,13 @@ error[E0282]: type annotations needed
|
||||
LL | |x| String::from("x".as_ref());
|
||||
| ^ consider giving this closure parameter a type
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
error[E0283]: type annotations needed for `&T`
|
||||
--> $DIR/issue-72690.rs:15:17
|
||||
|
|
||||
LL | let _ = "x".as_ref();
|
||||
| ^^^^^^ cannot infer type for type `str`
|
||||
| - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef`
|
||||
| |
|
||||
| consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified
|
||||
|
|
||||
= note: cannot satisfy `str: AsRef<_>`
|
||||
|
||||
@ -25,7 +27,7 @@ error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:19:5
|
||||
|
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
@ -34,7 +36,7 @@ error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:25:5
|
||||
|
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
@ -43,41 +45,34 @@ error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:33:5
|
||||
|
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
|
||||
error[E0283]: type annotations needed for `String`
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:41:5
|
||||
|
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
LL | let _ = String::from("x");
|
||||
| - consider giving this pattern a type
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
|
||||
error[E0283]: type annotations needed for `String`
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:47:5
|
||||
|
|
||||
LL | let _ = String::from("x");
|
||||
| - consider giving this pattern a type
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
|
||||
error[E0283]: type annotations needed for `String`
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/issue-72690.rs:55:5
|
||||
|
|
||||
LL | let _ = String::from("x");
|
||||
| - consider giving this pattern a type
|
||||
...
|
||||
LL | String::from("x".as_ref());
|
||||
| ^^^^^^^^^^^^ cannot infer type for struct `String`
|
||||
| ^^^^^^^^^^^^ cannot infer type for reference `&_`
|
||||
|
|
||||
= note: cannot satisfy `String: From<&_>`
|
||||
= note: required by `from`
|
||||
|
19
src/test/ui/issues/issue-78115.rs
Normal file
19
src/test/ui/issues/issue-78115.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Regression test for issue #78115: "ICE: variable should be placed in scope earlier"
|
||||
|
||||
// check-pass
|
||||
// edition:2018
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Foo {
|
||||
a: ()
|
||||
}
|
||||
|
||||
async fn _bar() {
|
||||
let foo = Foo { a: () };
|
||||
match foo {
|
||||
Foo { a: _a } | Foo { a: _a } if true => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -60,6 +60,8 @@ fn main() {
|
||||
if (v == X { y: true }) {}
|
||||
if (X { y: true } == v) {}
|
||||
if (X { y: false }.y) {}
|
||||
// this shouldn't warn, because the parens are necessary to disambiguate let chains
|
||||
if let true = (true && false) {}
|
||||
|
||||
while (X { y: false }.foo(true)) {}
|
||||
while (true | X { y: false }.y) {}
|
||||
|
@ -60,6 +60,8 @@ fn main() {
|
||||
if (v == X { y: true }) {}
|
||||
if (X { y: true } == v) {}
|
||||
if (X { y: false }.y) {}
|
||||
// this shouldn't warn, because the parens are necessary to disambiguate let chains
|
||||
if let true = (true && false) {}
|
||||
|
||||
while (X { y: false }.foo(true)) {}
|
||||
while (true | X { y: false }.y) {}
|
||||
|
@ -83,25 +83,25 @@ LL | while let 1 = (2) {}
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around method argument
|
||||
--> $DIR/lint-unnecessary-parens.rs:71:24
|
||||
--> $DIR/lint-unnecessary-parens.rs:73:24
|
||||
|
|
||||
LL | X { y: false }.foo((true));
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:73:18
|
||||
--> $DIR/lint-unnecessary-parens.rs:75:18
|
||||
|
|
||||
LL | let mut _a = (0);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:74:10
|
||||
--> $DIR/lint-unnecessary-parens.rs:76:10
|
||||
|
|
||||
LL | _a = (0);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:75:11
|
||||
--> $DIR/lint-unnecessary-parens.rs:77:11
|
||||
|
|
||||
LL | _a += (1);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user