Skip to content

Commit c5c9494

Browse files
committed
Auto merge of rust-lang#91627 - matthiaskrgr:rollup-z3e2peg, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - rust-lang#87614 (Recommend fix `count()` -> `len()` on slices) - rust-lang#91065 (Add test for evaluate_obligation: Ok(EvaluatedToOkModuloRegions) ICE) - rust-lang#91312 (Fix AnonConst ICE) - rust-lang#91341 (Add `array::IntoIter::{empty, from_raw_parts}`) - rust-lang#91493 (Remove a dead code path.) - rust-lang#91503 (Tweak "call this function" suggestion to have smaller span) - rust-lang#91547 (Suggest try_reserve in try_reserve_exact) - rust-lang#91562 (Pretty print async block without redundant space) - rust-lang#91620 (Update books) - rust-lang#91622 (:arrow_up: rust-analyzer) Failed merges: - rust-lang#91571 (Remove unneeded access to pretty printer's `s` field in favor of deref) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c67497a + 099412e commit c5c9494

31 files changed

+606
-52
lines changed

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2077,7 +2077,6 @@ impl<'a> State<'a> {
20772077
ast::ExprKind::Async(capture_clause, _, ref blk) => {
20782078
self.word_nbsp("async");
20792079
self.print_capture_clause(capture_clause);
2080-
self.s.space();
20812080
// cbox/ibox in analogy to the `ExprKind::Block` arm above
20822081
self.cbox(INDENT_UNIT);
20832082
self.ibox(0);

Diff for: compiler/rustc_infer/src/infer/opaque_types.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -461,10 +461,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
461461
if let Some(def_id) = def_id.as_local() {
462462
let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
463463
let parent_def_id = self.infcx.defining_use_anchor;
464-
let def_scope_default = || {
465-
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
466-
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
467-
};
468464
let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind
469465
{
470466
// Anonymous `impl Trait`
@@ -481,7 +477,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
481477
}) => {
482478
(may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin)
483479
}
484-
_ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias),
480+
ref itemkind => {
481+
span_bug!(
482+
self.value_span,
483+
"weird opaque type: {:#?}, {:#?}",
484+
ty.kind(),
485+
itemkind
486+
)
487+
}
485488
};
486489
if in_definition_scope {
487490
let opaque_type_key =

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ symbols! {
499499
core_panic_macro,
500500
cosf32,
501501
cosf64,
502+
count,
502503
cr,
503504
crate_id,
504505
crate_in_paths,

Diff for: compiler/rustc_typeck/src/check/method/suggest.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6767
}
6868
}
6969

70+
fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
71+
self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
72+
}
73+
7074
pub fn report_method_error(
7175
&self,
7276
mut span: Span,
@@ -691,7 +695,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
691695

692696
let mut restrict_type_params = false;
693697
let mut unsatisfied_bounds = false;
694-
if !unsatisfied_predicates.is_empty() {
698+
if item_name.name == sym::count && self.is_slice_ty(actual, span) {
699+
let msg = "consider using `len` instead";
700+
if let SelfSource::MethodCall(_expr) = source {
701+
err.span_suggestion_short(
702+
span,
703+
msg,
704+
String::from("len"),
705+
Applicability::MachineApplicable,
706+
);
707+
} else {
708+
err.span_label(span, msg);
709+
}
710+
if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
711+
let iterator_trait = self.tcx.def_path_str(iterator_trait);
712+
err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement"));
713+
}
714+
} else if !unsatisfied_predicates.is_empty() {
695715
let def_span = |def_id| {
696716
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
697717
};
@@ -990,9 +1010,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9901010
}
9911011
}
9921012

993-
let mut fallback_span = true;
994-
let msg = "remove this method call";
9951013
if item_name.name == sym::as_str && actual.peel_refs().is_str() {
1014+
let msg = "remove this method call";
1015+
let mut fallback_span = true;
9961016
if let SelfSource::MethodCall(expr) = source {
9971017
let call_expr =
9981018
self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));

Diff for: compiler/rustc_typeck/src/check/op.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
492492
) -> bool /* did we suggest to call a function because of missing parentheses? */ {
493493
err.span_label(span, ty.to_string());
494494
if let FnDef(def_id, _) = *ty.kind() {
495-
let source_map = self.tcx.sess.source_map();
496495
if !self.tcx.has_typeck_results(def_id) {
497496
return false;
498497
}
@@ -517,20 +516,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
517516
.lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign))
518517
.is_ok()
519518
{
520-
if let Ok(snippet) = source_map.span_to_snippet(span) {
521-
let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() {
522-
(format!("{}( /* arguments */ )", snippet), Applicability::HasPlaceholders)
523-
} else {
524-
(format!("{}()", snippet), Applicability::MaybeIncorrect)
525-
};
519+
let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() {
520+
("( /* arguments */ )".to_string(), Applicability::HasPlaceholders)
521+
} else {
522+
("()".to_string(), Applicability::MaybeIncorrect)
523+
};
526524

527-
err.span_suggestion(
528-
span,
529-
"you might have forgotten to call this function",
530-
variable_snippet,
531-
applicability,
532-
);
533-
}
525+
err.span_suggestion_verbose(
526+
span.shrink_to_hi(),
527+
"you might have forgotten to call this function",
528+
variable_snippet,
529+
applicability,
530+
);
534531
return true;
535532
}
536533
}

