Skip to content

Commit 36cbf94

Browse files
committed
Auto merge of rust-lang#116621 - aliemjay:rollup-0e2of3c, r=aliemjay
Rollup of 4 pull requests Successful merges: - rust-lang#95967 (Add explicit-endian String::from_utf16 variants) - rust-lang#116530 (delay a bug when encountering an ambiguity in MIR typeck) - rust-lang#116611 (Document `diagnostic_namespace` feature) - rust-lang#116612 (Remove unused dominator iterator) r? `@ghost` `@rustbot` modify labels: rollup
2 parents dcf89f4 + 88a929b commit 36cbf94

File tree

6 files changed

+275
-31
lines changed

6 files changed

+275
-31
lines changed

compiler/rustc_data_structures/src/graph/dominators/mod.rs

+1-26
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ struct Inner<N: Idx> {
349349
post_order_rank: IndexVec<N, usize>,
350350
// Even though we track only the immediate dominator of each node, it's
351351
// possible to get its full list of dominators by looking up the dominator
352-
// of each dominator. (See the `impl Iterator for Iter` definition).
352+
// of each dominator.
353353
immediate_dominators: IndexVec<N, Option<N>>,
354354
time: IndexVec<N, Time>,
355355
}
@@ -377,13 +377,6 @@ impl<Node: Idx> Dominators<Node> {
377377
}
378378
}
379379

380-
/// Provides an iterator over each dominator up the CFG, for the given Node.
381-
/// See the `impl Iterator for Iter` definition to understand how this works.
382-
pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
383-
assert!(self.is_reachable(node), "node {node:?} is not reachable");
384-
Iter { dom_tree: self, node: Some(node) }
385-
}
386-
387380
/// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
388381
/// relationship, the dominator will always precede the dominated. (The relative ordering
389382
/// of two unrelated nodes will also be consistent, but otherwise the order has no
@@ -413,24 +406,6 @@ impl<Node: Idx> Dominators<Node> {
413406
}
414407
}
415408

416-
pub struct Iter<'dom, Node: Idx> {
417-
dom_tree: &'dom Dominators<Node>,
418-
node: Option<Node>,
419-
}
420-
421-
impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
422-
type Item = Node;
423-
424-
fn next(&mut self) -> Option<Self::Item> {
425-
if let Some(node) = self.node {
426-
self.node = self.dom_tree.immediate_dominator(node);
427-
Some(node)
428-
} else {
429-
None
430-
}
431-
}
432-
}
433-
434409
/// Describes the number of vertices discovered at the time when processing of a particular vertex
435410
/// started and when it finished. Both values are zero for unreachable vertices.
436411
#[derive(Copy, Clone, Default, Debug)]

compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,18 @@ where
157157
}
158158

159159
let mut region_constraints = QueryRegionConstraints::default();
160-
let (output, error_info, mut obligations, _) =
161-
Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
162-
infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
163-
})?;
160+
let (output, error_info, mut obligations) =
161+
Q::fully_perform_into(self, infcx, &mut region_constraints)
162+
.map_err(|_| {
163+
infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
164+
})
165+
.and_then(|(output, error_info, obligations, certainty)| match certainty {
166+
Certainty::Proven => Ok((output, error_info, obligations)),
167+
Certainty::Ambiguous => Err(infcx
168+
.tcx
169+
.sess
170+
.delay_span_bug(span, format!("ambiguity performing {self:?}"))),
171+
})?;
164172

165173
// Typically, instantiating NLL query results does not
166174
// create obligations. However, in some cases there

library/alloc/src/string.rs

+150
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,156 @@ impl String {
714714
.collect()
715715
}
716716

