Skip to content

Commit d595b11

Browse files
committed
Auto merge of #60708 - Centril:rollup-j5smdo0, r=Centril
Rollup of 6 pull requests Successful merges: - #60529 (RFC 2008: Uninhabitedness fixes for enum variants and tests) - #60620 (Fix a couple of FIXMEs in ext::tt::transcribe) - #60659 (Tweak `Symbol` and `InternedString`) - #60692 (Extend #60676 test for nested mut patterns.) - #60697 (add regression test for #60629) - #60701 (Update mailmap for mati865) Failed merges: r? @ghost
2 parents cff1bdb + 329275a commit d595b11

32 files changed

+1106
-45
lines changed

.mailmap

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ Mark Sinclair <[email protected]> =Mark Sinclair <[email protected]>
155155
Markus Westerlind <[email protected]> Markus <[email protected]>
156156
Martin Hafskjold Thoresen <[email protected]>
157157
Matej Lach <[email protected]> Matej Ľach <[email protected]>
158+
159+
158160
159161
Matthew Auld <[email protected]>
160162

src/librustc/ty/inhabitedness/mod.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,14 @@ impl<'a, 'gcx, 'tcx> AdtDef {
113113
tcx: TyCtxt<'a, 'gcx, 'tcx>,
114114
substs: SubstsRef<'tcx>) -> DefIdForest
115115
{
116-
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
117-
v.uninhabited_from(tcx, substs, self.adt_kind())
118-
}))
116+
// Non-exhaustive ADTs from other crates are always considered inhabited.
117+
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
118+
DefIdForest::empty()
119+
} else {
120+
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
121+
v.uninhabited_from(tcx, substs, self.adt_kind())
122+
}))
123+
}
119124
}
120125
}
121126

@@ -134,9 +139,14 @@ impl<'a, 'gcx, 'tcx> VariantDef {
134139
AdtKind::Enum => true,
135140
AdtKind::Struct => false,
136141
};
137-
DefIdForest::union(tcx, self.fields.iter().map(|f| {
138-
f.uninhabited_from(tcx, substs, is_enum)
139-
}))
142+
// Non-exhaustive variants from other crates are always considered inhabited.
143+
if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
144+
DefIdForest::empty()
145+
} else {
146+
DefIdForest::union(tcx, self.fields.iter().map(|f| {
147+
f.uninhabited_from(tcx, substs, is_enum)
148+
}))
149+
}
140150
}
141151
}
142152

src/librustc_mir/hair/pattern/_match.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,18 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
388388
}
389389
}
390390

391+
fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pattern<'tcx>) -> bool
392+
where 'a: 'p
393+
{
394+
match *pattern.kind {
395+
PatternKind::Variant { adt_def, variant_index, .. } => {
396+
let ref variant = adt_def.variants[variant_index];
397+
variant.is_field_list_non_exhaustive()
398+
}
399+
_ => false,
400+
}
401+
}
402+
391403
fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
392404
match ty.sty {
393405
ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
@@ -1097,10 +1109,17 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
10971109
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
10981110

10991111
if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
1100-
debug!("is_useful - expanding constructors: {:#?}", constructors);
1101-
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
1102-
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
1103-
).find(|result| result.is_useful()).unwrap_or(NotUseful)
1112+
let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty);
1113+
debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}",
1114+
constructors, is_declared_nonexhaustive);
1115+
1116+
if is_declared_nonexhaustive {
1117+
Useful
1118+
} else {
1119+
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
1120+
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
1121+
).find(|result| result.is_useful()).unwrap_or(NotUseful)
1122+
}
11041123
} else {
11051124
debug!("is_useful - expanding wildcard");
11061125

src/librustc_mir/hair/pattern/check_match.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
208208
.map(|variant| variant.ident)
209209
.collect();
210210
}
211-
def.variants.is_empty()
211+
212+
let is_non_exhaustive_and_non_local =
213+
def.is_variant_list_non_exhaustive() && !def.did.is_local();
214+
215+
!(is_non_exhaustive_and_non_local) && def.variants.is_empty()
212216
},
213217
_ => false
214218
}

src/libsyntax/ext/tt/transcribe.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,9 @@ pub fn transcribe(
170170
}
171171

172172
LockstepIterSize::Contradiction(ref msg) => {
173-
// FIXME: this should be impossible. I (mark-i-m) believe it would
174-
// represent a bug in the macro_parser.
175-
// FIXME #2887 blame macro invoker instead
176-
cx.span_fatal(seq.span(), &msg[..]);
173+
// This should never happen because the macro parser should generate
174+
// properly-sized matches for all meta-vars.
175+
cx.span_bug(seq.span(), &msg[..]);
177176
}
178177