Diff for: compiler/rustc_typeck/src/collect/type_of.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
172172
// We've encountered an `AnonConst` in some path, so we need to
173173
// figure out which generic parameter it corresponds to and return
174174
// the relevant type.
175-
let (arg_index, segment) = path
175+
let filtered = path
176176
.segments
177177
.iter()
178178
.filter_map(|seg| seg.args.map(|args| (args.args, seg)))
@@ -181,10 +181,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
181181
.filter(|arg| arg.is_const())
182182
.position(|arg| arg.id() == hir_id)
183183
.map(|index| (index, seg))
184-
})
185-
.unwrap_or_else(|| {
186-
bug!("no arg matching AnonConst in path");
187184
});
185+
let (arg_index, segment) = match filtered {
186+
None => {
187+
tcx.sess.delay_span_bug(
188+
tcx.def_span(def_id),
189+
"no arg matching AnonConst in path",
190+
);
191+
return None;
192+
}
193+
Some(inner) => inner,
194+
};
188195

189196
// Try to use the segment resolution if it is valid, otherwise we
190197
// default to the path resolution.

Diff for: library/alloc/src/collections/vec_deque/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -720,9 +720,9 @@ impl<T, A: Allocator> VecDeque<T, A> {
720720
///
721721
/// Note that the allocator may give the collection more space than it
722722
/// requests. Therefore, capacity can not be relied upon to be precisely
723-
/// minimal. Prefer [`reserve`] if future insertions are expected.
723+
/// minimal. Prefer [`try_reserve`] if future insertions are expected.
724724
///
725-
/// [`reserve`]: VecDeque::reserve
725+
/// [`try_reserve`]: VecDeque::try_reserve
726726
///
727727
/// # Errors
728728
///

Diff for: library/alloc/src/string.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1044,9 +1044,9 @@ impl String {
10441044
///
10451045
/// Note that the allocator may give the collection more space than it
10461046
/// requests. Therefore, capacity can not be relied upon to be precisely
1047-
/// minimal. Prefer [`reserve`] if future insertions are expected.
1047+
/// minimal. Prefer [`try_reserve`] if future insertions are expected.
10481048
///
1049-
/// [`reserve`]: String::reserve
1049+
/// [`try_reserve`]: String::try_reserve
10501050
///
10511051
/// # Errors
10521052
///

Diff for: library/alloc/src/vec/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -881,9 +881,9 @@ impl<T, A: Allocator> Vec<T, A> {
881881
///
882882
/// Note that the allocator may give the collection more space than it
883883
/// requests. Therefore, capacity can not be relied upon to be precisely
884-
/// minimal. Prefer [`reserve`] if future insertions are expected.
884+
/// minimal. Prefer [`try_reserve`] if future insertions are expected.
885885
///
886-
/// [`reserve`]: Vec::reserve
886+
/// [`try_reserve`]: Vec::try_reserve
887887
///
888888
/// # Errors
889889
///

Diff for: library/core/src/array/iter.rs

+129
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,135 @@ impl<T, const N: usize> IntoIter<T, N> {
8484
IntoIterator::into_iter(array)
8585
}
8686

87+
/// Creates an iterator over the elements in a partially-initialized buffer.
88+
///
89+
/// If you have a fully-initialized array, then use [`IntoIterator`].
90+
/// But this is useful for returning partial results from unsafe code.
91+
///
92+
/// # Safety
93+
///
94+
/// - The `buffer[initialized]` elements must all be initialized.
95+
/// - The range must be canonical, with `initialized.start <= initialized.end`.
96+
/// - The range must in in-bounds for the buffer, with `initialized.end <= N`.
97+
/// (Like how indexing `[0][100..100]` fails despite the range being empty.)
98+
///
99+
/// It's sound to have more elements initialized than mentioned, though that
100+
/// will most likely result in them being leaked.
101+
///
102+
/// # Examples
103+
///
104+
/// ```
105+
/// #![feature(array_into_iter_constructors)]
106+
///
107+
/// #![feature(maybe_uninit_array_assume_init)]
108+
/// #![feature(maybe_uninit_uninit_array)]
109+
/// use std::array::IntoIter;
110+
/// use std::mem::MaybeUninit;
111+
///
112+
/// # // Hi! Thanks for reading the code. This is restricted to `Copy` because
113+
/// # // otherwise it could leak. A fully-general version this would need a drop
114+
/// # // guard to handle panics from the iterator, but this works for an example.
115+
/// fn next_chunk<T: Copy, const N: usize>(
116+
/// it: &mut impl Iterator<Item = T>,
117+
/// ) -> Result<[T; N], IntoIter<T, N>> {
118+
/// let mut buffer = MaybeUninit::uninit_array();
119+
/// let mut i = 0;
120+
/// while i < N {
121+
/// match it.next() {
122+
/// Some(x) => {
123+
/// buffer[i].write(x);
124+
/// i += 1;
125+
/// }
126+
/// None => {
127+
/// // SAFETY: We've initialized the first `i` items
128+
/// unsafe {
129+
/// return Err(IntoIter::new_unchecked(buffer, 0..i));
130+
/// }
131+
/// }
132+
/// }
133+
/// }
134+
///
135+
/// // SAFETY: We've initialized all N items
136+
/// unsafe { Ok(MaybeUninit::array_assume_init(buffer)) }
137+
/// }
138+
///
139+
/// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap();
140+
/// assert_eq!(r, [10, 11, 12, 13]);
141+
/// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err();
142+
/// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
143+
/// ```
144+
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
145+
#[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
146+
pub const unsafe fn new_unchecked(
147+
buffer: [MaybeUninit<T>; N],
148+
initialized: Range<usize>,
149+
) -> Self {
150+
Self { data: buffer, alive: initialized }
151+
}
152+
153+
/// Creates an iterator over `T` which returns no elements.
154+
///
155+
/// If you just need an empty iterator, then use
156+
/// [`iter::empty()`](crate::iter::empty) instead.
157+
/// And if you need an empty array, use `[]`.
158+
///
159+
/// But this is useful when you need an `array::IntoIter<T, N>` *specifically*.
160+
///
161+
/// # Examples
162+
///
163+
/// ```
164+
/// #![feature(array_into_iter_constructors)]
165+
/// use std::array::IntoIter;
166+
///
167+
/// let empty = IntoIter::<i32, 3>::empty();
168+
/// assert_eq!(empty.len(), 0);
169+
/// assert_eq!(empty.as_slice(), &[]);
170+
///
171+
/// let empty = IntoIter::<std::convert::Infallible, 200>::empty();
172+
/// assert_eq!(empty.len(), 0);
173+
/// ```
174+
///
175+
/// `[1, 2].into_iter()` and `[].into_iter()` have different types
176+
/// ```should_fail,edition2021
177+
/// #![feature(array_into_iter_constructors)]
178+
/// use std::array::IntoIter;
179+
///
180+
/// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
181+
/// if b {
182+
/// [1, 2, 3, 4].into_iter()
183+
/// } else {
184+
/// [].into_iter() // error[E0308]: mismatched types
185+
/// }
186+
/// }
187+
/// ```
188+
///
189+
/// But using this method you can get an empty iterator of appropriate size:
190+
/// ```edition2021
191+
/// #![feature(array_into_iter_constructors)]
192+
/// use std::array::IntoIter;
193+
///
194+
/// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
195+
/// if b {
196+
/// [1, 2, 3, 4].into_iter()
197+
/// } else {
198+
/// IntoIter::empty()
199+
/// }
200+
/// }
201+
///
202+
/// assert_eq!(get_bytes(true).collect::<Vec<_>>(), vec![1, 2, 3, 4]);
203+
/// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
204+
/// ```
205+
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
206+
#[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
207+
pub const fn empty() -> Self {
208+
let buffer = MaybeUninit::uninit_array();
209+
let initialized = 0..0;
210+
211+
// SAFETY: We're telling it that none of the elements are initialized,
212+
// which is trivially true. And ∀N: usize, 0 <= N.
213+
unsafe { Self::new_unchecked(buffer, initialized) }
214+
}
215+
87216
/// Returns an immutable slice of all elements that have not been yielded
88217
/// yet.
89218
#[stable(feature = "array_value_iter", since = "1.51.0")]

Diff for: library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#![feature(const_align_of_val)]
102102
#![feature(const_alloc_layout)]
103103
#![feature(const_arguments_as_str)]
104+
#![feature(const_array_into_iter_constructors)]
104105
#![feature(const_bigint_helper_methods)]
105106
#![feature(const_caller_location)]
106107
#![feature(const_cell_into_inner)]
@@ -138,6 +139,7 @@
138139
#![feature(const_type_name)]
139140
#![feature(const_default_impls)]
140141
#![feature(duration_consts_float)]
142+
#![feature(maybe_uninit_uninit_array)]
141143
#![feature(ptr_metadata)]
142144
#![feature(slice_ptr_get)]
143145
#![feature(str_internals)]

Diff for: src/doc/book

Submodule book updated 34 files

Diff for: src/doc/edition-guide

Diff for: src/doc/nomicon

Diff for: src/doc/rust-by-example

0 commit comments

Comments
 (0)