717+
/// Decode a UTF-16LE–encoded vector `v` into a `String`, returning [`Err`]
718+
/// if `v` contains any invalid data.
719+
///
720+
/// # Examples
721+
///
722+
/// Basic usage:
723+
///
724+
/// ```
725+
/// #![feature(str_from_utf16_endian)]
726+
/// // 𝄞music
727+
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
728+
/// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00];
729+
/// assert_eq!(String::from("𝄞music"),
730+
/// String::from_utf16le(v).unwrap());
731+
///
732+
/// // 𝄞mu<invalid>ic
733+
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
734+
/// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00];
735+
/// assert!(String::from_utf16le(v).is_err());
736+
/// ```
737+
#[cfg(not(no_global_oom_handling))]
738+
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
739+
pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error> {
740+
if v.len() % 2 != 0 {
741+
return Err(FromUtf16Error(()));
742+
}
743+
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
744+
(true, ([], v, [])) => Self::from_utf16(v),
745+
_ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes))
746+
.collect::<Result<_, _>>()
747+
.map_err(|_| FromUtf16Error(())),
748+
}
749+
}
750+
751+
/// Decode a UTF-16LE–encoded slice `v` into a `String`, replacing
752+
/// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
753+
///
754+
/// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
755+
/// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8
756+
/// conversion requires a memory allocation.
757+
///
758+
/// [`from_utf8_lossy`]: String::from_utf8_lossy
759+
/// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
760+
/// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
761+
///
762+
/// # Examples
763+
///
764+
/// Basic usage:
765+
///
766+
/// ```
767+
/// #![feature(str_from_utf16_endian)]
768+
/// // 𝄞mus<invalid>ic<invalid>
769+
/// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,
770+
/// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00,
771+
/// 0x34, 0xD8];
772+
///
773+
/// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
774+
/// String::from_utf16le_lossy(v));
775+
/// ```
776+
#[cfg(not(no_global_oom_handling))]
777+
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
778+
pub fn from_utf16le_lossy(v: &[u8]) -> String {
779+
match (cfg!(target_endian = "little"), unsafe { v.align_to::<u16>() }) {
780+
(true, ([], v, [])) => Self::from_utf16_lossy(v),
781+
(true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}",
782+
_ => {
783+
let mut iter = v.array_chunks::<2>();
784+
let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes))
785+
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
786+
.collect();
787+
if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" }
788+
}
789+
}
790+
}
791+
792+
/// Decode a UTF-16BE–encoded vector `v` into a `String`, returning [`Err`]
793+
/// if `v` contains any invalid data.
794+
///
795+
/// # Examples
796+
///
797+
/// Basic usage:
798+
///
799+
/// ```
800+
/// #![feature(str_from_utf16_endian)]
801+
/// // 𝄞music
802+
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
803+
/// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63];
804+
/// assert_eq!(String::from("𝄞music"),
805+
/// String::from_utf16be(v).unwrap());
806+
///
807+
/// // 𝄞mu<invalid>ic
808+
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
809+
/// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63];
810+
/// assert!(String::from_utf16be(v).is_err());
811+
/// ```
812+
#[cfg(not(no_global_oom_handling))]
813+
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
814+
pub fn from_utf16be(v: &[u8]) -> Result<String, FromUtf16Error> {
815+
if v.len() % 2 != 0 {
816+
return Err(FromUtf16Error(()));
817+
}
818+
match (cfg!(target_endian = "big"), unsafe { v.align_to::<u16>() }) {
819+
(true, ([], v, [])) => Self::from_utf16(v),
820+
_ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes))
821+
.collect::<Result<_, _>>()
822+
.map_err(|_| FromUtf16Error(())),
823+
}
824+
}
825+
826+
/// Decode a UTF-16BE–encoded slice `v` into a `String`, replacing
827+
/// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
828+
///
829+
/// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
830+
/// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8
831+
/// conversion requires a memory allocation.
832+
///
833+
/// [`from_utf8_lossy`]: String::from_utf8_lossy
834+
/// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
835+
/// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
836+
///
837+
/// # Examples
838+
///
839+
/// Basic usage:
840+
///
841+
/// ```
842+
/// #![feature(str_from_utf16_endian)]
843+
/// // 𝄞mus<invalid>ic<invalid>
844+
/// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,
845+
/// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63,
846+
/// 0xD8, 0x34];
847+
///
848+
/// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
849+
/// String::from_utf16be_lossy(v));
850+
/// ```
851+
#[cfg(not(no_global_oom_handling))]
852+
#[unstable(feature = "str_from_utf16_endian", issue = "116258")]
853+
pub fn from_utf16be_lossy(v: &[u8]) -> String {
854+
match (cfg!(target_endian = "big"), unsafe { v.align_to::<u16>() }) {
855+
(true, ([], v, [])) => Self::from_utf16_lossy(v),
856+
(true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}",
857+
_ => {
858+
let mut iter = v.array_chunks::<2>();
859+
let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes))
860+
.map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
861+
.collect();
862+
if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" }
863+
}
864+
}
865+
}
866+
717867
/// Decomposes a `String` into its raw components.
718868
///
719869
/// Returns the raw pointer to the underlying data, the length of
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# `diagnostic_namespace`
2+
3+
The tracking issue for this feature is: [#111996]
4+
5+
[#111996]: https://github.com/rust-lang/rust/issues/111996
6+
7+
------------------------
8+
9+
The `diagnostic_namespace` feature permits customization of compilation errors.
10+
11+
## diagnostic::on_unimplemented
12+
13+
With [#114452] support for `diagnostic::on_unimplemented` was added.
14+
15+
When used on a trait declaration, the following options are available:
16+
17+
* `message` to customize the primary error message
18+
* `note` to add a customized note message to an error message
19+
* `label` to customize the label part of the error message
20+
21+
The attribute will hint to the compiler to use these in error messages:
22+
```rust
23+
// some library
24+
#![feature(diagnostic_namespace)]
25+
26+
#[diagnostic::on_unimplemented(
27+
message = "cannot insert element",
28+
label = "cannot be put into a table",
29+
note = "see <link> for more information about the Table api"
30+
)]
31+
pub trait Element {
32+
// ...
33+
}
34+
```
35+
36+
```rust,compile_fail,E0277
37+
# #![feature(diagnostic_namespace)]
38+
#
39+
# #[diagnostic::on_unimplemented(
40+
# message = "cannot insert element",
41+
# label = "cannot be put into a table",
42+
# note = "see <link> for more information about the Table api"
43+
# )]
44+
# pub trait Element {
45+
# // ...
46+
# }
47+
# struct Table;
48+
# impl Table {
49+
# fn insert<T: Element>(&self, element: T) {
50+
# // ..
51+
# }
52+
# }
53+
# fn main() {
54+
# let table = Table;
55+
# let element = ();
56+
// user code
57+
table.insert(element);
58+
# }
59+
```
60+
61+
```text
62+
error[E0277]: cannot insert element
63+
--> src/main.rs:24:18
64+
|
65+
24 | table.insert(element);
66+
| ------ ^^^^^^^ cannot be put into a table
67+
| |
68+
| required by a bound introduced by this call
69+
|
70+
= help: the trait `Element` is not implemented for `<type>`
71+
= note: see <link> for more information about the Table api
72+
note: required by a bound in `Table::insert`
73+
--> src/main.rs:15:18
74+
|
75+
15 | fn insert<T: Element>(&self, element: T) {
76+
| ^^^^^^^ required by this bound in `Table::insert`
77+
78+
For more information about this error, try `rustc --explain E0277`.
79+
```
80+
81+
See [RFC 3368] for more information.
82+
83+
[#114452]: https://github.com/rust-lang/rust/pull/114452
84+
[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: internal compiler error: no errors encountered even though `delay_span_bug` issued
2+
3+
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: [] } } }
4+
--> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5
5+
|
6+
LL | query(get_rpit);
7+
| ^^^^^^^^^^^^^^^
8+
|
9+
--> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5
10+
|
11+
LL | query(get_rpit);
12+
| ^^^^^^^^^^^^^^^
13+
14+
15+
16+
17+
query stack during panic:
18+
end of query stack
19+
error: aborting due to 2 previous errors
20+

tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
88
// revisions: current next
99
//[next] compile-flags: -Ztrait-solver=next
10-
// check-pass
10+
//[next] check-pass
11+
12+
//[current] known-bug: #108498
13+
//[current] failure-status: 101
14+
//[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId("
15+
//[current] normalize-stderr-test: "(?m)^note: .*\n" -> ""
16+
//[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> ""
17+
//[current] normalize-stderr-test: "(?m)^ *at .*\n" -> ""
1118

1219
#![feature(type_alias_impl_trait)]
1320

0 commit comments

Comments
 (0)