Skip to content

Commit

Permalink
Auto merge of #60708 - Centril:rollup-j5smdo0, r=Centril
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed May 10, 2019
2 parents cff1bdb + 329275a commit d595b11
Show file tree
Hide file tree
Showing 32 changed files with 1,106 additions and 45 deletions.
2 changes: 2 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ Mark Sinclair <[email protected]> =Mark Sinclair <[email protected]>
Markus Westerlind <[email protected]> Markus <[email protected]>
Martin Hafskjold Thoresen <[email protected]>
Matej Lach <[email protected]> Matej Ľach <[email protected]>
Mateusz Mikuła <[email protected]> <[email protected]>
Mateusz Mikuła <[email protected]> <[email protected]>
Matt Brubeck <[email protected]> <[email protected]>
Matthew Auld <[email protected]>
Matthew McPherrin <[email protected]> <[email protected]>
Expand Down
22 changes: 16 additions & 6 deletions src/librustc/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,14 @@ impl<'a, 'gcx, 'tcx> AdtDef {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: SubstsRef<'tcx>) -> DefIdForest
{
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(tcx, substs, self.adt_kind())
}))
// Non-exhaustive ADTs from other crates are always considered inhabited.
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
DefIdForest::empty()
} else {
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(tcx, substs, self.adt_kind())
}))
}
}
}

Expand All @@ -134,9 +139,14 @@ impl<'a, 'gcx, 'tcx> VariantDef {
AdtKind::Enum => true,
AdtKind::Struct => false,
};
DefIdForest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(tcx, substs, is_enum)
}))
// Non-exhaustive variants from other crates are always considered inhabited.
if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
DefIdForest::empty()
} else {
DefIdForest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(tcx, substs, is_enum)
}))
}
}
}

Expand Down
27 changes: 23 additions & 4 deletions src/librustc_mir/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,18 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
}
}

fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pattern<'tcx>) -> bool
where 'a: 'p
{
match *pattern.kind {
PatternKind::Variant { adt_def, variant_index, .. } => {
let ref variant = adt_def.variants[variant_index];
variant.is_field_list_non_exhaustive()
}
_ => false,
}
}

fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
Expand Down Expand Up @@ -1097,10 +1109,17 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);

if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
debug!("is_useful - expanding constructors: {:#?}", constructors);
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty);
debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}",
constructors, is_declared_nonexhaustive);

if is_declared_nonexhaustive {
Useful
} else {
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
}
} else {
debug!("is_useful - expanding wildcard");

Expand Down
6 changes: 5 additions & 1 deletion src/librustc_mir/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
.map(|variant| variant.ident)
.collect();
}
def.variants.is_empty()

let is_non_exhaustive_and_non_local =
def.is_variant_list_non_exhaustive() && !def.did.is_local();

!(is_non_exhaustive_and_non_local) && def.variants.is_empty()
},
_ => false
}
Expand Down
16 changes: 7 additions & 9 deletions src/libsyntax/ext/tt/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,9 @@ pub fn transcribe(
}

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

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

// The first time we encounter the sequence we push it to the stack. It
Expand Down
84 changes: 60 additions & 24 deletions src/libsyntax_pos/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,22 @@ impl Decodable for Ident {
}
}

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

pub fn interned(self) -> Self {
with_interner(|interner| interner.interned(self))
}

/// Gensyms a new `usize`, using the current interner.
pub fn gensym(string: &str) -> Self {
with_interner(|interner| interner.gensym(string))
Expand All @@ -380,6 +389,7 @@ impl Symbol {
with_interner(|interner| interner.gensymed(self))
}

// WARNING: this function is deprecated and will be removed in the future.
pub fn is_gensymed(self) -> bool {
with_interner(|interner| interner.is_gensymed(self))
}
Expand Down Expand Up @@ -488,11 +498,11 @@ impl Interner {
name
}

pub fn interned(&self, symbol: Symbol) -> Symbol {
fn interned(&self, symbol: Symbol) -> Symbol {
if (symbol.0.as_usize()) < self.strings.len() {
symbol
} else {
self.interned(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize])
self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
}
}

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

// Get the symbol as a string. `Symbol::as_str()` should be used in
// preference to this function.
pub fn get(&self, symbol: Symbol) -> &str {
match self.strings.get(symbol.0.as_usize()) {
Some(string) => string,
None => self.get(self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]),
None => {
let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
self.strings[symbol.0.as_usize()]
}
}
}
}
Expand Down Expand Up @@ -611,11 +626,17 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
}

