Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #60708

Merged
merged 20 commits into from
May 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8c465b4
Add `InternedString::with2`.
nnethercote May 9, 2019
c2cae7b
Avoid recursion in de-gensym functions.
nnethercote May 9, 2019
0e27c36
Add various comments.
nnethercote May 9, 2019
cb7eacb
Remove the `From<InternedString> for String` impl.
nnethercote May 9, 2019
e53bb1a
Reduce `Symbol`'s interface slightly.
nnethercote May 9, 2019
d28b7af
Extend existing test for nested mut patterns.
davidtwco May 10, 2019
c81780b
add regression test for #60629
hellow554 May 10, 2019
8fbe1ed
Update mailmap for mati865
mati865 May 10, 2019
5b6bda3
turn a couple of fixmes into span_bugs
mark-i-m May 7, 2019
0db087e
Add uninhabitedness tests w/ `#[non_exhaustive]`.
davidtwco May 4, 2019
0d034a2
Fix inhabitedness of non-exhaustive variants.
davidtwco May 4, 2019
8838b91
Fix uninhabitedness of non-exhaustive enums.
davidtwco May 4, 2019
214f977
Move uninhabited tests into subdirectory.
davidtwco May 4, 2019
1f0fb03
Add a bunch more tests.
davidtwco May 4, 2019
d94cb9f
Rollup merge of #60529 - davidtwco:rfc-2008-uninhabited, r=petrochenkov
Centril May 10, 2019
20dff29
Rollup merge of #60620 - mark-i-m:transcribe-2, r=petrochenkov
Centril May 10, 2019
bc8c782
Rollup merge of #60659 - nnethercote:tweak-Symbol-and-InternedString,…
Centril May 10, 2019
ec6afb1
Rollup merge of #60692 - davidtwco:pr-60676-followup, r=Centril
Centril May 10, 2019
0b63f55
Rollup merge of #60697 - hellow554:fix_60629, r=michaelwoerister
Centril May 10, 2019
329275a
Rollup merge of #60701 - mati865:mailmap, r=Mark-Simulacrum
Centril May 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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