Auto merge of #116621 - aliemjay:rollup-0e2of3c, r=aliemjay
Rollup of 4 pull requests Successful merges: - #95967 (Add explicit-endian String::from_utf16 variants) - #116530 (delay a bug when encountering an ambiguity in MIR typeck) - #116611 (Document `diagnostic_namespace` feature) - #116612 (Remove unused dominator iterator) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
36cbf944b3
@ -349,7 +349,7 @@ struct Inner<N: Idx> {
|
||||
post_order_rank: IndexVec<N, usize>,
|
||||
// Even though we track only the immediate dominator of each node, it's
|
||||
// possible to get its full list of dominators by looking up the dominator
|
||||
// of each dominator. (See the `impl Iterator for Iter` definition).
|
||||
// of each dominator.
|
||||
immediate_dominators: IndexVec<N, Option<N>>,
|
||||
time: IndexVec<N, Time>,
|
||||
}
|
||||
@ -377,13 +377,6 @@ impl<Node: Idx> Dominators<Node> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides an iterator over each dominator up the CFG, for the given Node.
|
||||
/// See the `impl Iterator for Iter` definition to understand how this works.
|
||||
pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
|
||||
assert!(self.is_reachable(node), "node {node:?} is not reachable");
|
||||
Iter { dom_tree: self, node: Some(node) }
|
||||
}
|
||||
|
||||
/// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
|
||||
/// relationship, the dominator will always precede the dominated. (The relative ordering
|
||||
/// of two unrelated nodes will also be consistent, but otherwise the order has no
|
||||
@ -413,24 +406,6 @@ impl<Node: Idx> Dominators<Node> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'dom, Node: Idx> {
|
||||
dom_tree: &'dom Dominators<Node>,
|
||||
node: Option<Node>,
|
||||
}
|
||||
|
||||
impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
|
||||
type Item = Node;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(node) = self.node {
|
||||
self.node = self.dom_tree.immediate_dominator(node);
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the number of vertices discovered at the time when processing of a particular vertex
|
||||
/// started and when it finished. Both values are zero for unreachable vertices.
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
|
@ -157,9 +157,17 @@ where
|
||||
}
|
||||
|
||||
let mut region_constraints = QueryRegionConstraints::default();
|
||||
let (output, error_info, mut obligations, _) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
|
||||
let (output, error_info, mut obligations) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints)
|
||||
.map_err(|_| {
|
||||
infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
|
||||
})
|
||||
.and_then(|(output, error_info, obligations, certainty)| match certainty {
|
||||
Certainty::Proven => Ok((output, error_info, obligations)),
|
||||
Certainty::Ambiguous => Err(infcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(span, format!("ambiguity performing {self:?}"))),
|
||||
})?;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
|
@ -714,6 +714,156 @@ impl String {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Decode a UTF-16LE–encoded vector `v` into a `String`, returning [`Err`]
|
||||
/// if `v` contains any invalid data.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_from_utf16_endian)]
|
||||
/// // 𝄞music
|
||||
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
|
||||
/// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00];
|
||||
/// assert_eq!(String::from("𝄞music"),
|
||||
/// String::from_utf16le(v).unwrap());
|
||||
///
|
||||
/// // 𝄞mu<invalid>ic
|
||||
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
|
||||
/// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00];
|
||||
/// assert!(String::from_utf16le(v).is_err());
|
||||
/// ```
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
|
||||
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
|
||||
if v.len() % 2 != 0 {
|
||||
return Err(FromUtf16Error(()));
|
||||
}
|
||||
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
|
||||
(true, ([], v, [])) => Self::from_utf16(v),
|
||||
_ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes))
|
||||
.collect::<Result<_, _>>()
|
||||
.map_err(|_| FromUtf16Error(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode a UTF-16LE–encoded slice `v` into a `String`, replacing
|
||||
/// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
|
||||
///
|
||||
/// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
|
||||
/// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8
|
||||
/// conversion requires a memory allocation.
|
||||
///
|
||||
/// [`from_utf8_lossy`]: String::from_utf8_lossy
|
||||
/// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
|
||||
/// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_from_utf16_endian)]
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
|
||||
/// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00,
|
||||
/// 0x34, 0xD8];
|
||||
///
|
||||
/// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
|
||||
/// String::from_utf16le_lossy(v));
|
||||
/// ```
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
|
||||
pub fn from_utf16le_lossy(v: &[u8]) -> String {
|
||||
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
|
||||
(true, ([], v, [])) => Self::from_utf16_lossy(v),
|
||||
(true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}",
|
||||
_ => {
|
||||
let mut iter = v.array_chunks::<2>();
|
||||
let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes))
|
||||
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
|
||||
.collect();
|
||||
if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode a UTF-16BE–encoded vector `v` into a `String`, returning [`Err`]
|
||||
/// if `v` contains any invalid data.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_from_utf16_endian)]
|
||||
/// // 𝄞music
|
||||
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
|
||||
/// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63];
|
||||
/// assert_eq!(String::from("𝄞music"),
|
||||
/// String::from_utf16be(v).unwrap());
|
||||
///
|
||||
/// // 𝄞mu<invalid>ic
|
||||
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
|
||||
/// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63];
|
||||
/// assert!(String::from_utf16be(v).is_err());
|
||||
/// ```
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
|
||||
pub fn from_utf16be(v: &[u8]) -> Result<String, FromUtf16Error> {
|
||||
if v.len() % 2 != 0 {
|
||||
return Err(FromUtf16Error(()));
|
||||
}
|
||||
match (cfg!(target_endian = "big"), unsafe { v.align_to::<u16>() }) {
|
||||
(true, ([], v, [])) => Self::from_utf16(v),
|
||||
_ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes))
|
||||
.collect::<Result<_, _>>()
|
||||
.map_err(|_| FromUtf16Error(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode a UTF-16BE–encoded slice `v` into a `String`, replacing
|
||||
/// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
|
||||
///
|
||||
/// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
|
||||
/// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8
|
||||
/// conversion requires a memory allocation.
|
||||
///
|
||||
/// [`from_utf8_lossy`]: String::from_utf8_lossy
|
||||
/// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
|
||||
/// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_from_utf16_endian)]
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
|
||||
/// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63,
|
||||
/// 0xD8, 0x34];
|
||||
///
|
||||
/// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
|
||||
/// String::from_utf16be_lossy(v));
|
||||
/// ```
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
|
||||
pub fn from_utf16be_lossy(v: &[u8]) -> String {
|
||||
match (cfg!(target_endian = "big"), unsafe { v.align_to::<u16>() }) {
|
||||
(true, ([], v, [])) => Self::from_utf16_lossy(v),
|
||||
(true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}",
|
||||
_ => {
|
||||
let mut iter = v.array_chunks::<2>();
|
||||
let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes))
|
||||
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
|
||||
.collect();
|
||||
if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Decomposes a `String` into its raw components.
|
||||
///
|
||||
/// Returns the raw pointer to the underlying data, the length of
|
||||
|
@ -0,0 +1,84 @@
|
||||
# `diagnostic_namespace`
|
||||
|
||||
The tracking issue for this feature is: [#111996]
|
||||
|
||||
[#111996]: https://github.com/rust-lang/rust/issues/111996
|
||||
|
||||
------------------------
|
||||
|
||||
The `diagnostic_namespace` feature permits customization of compilation errors.
|
||||
|
||||
## diagnostic::on_unimplemented
|
||||
|
||||
With [#114452] support for `diagnostic::on_unimplemented` was added.
|
||||
|
||||
When used on a trait declaration, the following options are available:
|
||||
|
||||
* `message` to customize the primary error message
|
||||
* `note` to add a customized note message to an error message
|
||||
* `label` to customize the label part of the error message
|
||||
|
||||
The attribute will hint to the compiler to use these in error messages:
|
||||
```rust
|
||||
// some library
|
||||
#![feature(diagnostic_namespace)]
|
||||
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "cannot insert element",
|
||||
label = "cannot be put into a table",
|
||||
note = "see <link> for more information about the Table api"
|
||||
)]
|
||||
pub trait Element {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```rust,compile_fail,E0277
|
||||
# #![feature(diagnostic_namespace)]
|
||||
#
|
||||
# #[diagnostic::on_unimplemented(
|
||||
# message = "cannot insert element",
|
||||
# label = "cannot be put into a table",
|
||||
# note = "see <link> for more information about the Table api"
|
||||
# )]
|
||||
# pub trait Element {
|
||||
# // ...
|
||||
# }
|
||||
# struct Table;
|
||||
# impl Table {
|
||||
# fn insert<T: Element>(&self, element: T) {
|
||||
# // ..
|
||||
# }
|
||||
# }
|
||||
# fn main() {
|
||||
# let table = Table;
|
||||
# let element = ();
|
||||
// user code
|
||||
table.insert(element);
|
||||
# }
|
||||
```
|
||||
|
||||
```text
|
||||
error[E0277]: cannot insert element
|
||||
--> src/main.rs:24:18
|
||||
|
|
||||
24 | table.insert(element);
|
||||
| ------ ^^^^^^^ cannot be put into a table
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Element` is not implemented for `<type>`
|
||||
= note: see <link> for more information about the Table api
|
||||
note: required by a bound in `Table::insert`
|
||||
--> src/main.rs:15:18
|
||||
|
|
||||
15 | fn insert<T: Element>(&self, element: T) {
|
||||
| ^^^^^^^ required by this bound in `Table::insert`
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
```
|
||||
|
||||
See [RFC 3368] for more information.
|
||||
|
||||
[#114452]: https://github.com/rust-lang/rust/pull/114452
|
||||
[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md
|
@ -0,0 +1,20 @@
|
||||
error: internal compiler error: no errors encountered even though `delay_span_bug` issued
|
||||
|
||||
error: internal compiler error: ambiguity performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } }
|
||||
--> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5
|
||||
|
|
||||
LL | query(get_rpit);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
--> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5
|
||||
|
|
||||
LL | query(get_rpit);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
|
||||
|
||||
query stack during panic:
|
||||
end of query stack
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -7,7 +7,14 @@
|
||||
|
||||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
//[next] check-pass
|
||||
|
||||
//[current] known-bug: #108498
|
||||
//[current] failure-status: 101
|
||||
//[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId("
|
||||
//[current] normalize-stderr-test: "(?m)^note: .*\n" -> ""
|
||||
//[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> ""
|
||||
//[current] normalize-stderr-test: "(?m)^ *at .*\n" -> ""
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user