/// Represents a string stored in the interner. Because the interner outlives any thread
/// which uses this type, we can safely treat `string` which points to interner data,
/// as an immortal string, as long as this type never crosses between threads.
// FIXME: ensure that the interner outlives any thread which uses `LocalInternedString`,
// by creating a new thread right after constructing the interner.
/// An alternative to `Symbol` and `InternedString`, useful when the chars
/// within the symbol need to be accessed. It is best used for temporary
/// values.
///
/// Because the interner outlives any thread which uses this type, we can
/// safely treat `string` which points to interner data, as an immortal string,
/// as long as this type never crosses between threads.
//
// FIXME: ensure that the interner outlives any thread which uses
// `LocalInternedString`, by creating a new thread right after constructing the
// interner.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct LocalInternedString {
string: &'static str,
Expand Down Expand Up @@ -708,7 +729,19 @@ impl Encodable for LocalInternedString {
}
}

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

fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
let (self_str, other_str) = with_interner(|interner| {
(interner.get(self.symbol) as *const str,
interner.get(other.symbol) as *const str)
});
// This is safe for the same reason that `with` is safe.
unsafe { f(&*self_str, &*other_str) }
}

pub fn as_symbol(self) -> Symbol {
self.symbol
}
Expand All @@ -745,7 +787,7 @@ impl PartialOrd<InternedString> for InternedString {
if self.symbol == other.symbol {
return Some(Ordering::Equal);
}
self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str)))
self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str))
}
}

Expand All @@ -754,7 +796,7 @@ impl Ord for InternedString {
if self.symbol == other.symbol {
return Ordering::Equal;
}
self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
self.with2(other, |self_str, other_str| self_str.cmp(other_str))
}
}

Expand Down Expand Up @@ -794,12 +836,6 @@ impl<'a> PartialEq<InternedString> for &'a String {
}
}

impl std::convert::From<InternedString> for String {
fn from(val: InternedString) -> String {
val.as_symbol().to_string()
}
}

impl fmt::Debug for InternedString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.with(|str| fmt::Debug::fmt(&str, f))
Expand Down
10 changes: 10 additions & 0 deletions src/test/incremental/issue-60629.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// revisions:rpass1 rpass2

struct A;

#[cfg(rpass2)]
impl From<A> for () {
fn from(_: A) {}
}

fn main() {}
6 changes: 6 additions & 0 deletions src/test/ui/async-await/issue-60674.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ extern crate issue_60674;
#[issue_60674::attr]
async fn f(mut x: u8) {}

#[issue_60674::attr]
async fn g((mut x, y, mut z): (u8, u8, u8)) {}

#[issue_60674::attr]
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {}

fn main() {}
2 changes: 2 additions & 0 deletions src/test/ui/async-await/issue-60674.stdout
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
async fn f(mut x: u8) { }
async fn g((mut x, y, mut z): (u8, u8, u8)) { }
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { }
2 changes: 1 addition & 1 deletion src/test/ui/pattern/const-pat-ice.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1071:5
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#![crate_type = "rlib"]
#![feature(never_type)]
#![feature(non_exhaustive)]

#[non_exhaustive]
pub enum UninhabitedEnum {
}

#[non_exhaustive]
pub struct UninhabitedStruct {
_priv: !,
}

#[non_exhaustive]
pub struct UninhabitedTupleStruct(!);

pub enum UninhabitedVariants {
#[non_exhaustive] Tuple(!),
#[non_exhaustive] Struct { x: ! }
}

pub enum PartiallyInhabitedVariants {
Tuple(u8),
#[non_exhaustive] Struct { x: ! }
}

pub struct IndirectUninhabitedEnum(UninhabitedEnum);

pub struct IndirectUninhabitedStruct(UninhabitedStruct);

pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);

pub struct IndirectUninhabitedVariants(UninhabitedVariants);
Loading

0 comments on commit d595b11

Please sign in to comment.