179178
LockstepIterSize::Constraint(len, _) => {
@@ -188,14 +187,13 @@ pub fn transcribe(
188187
// Is the repetition empty?
189188
if len == 0 {
190189
if seq.op == quoted::KleeneOp::OneOrMore {
191-
// FIXME: this should be impossible because we check for this in
192-
// macro_parser.rs
193-
// FIXME #2887 blame invoker
194-
cx.span_fatal(sp.entire(), "this must repeat at least once");
190+
// This should be impossible because the macro parser would not
191+
// match the given macro arm.
192+
cx.span_bug(sp.entire(), "this must repeat at least once");
195193
}
196194
} else {
197195
// 0 is the initial counter (we have done 0 repretitions so far). `len`
198-
// is the total number of reptitions we should generate.
196+
// is the total number of reptitions we should generate.
199197
repeats.push((0, len));
200198

201199
// The first time we encounter the sequence we push it to the stack. It

src/libsyntax_pos/symbol.rs

+60-24
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,22 @@ impl Decodable for Ident {
344344
}
345345
}
346346

347-
/// A symbol is an interned or gensymed string. The use of `newtype_index!` means
348-
/// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index!` reserves
349-
/// the last 256 values for tagging purposes.
347+
/// A symbol is an interned or gensymed string. A gensym is a symbol that is
348+
/// never equal to any other symbol. E.g.:
349+
/// ```
350+
/// assert_eq!(Symbol::intern("x"), Symbol::intern("x"))
351+
/// assert_ne!(Symbol::gensym("x"), Symbol::intern("x"))
352+
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
353+
/// ```
354+
/// Conceptually, a gensym can be thought of as a normal symbol with an
355+
/// invisible unique suffix. Gensyms are useful when creating new identifiers
356+
/// that must not match any existing identifiers, e.g. during macro expansion
357+
/// and syntax desugaring.
358+
///
359+
/// Internally, a Symbol is implemented as an index, and all operations
360+
/// (including hashing, equality, and ordering) operate on that index. The use
361+
/// of `newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
362+
/// because `newtype_index!` reserves the last 256 values for tagging purposes.
350363
///
351364
/// Note that `Symbol` cannot directly be a `newtype_index!` because it implements
352365
/// `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
@@ -367,10 +380,6 @@ impl Symbol {
367380
with_interner(|interner| interner.intern(string))
368381
}
369382

370-
pub fn interned(self) -> Self {
371-
with_interner(|interner| interner.interned(self))
372-
}
373-
374383
/// Gensyms a new `usize`, using the current interner.
375384
pub fn gensym(string: &str) -> Self {
376385
with_interner(|interner| interner.gensym(string))
@@ -380,6 +389,7 @@ impl Symbol {
380389
with_interner(|interner| interner.gensymed(self))
381390
}
382391

392+
// WARNING: this function is deprecated and will be removed in the future.
383393
pub fn is_gensymed(self) -> bool {
384394
with_interner(|interner| interner.is_gensymed(self))
385395
}
@@ -488,11 +498,11 @@ impl Interner {
488498
name
489499
}
490500

491-
pub fn interned(&self, symbol: Symbol) -> Symbol {
501+
fn interned(&self, symbol: Symbol) -> Symbol {
492502
if (symbol.0.as_usize()) < self.strings.len() {
493503
symbol
494504
} else {
495-
self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize])
505+
self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
496506
}
497507
}
498508

@@ -510,10 +520,15 @@ impl Interner {
510520
symbol.0.as_usize() >= self.strings.len()
511521
}
512522

523+
// Get the symbol as a string. `Symbol::as_str()` should be used in
524+
// preference to this function.
513525
pub fn get(&self, symbol: Symbol) -> &str {
514526
match self.strings.get(symbol.0.as_usize()) {
515527
Some(string) => string,
516-
None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]),
528+
None => {
529+
let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
530+
self.strings[symbol.0.as_usize()]
531+
}
517532
}
518533
}
519534
}
@@ -611,11 +626,17 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
611626
GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
612627
}
613628

614-
/// Represents a string stored in the interner. Because the interner outlives any thread
615-
/// which uses this type, we can safely treat `string` which points to interner data,
616-
/// as an immortal string, as long as this type never crosses between threads.
617-
// FIXME: ensure that the interner outlives any thread which uses `LocalInternedString`,
618-
// by creating a new thread right after constructing the interner.
629+
/// An alternative to `Symbol` and `InternedString`, useful when the chars
630+
/// within the symbol need to be accessed. It is best used for temporary
631+
/// values.
632+
///
633+
/// Because the interner outlives any thread which uses this type, we can
634+
/// safely treat `string` which points to interner data, as an immortal string,
635+
/// as long as this type never crosses between threads.
636+
//
637+
// FIXME: ensure that the interner outlives any thread which uses
638+
// `LocalInternedString`, by creating a new thread right after constructing the
639+
// interner.
619640
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
620641
pub struct LocalInternedString {
621642
string: &'static str,
@@ -708,7 +729,19 @@ impl Encodable for LocalInternedString {
708729
}
709730
}
710731

