Auto merge of #89158 - the8472:rollup-3e4ijth, r=the8472
Rollup of 12 pull requests Successful merges: - #88795 (Print a note if a character literal contains a variation selector) - #89015 (core::ascii::escape_default: reduce struct size) - #89078 (Cleanup: Remove needless reference in ParentHirIterator) - #89086 (Stabilize `Iterator::map_while`) - #89096 ([bootstrap] Improve the error message when `ninja` is not found to link to installation instructions) - #89113 (dont `.ensure()` the `thir_abstract_const` query call in `mir_build`) - #89114 (Fixes a technicality regarding the size of C's `char` type) - #89115 (⬆️ rust-analyzer) - #89126 (Fix ICE when `indirect_structural_match` is allowed) - #89141 (Impl `Error` for `FromSecsError` without foreign type) - #89142 (Fix match for placeholder region) - #89147 (add case for checking const refs in check_const_value_eq) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d8d1d1059a
29 changed files with 275 additions and 67 deletions
|
@ -18,7 +18,6 @@
|
||||||
#![feature(extend_one)]
|
#![feature(extend_one)]
|
||||||
#![feature(hash_raw_entry)]
|
#![feature(hash_raw_entry)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(iter_map_while)]
|
|
||||||
#![feature(maybe_uninit_uninit_array)]
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
|
@ -83,12 +83,12 @@ pub struct Map<'hir> {
|
||||||
|
|
||||||
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
||||||
/// Constructed using `tcx.hir().parent_iter(hir_id)`.
|
/// Constructed using `tcx.hir().parent_iter(hir_id)`.
|
||||||
pub struct ParentHirIterator<'map, 'hir> {
|
pub struct ParentHirIterator<'hir> {
|
||||||
current_id: HirId,
|
current_id: HirId,
|
||||||
map: &'map Map<'hir>,
|
map: Map<'hir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
|
impl<'hir> Iterator for ParentHirIterator<'hir> {
|
||||||
type Item = (HirId, Node<'hir>);
|
type Item = (HirId, Node<'hir>);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -115,12 +115,12 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
|
||||||
|
|
||||||
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
/// An iterator that walks up the ancestor tree of a given `HirId`.
|
||||||
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
|
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
|
||||||
pub struct ParentOwnerIterator<'map, 'hir> {
|
pub struct ParentOwnerIterator<'hir> {
|
||||||
current_id: HirId,
|
current_id: HirId,
|
||||||
map: &'map Map<'hir>,
|
map: Map<'hir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
|
impl<'hir> Iterator for ParentOwnerIterator<'hir> {
|
||||||
type Item = (HirId, OwnerNode<'hir>);
|
type Item = (HirId, OwnerNode<'hir>);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -588,13 +588,13 @@ impl<'hir> Map<'hir> {
|
||||||
|
|
||||||
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
||||||
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
||||||
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
|
pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
|
||||||
ParentHirIterator { current_id, map: self }
|
ParentHirIterator { current_id, map: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
||||||
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
||||||
pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> {
|
pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
|
||||||
ParentOwnerIterator { current_id, map: self }
|
ParentOwnerIterator { current_id, map: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,10 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
|
||||||
ty::ReFree(ref free_region) => {
|
ty::ReFree(ref free_region) => {
|
||||||
free_region.hash_stable(hcx, hasher);
|
free_region.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
ty::ReVar(..) | ty::RePlaceholder(..) => {
|
ty::RePlaceholder(p) => {
|
||||||
|
p.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ty::ReVar(..) => {
|
||||||
bug!("StableHasher: unexpected region {:?}", *self)
|
bug!("StableHasher: unexpected region {:?}", *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -639,6 +639,15 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
|
||||||
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
|
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
|
||||||
|
if a.ty.is_ref() || b.ty.is_ref() =>
|
||||||
|
{
|
||||||
|
if a.ty.is_ref() && b.ty.is_ref() {
|
||||||
|
alloc_a == alloc_b
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
|
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
|
||||||
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
|
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
|
||||||
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
|
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
|
||||||
|
|
|
@ -44,15 +44,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
let body_owner_kind = tcx.hir().body_owner_kind(id);
|
let body_owner_kind = tcx.hir().body_owner_kind(id);
|
||||||
let typeck_results = tcx.typeck_opt_const_arg(def);
|
let typeck_results = tcx.typeck_opt_const_arg(def);
|
||||||
|
|
||||||
// Ensure unsafeck is ran before we steal the THIR.
|
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
|
||||||
|
// We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
|
||||||
|
// if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
|
||||||
|
// THIR has been stolen if we haven't computed this query yet.
|
||||||
match def {
|
match def {
|
||||||
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
|
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
|
||||||
tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
|
tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
|
||||||
tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did));
|
drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did)));
|
||||||
}
|
}
|
||||||
ty::WithOptConstParam { did, const_param_did: None } => {
|
ty::WithOptConstParam { did, const_param_did: None } => {
|
||||||
tcx.ensure().thir_check_unsafety(did);
|
tcx.ensure().thir_check_unsafety(did);
|
||||||
tcx.ensure().thir_abstract_const(did);
|
drop(tcx.thir_abstract_const(did));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,16 +322,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
&& !self.saw_const_match_lint.get()
|
&& !self.saw_const_match_lint.get()
|
||||||
{
|
{
|
||||||
self.saw_const_match_lint.set(true);
|
self.saw_const_match_lint.set(true);
|
||||||
let msg = format!(
|
|
||||||
"to use a constant of type `{}` in a pattern, \
|
|
||||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
|
||||||
cv.ty, cv.ty,
|
|
||||||
);
|
|
||||||
tcx.struct_span_lint_hir(
|
tcx.struct_span_lint_hir(
|
||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|lint| lint.build(&msg).emit(),
|
|lint| {
|
||||||
|
let msg = format!(
|
||||||
|
"to use a constant of type `{}` in a pattern, \
|
||||||
|
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||||
|
cv.ty, cv.ty,
|
||||||
|
);
|
||||||
|
lint.build(&msg).emit()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Since we are behind a reference, we can just bubble the error up so we get a
|
// Since we are behind a reference, we can just bubble the error up so we get a
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use rustc_errors::{Applicability, Handler};
|
use rustc_errors::{pluralize, Applicability, Handler};
|
||||||
use rustc_lexer::unescape::{EscapeError, Mode};
|
use rustc_lexer::unescape::{EscapeError, Mode};
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
|
|
||||||
|
@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error(
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
EscapeError::MoreThanOneChar => {
|
EscapeError::MoreThanOneChar => {
|
||||||
let (prefix, msg) = if mode.is_bytes() {
|
use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
|
||||||
("b", "if you meant to write a byte string literal, use double quotes")
|
|
||||||
} else {
|
|
||||||
("", "if you meant to write a `str` literal, use double quotes")
|
|
||||||
};
|
|
||||||
|
|
||||||
handler
|
let mut has_help = false;
|
||||||
.struct_span_err(
|
let mut handler = handler.struct_span_err(
|
||||||
span_with_quotes,
|
span_with_quotes,
|
||||||
"character literal may only contain one codepoint",
|
"character literal may only contain one codepoint",
|
||||||
)
|
);
|
||||||
.span_suggestion(
|
|
||||||
|
if lit.chars().skip(1).all(|c| is_combining_mark(c)) {
|
||||||
|
let escaped_marks =
|
||||||
|
lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>();
|
||||||
|
handler.span_note(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"this `{}` is followed by the combining mark{} `{}`",
|
||||||
|
lit.chars().next().unwrap(),
|
||||||
|
pluralize!(escaped_marks.len()),
|
||||||
|
escaped_marks.join(""),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let normalized = lit.nfc().to_string();
|
||||||
|
if normalized.chars().count() == 1 {
|
||||||
|
has_help = true;
|
||||||
|
handler.span_suggestion(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"consider using the normalized form `{}` of this character",
|
||||||
|
normalized.chars().next().unwrap().escape_default()
|
||||||
|
),
|
||||||
|
normalized,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has_help {
|
||||||
|
let (prefix, msg) = if mode.is_bytes() {
|
||||||
|
("b", "if you meant to write a byte string literal, use double quotes")
|
||||||
|
} else {
|
||||||
|
("", "if you meant to write a `str` literal, use double quotes")
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.span_suggestion(
|
||||||
span_with_quotes,
|
span_with_quotes,
|
||||||
msg,
|
msg,
|
||||||
format!("{}\"{}\"", prefix, lit),
|
format!("{}\"{}\"", prefix, lit),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
);
|
||||||
.emit();
|
}
|
||||||
|
|
||||||
|
handler.emit();
|
||||||
}
|
}
|
||||||
EscapeError::EscapeOnlyChar => {
|
EscapeError::EscapeOnlyChar => {
|
||||||
let (c, char_span) = last_char();
|
let (c, char_span) = last_char();
|
||||||
|
|
|
@ -522,8 +522,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let item = {
|
let item = {
|
||||||
let hir = tcx.hir();
|
let mut parent_iter = tcx.hir().parent_iter(hir_id);
|
||||||
let mut parent_iter = hir.parent_iter(hir_id);
|
|
||||||
loop {
|
loop {
|
||||||
let node = parent_iter.next().map(|n| n.1);
|
let node = parent_iter.next().map(|n| n.1);
|
||||||
match node {
|
match node {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#![feature(binary_heap_retain)]
|
#![feature(binary_heap_retain)]
|
||||||
#![feature(binary_heap_as_slice)]
|
#![feature(binary_heap_as_slice)]
|
||||||
#![feature(inplace_iteration)]
|
#![feature(inplace_iteration)]
|
||||||
#![feature(iter_map_while)]
|
|
||||||
#![feature(slice_group_by)]
|
#![feature(slice_group_by)]
|
||||||
#![feature(slice_partition_dedup)]
|
#![feature(slice_partition_dedup)]
|
||||||
#![feature(vec_spare_capacity)]
|
#![feature(vec_spare_capacity)]
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::str::from_utf8_unchecked;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EscapeDefault {
|
pub struct EscapeDefault {
|
||||||
range: Range<usize>,
|
range: Range<u8>,
|
||||||
data: [u8; 4],
|
data: [u8; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ pub fn escape_default(c: u8) -> EscapeDefault {
|
||||||
impl Iterator for EscapeDefault {
|
impl Iterator for EscapeDefault {
|
||||||
type Item = u8;
|
type Item = u8;
|
||||||
fn next(&mut self) -> Option<u8> {
|
fn next(&mut self) -> Option<u8> {
|
||||||
self.range.next().map(|i| self.data[i])
|
self.range.next().map(|i| self.data[i as usize])
|
||||||
}
|
}
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.range.size_hint()
|
self.range.size_hint()
|
||||||
|
@ -126,7 +126,7 @@ impl Iterator for EscapeDefault {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl DoubleEndedIterator for EscapeDefault {
|
impl DoubleEndedIterator for EscapeDefault {
|
||||||
fn next_back(&mut self) -> Option<u8> {
|
fn next_back(&mut self) -> Option<u8> {
|
||||||
self.range.next_back().map(|i| self.data[i])
|
self.range.next_back().map(|i| self.data[i as usize])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -138,7 +138,9 @@ impl FusedIterator for EscapeDefault {}
|
||||||
impl fmt::Display for EscapeDefault {
|
impl fmt::Display for EscapeDefault {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// SAFETY: ok because `escape_default` created only valid utf-8 data
|
// SAFETY: ok because `escape_default` created only valid utf-8 data
|
||||||
f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
|
f.write_str(unsafe {
|
||||||
|
from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::ops::{ControlFlow, Try};
|
||||||
/// [`map_while`]: Iterator::map_while
|
/// [`map_while`]: Iterator::map_while
|
||||||
/// [`Iterator`]: trait.Iterator.html
|
/// [`Iterator`]: trait.Iterator.html
|
||||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct MapWhile<I, P> {
|
pub struct MapWhile<I, P> {
|
||||||
iter: I,
|
iter: I,
|
||||||
|
@ -23,14 +23,14 @@ impl<I, P> MapWhile<I, P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
|
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
|
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
|
impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
|
||||||
where
|
where
|
||||||
P: FnMut(I::Item) -> Option<B>,
|
P: FnMut(I::Item) -> Option<B>,
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub use self::copied::Copied;
|
||||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||||
pub use self::intersperse::{Intersperse, IntersperseWith};
|
pub use self::intersperse::{Intersperse, IntersperseWith};
|
||||||
|
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
pub use self::map_while::MapWhile;
|
pub use self::map_while::MapWhile;
|
||||||
|
|
||||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||||
|
|
|
@ -399,7 +399,7 @@ pub use self::adapters::Cloned;
|
||||||
pub use self::adapters::Copied;
|
pub use self::adapters::Copied;
|
||||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||||
pub use self::adapters::Flatten;
|
pub use self::adapters::Flatten;
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
pub use self::adapters::MapWhile;
|
pub use self::adapters::MapWhile;
|
||||||
#[unstable(feature = "inplace_iteration", issue = "none")]
|
#[unstable(feature = "inplace_iteration", issue = "none")]
|
||||||
pub use self::adapters::SourceIter;
|
pub use self::adapters::SourceIter;
|
||||||
|
|
|
@ -1116,7 +1116,6 @@ pub trait Iterator {
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(iter_map_while)]
|
|
||||||
/// let a = [-1i32, 4, 0, 1];
|
/// let a = [-1i32, 4, 0, 1];
|
||||||
///
|
///
|
||||||
/// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
|
/// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
|
||||||
|
@ -1147,7 +1146,6 @@ pub trait Iterator {
|
||||||
/// Stopping after an initial [`None`]:
|
/// Stopping after an initial [`None`]:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(iter_map_while)]
|
|
||||||
/// use std::convert::TryFrom;
|
/// use std::convert::TryFrom;
|
||||||
///
|
///
|
||||||
/// let a = [0, 1, 2, -3, 4, 5, -6];
|
/// let a = [0, 1, 2, -3, 4, 5, -6];
|
||||||
|
@ -1165,7 +1163,6 @@ pub trait Iterator {
|
||||||
/// removed:
|
/// removed:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(iter_map_while)]
|
|
||||||
/// use std::convert::TryFrom;
|
/// use std::convert::TryFrom;
|
||||||
///
|
///
|
||||||
/// let a = [1, 2, -3, 4];
|
/// let a = [1, 2, -3, 4];
|
||||||
|
@ -1191,7 +1188,7 @@ pub trait Iterator {
|
||||||
///
|
///
|
||||||
/// [`fuse`]: Iterator::fuse
|
/// [`fuse`]: Iterator::fuse
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||||
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
|
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
#![feature(iter_partition_in_place)]
|
#![feature(iter_partition_in_place)]
|
||||||
#![feature(iter_is_partitioned)]
|
#![feature(iter_is_partitioned)]
|
||||||
#![feature(iter_order_by)]
|
#![feature(iter_order_by)]
|
||||||
#![feature(iter_map_while)]
|
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(const_pin)]
|
#![feature(const_pin)]
|
||||||
#![feature(const_slice_from_raw_parts)]
|
#![feature(const_slice_from_raw_parts)]
|
||||||
|
|
|
@ -31,6 +31,7 @@ use crate::num;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
use crate::string;
|
use crate::string;
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
|
use crate::time;
|
||||||
|
|
||||||
/// `Error` is a trait representing the basic expectations for error values,
|
/// `Error` is a trait representing the basic expectations for error values,
|
||||||
/// i.e., values of type `E` in [`Result<T, E>`].
|
/// i.e., values of type `E` in [`Result<T, E>`].
|
||||||
|
@ -598,7 +599,7 @@ impl Error for char::ParseCharError {
|
||||||
impl Error for alloc::collections::TryReserveError {}
|
impl Error for alloc::collections::TryReserveError {}
|
||||||
|
|
||||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||||
impl Error for core::time::FromSecsError {}
|
impl Error for time::FromSecsError {}
|
||||||
|
|
||||||
// Copied from `any.rs`.
|
// Copied from `any.rs`.
|
||||||
impl dyn Error + 'static {
|
impl dyn Error + 'static {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Equivalent to C's `char` type.
|
Equivalent to C's `char` type.
|
||||||
|
|
||||||
[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long.
|
[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
|
||||||
|
|
||||||
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
|
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,9 @@ use crate::sys_common::FromInner;
|
||||||
#[stable(feature = "time", since = "1.3.0")]
|
#[stable(feature = "time", since = "1.3.0")]
|
||||||
pub use core::time::Duration;
|
pub use core::time::Duration;
|
||||||
|
|
||||||
|
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||||
|
pub use core::time::FromSecsError;
|
||||||
|
|
||||||
/// A measurement of a monotonically nondecreasing clock.
|
/// A measurement of a monotonically nondecreasing clock.
|
||||||
/// Opaque and useful only with [`Duration`].
|
/// Opaque and useful only with [`Duration`].
|
||||||
///
|
///
|
||||||
|
|
|
@ -1494,8 +1494,13 @@ impl Build {
|
||||||
{
|
{
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"
|
"
|
||||||
Couldn't find required command: ninja
|
Couldn't find required command: ninja (or ninja-build)
|
||||||
You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
|
|
||||||
|
You should install ninja as described at
|
||||||
|
<https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages>,
|
||||||
|
or set `ninja = false` in the `[llvm]` section of `config.toml`.
|
||||||
|
Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
|
||||||
|
to download LLVM rather than building it.
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
|
22
src/test/ui/consts/issue-89088.rs
Normal file
22
src/test/ui/consts/issue-89088.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Regression test for the ICE described in #89088.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![allow(indirect_structural_match)]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
const FOO: &A = &A::Field(Cow::Borrowed("foo"));
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum A {
|
||||||
|
Field(Cow<'static, str>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let var = A::Field(Cow::Borrowed("bar"));
|
||||||
|
|
||||||
|
match &var {
|
||||||
|
FOO => todo!(),
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
|
}
|
25
src/test/ui/consts/refs_check_const_eq-issue-88384.rs
Normal file
25
src/test/ui/consts/refs_check_const_eq-issue-88384.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(fn_traits)]
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
//~^ WARNING the feature `adt_const_params` is incomplete
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
struct CompileTimeSettings{
|
||||||
|
hooks: &'static[fn()],
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<const T: CompileTimeSettings>;
|
||||||
|
|
||||||
|
impl<const T: CompileTimeSettings> Foo<T> {
|
||||||
|
fn call_hooks(){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(){
|
||||||
|
const SETTINGS: CompileTimeSettings = CompileTimeSettings{
|
||||||
|
hooks: &[],
|
||||||
|
};
|
||||||
|
|
||||||
|
Foo::<SETTINGS>::call_hooks();
|
||||||
|
}
|
11
src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
Normal file
11
src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/refs_check_const_eq-issue-88384.rs:4:12
|
||||||
|
|
|
||||||
|
LL | #![feature(adt_const_params)]
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
|
warning: 1 warning emitted
|
||||||
|
|
12
src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs
Normal file
12
src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
|
struct FooConst<const ARRAY: &'static [&'static str]> {}
|
||||||
|
|
||||||
|
const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"];
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = FooConst::<FOO_ARR> {};
|
||||||
|
}
|
21
src/test/ui/parser/unicode-character-literal.fixed
Normal file
21
src/test/ui/parser/unicode-character-literal.fixed
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Regression test for #88684: Improve diagnostics for combining marks
|
||||||
|
// in character literals.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _spade = "♠️";
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
|
||||||
|
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
||||||
|
let _s = "ṩ̂̊";
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
||||||
|
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
||||||
|
let _a = 'Å';
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `A` is followed by the combining mark `\u{30a}`
|
||||||
|
//~| HELP: consider using the normalized form `\u{c5}` of this character
|
||||||
|
}
|
21
src/test/ui/parser/unicode-character-literal.rs
Normal file
21
src/test/ui/parser/unicode-character-literal.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Regression test for #88684: Improve diagnostics for combining marks
|
||||||
|
// in character literals.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _spade = '♠️';
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
|
||||||
|
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
||||||
|
let _s = 'ṩ̂̊';
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
||||||
|
//~| HELP: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
||||||
|
let _a = 'Å';
|
||||||
|
//~^ ERROR: character literal may only contain one codepoint
|
||||||
|
//~| NOTE: this `A` is followed by the combining mark `\u{30a}`
|
||||||
|
//~| HELP: consider using the normalized form `\u{c5}` of this character
|
||||||
|
}
|
48
src/test/ui/parser/unicode-character-literal.stderr
Normal file
48
src/test/ui/parser/unicode-character-literal.stderr
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
error: character literal may only contain one codepoint
|
||||||
|
--> $DIR/unicode-character-literal.rs:7:18
|
||||||
|
|
|
||||||
|
LL | let _spade = '♠️';
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
note: this `♠` is followed by the combining mark `\u{fe0f}`
|
||||||
|
--> $DIR/unicode-character-literal.rs:7:19
|
||||||
|
|
|
||||||
|
LL | let _spade = '♠️';
|
||||||
|
| ^
|
||||||
|
help: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
|
||||||
|
LL | let _spade = "♠️";
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error: character literal may only contain one codepoint
|
||||||
|
--> $DIR/unicode-character-literal.rs:12:14
|
||||||
|
|
|
||||||
|
LL | let _s = 'ṩ̂̊';
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
|
||||||
|
--> $DIR/unicode-character-literal.rs:12:15
|
||||||
|
|
|
||||||
|
LL | let _s = 'ṩ̂̊';
|
||||||
|
| ^
|
||||||
|
help: if you meant to write a `str` literal, use double quotes
|
||||||
|
|
|
||||||
|
LL | let _s = "ṩ̂̊";
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error: character literal may only contain one codepoint
|
||||||
|
--> $DIR/unicode-character-literal.rs:17:14
|
||||||
|
|
|
||||||
|
LL | let _a = 'Å';
|
||||||
|
| ^-^
|
||||||
|
| |
|
||||||
|
| help: consider using the normalized form `\u{c5}` of this character: `Å`
|
||||||
|
|
|
||||||
|
note: this `A` is followed by the combining mark `\u{30a}`
|
||||||
|
--> $DIR/unicode-character-literal.rs:17:15
|
||||||
|
|
|
||||||
|
LL | let _a = 'Å';
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
|
@ -105,8 +105,7 @@ impl<'hir> IfLet<'hir> {
|
||||||
if_else,
|
if_else,
|
||||||
) = expr.kind
|
) = expr.kind
|
||||||
{
|
{
|
||||||
let hir = cx.tcx.hir();
|
let mut iter = cx.tcx.hir().parent_iter(expr.hir_id);
|
||||||
let mut iter = hir.parent_iter(expr.hir_id);
|
|
||||||
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
|
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
|
||||||
if let Some((
|
if let Some((
|
||||||
_,
|
_,
|
||||||
|
|
|
@ -833,12 +833,11 @@ pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind
|
||||||
ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
|
ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
|
||||||
));
|
));
|
||||||
|
|
||||||
let map = cx.tcx.hir();
|
|
||||||
let mut child_id = e.hir_id;
|
let mut child_id = e.hir_id;
|
||||||
let mut capture = CaptureKind::Value;
|
let mut capture = CaptureKind::Value;
|
||||||
let mut capture_expr_ty = e;
|
let mut capture_expr_ty = e;
|
||||||
|
|
||||||
for (parent_id, parent) in map.parent_iter(e.hir_id) {
|
for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
|
||||||
if let [Adjustment {
|
if let [Adjustment {
|
||||||
kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
|
kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
|
||||||
target,
|
target,
|
||||||
|
@ -1224,8 +1223,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
|
||||||
|
|
||||||
/// Gets the loop or closure enclosing the given expression, if any.
|
/// Gets the loop or closure enclosing the given expression, if any.
|
||||||
pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
||||||
let map = tcx.hir();
|
for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
|
||||||
for (_, node) in map.parent_iter(expr.hir_id) {
|
|
||||||
match node {
|
match node {
|
||||||
Node::Expr(
|
Node::Expr(
|
||||||
e
|
e
|
||||||
|
@ -1244,8 +1242,7 @@ pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Opti
|
||||||
|
|
||||||
/// Gets the parent node if it's an impl block.
|
/// Gets the parent node if it's an impl block.
|
||||||
pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
|
pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
|
||||||
let map = tcx.hir();
|
match tcx.hir().parent_iter(id).next() {
|
||||||
match map.parent_iter(id).next() {
|
|
||||||
Some((
|
Some((
|
||||||
_,
|
_,
|
||||||
Node::Item(Item {
|
Node::Item(Item {
|
||||||
|
@ -1259,8 +1256,7 @@ pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
|
||||||
|
|
||||||
/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
|
/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
|
||||||
pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
|
pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
|
||||||
let map = tcx.hir();
|
let mut iter = tcx.hir().parent_iter(expr.hir_id);
|
||||||
let mut iter = map.parent_iter(expr.hir_id);
|
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some((
|
Some((
|
||||||
_,
|
_,
|
||||||
|
@ -1794,9 +1790,8 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
|
||||||
|
|
||||||
/// Gets the node where an expression is either used, or it's type is unified with another branch.
|
/// Gets the node where an expression is either used, or it's type is unified with another branch.
|
||||||
pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
|
pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
|
||||||
let map = tcx.hir();
|
|
||||||
let mut child_id = expr.hir_id;
|
let mut child_id = expr.hir_id;
|
||||||
let mut iter = map.parent_iter(child_id);
|
let mut iter = tcx.hir().parent_iter(child_id);
|
||||||
loop {
|
loop {
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
None => break None,
|
None => break None,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
|
Subproject commit f1d7f98ed07b9934286b9c4809dd4d7a47537879
|
Loading…
Add table
Add a link
Reference in a new issue