711-
/// Represents a string stored in the string interner.
732+
/// An alternative to `Symbol` that is focused on string contents. It has two
733+
/// main differences to `Symbol`.
734+
///
735+
/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
736+
/// string chars rather than the symbol integer. This is useful when hash
737+
/// stability is required across compile sessions, or a guaranteed sort
738+
/// ordering is required.
739+
///
740+
/// Second, gensym-ness is irrelevant. E.g.:
741+
/// ```
742+
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
743+
/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
744+
/// ```
712745
#[derive(Clone, Copy, Eq)]
713746
pub struct InternedString {
714747
symbol: Symbol,
@@ -725,6 +758,15 @@ impl InternedString {
725758
unsafe { f(&*str) }
726759
}
727760

761+
fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
762+
let (self_str, other_str) = with_interner(|interner| {
763+
(interner.get(self.symbol) as *const str,
764+
interner.get(other.symbol) as *const str)
765+
});
766+
// This is safe for the same reason that `with` is safe.
767+
unsafe { f(&*self_str, &*other_str) }
768+
}
769+
728770
pub fn as_symbol(self) -> Symbol {
729771
self.symbol
730772
}
@@ -745,7 +787,7 @@ impl PartialOrd<InternedString> for InternedString {
745787
if self.symbol == other.symbol {
746788
return Some(Ordering::Equal);
747789
}
748-
self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str)))
790+
self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str))
749791
}
750792
}
751793

@@ -754,7 +796,7 @@ impl Ord for InternedString {
754796
if self.symbol == other.symbol {
755797
return Ordering::Equal;
756798
}
757-
self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
799+
self.with2(other, |self_str, other_str| self_str.cmp(other_str))
758800
}
759801
}
760802

@@ -794,12 +836,6 @@ impl<'a> PartialEq<InternedString> for &'a String {
794836
}
795837
}
796838

797-
impl std::convert::From<InternedString> for String {
798-
fn from(val: InternedString) -> String {
799-
val.as_symbol().to_string()
800-
}
801-
}
802-
803839
impl fmt::Debug for InternedString {
804840
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
805841
self.with(|str| fmt::Debug::fmt(&str, f))

src/test/incremental/issue-60629.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// revisions:rpass1 rpass2
2+
3+
struct A;
4+
5+
#[cfg(rpass2)]
6+
impl From<A> for () {
7+
fn from(_: A) {}
8+
}
9+
10+
fn main() {}

src/test/ui/async-await/issue-60674.rs

+6
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ extern crate issue_60674;
1111
#[issue_60674::attr]
1212
async fn f(mut x: u8) {}
1313

14+
#[issue_60674::attr]
15+
async fn g((mut x, y, mut z): (u8, u8, u8)) {}
16+
17+
#[issue_60674::attr]
18+
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {}
19+
1420
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
async fn f(mut x: u8) { }
2+
async fn g((mut x, y, mut z): (u8, u8, u8)) { }
3+
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { }

src/test/ui/pattern/const-pat-ice.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1071:5
1+
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5
22
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
33

44
error: internal compiler error: unexpected panic
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![crate_type = "rlib"]
2+
#![feature(never_type)]
3+
#![feature(non_exhaustive)]
4+
5+
#[non_exhaustive]
6+
pub enum UninhabitedEnum {
7+
}
8+
9+
#[non_exhaustive]
10+
pub struct UninhabitedStruct {
11+
_priv: !,
12+
}
13+
14+
#[non_exhaustive]
15+
pub struct UninhabitedTupleStruct(!);
16+
17+
pub enum UninhabitedVariants {
18+
#[non_exhaustive] Tuple(!),
19+
#[non_exhaustive] Struct { x: ! }
20+
}
21+
22+
pub enum PartiallyInhabitedVariants {
23+
Tuple(u8),
24+
#[non_exhaustive] Struct { x: ! }
25+
}
26+
27+
pub struct IndirectUninhabitedEnum(UninhabitedEnum);
28+
29+
pub struct IndirectUninhabitedStruct(UninhabitedStruct);
30+
31+
pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
32+
33+
pub struct IndirectUninhabitedVariants(UninhabitedVariants);

0 commit comments

Comments
 (0)