diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d61feef81a80..495d7e46baa6e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,6 +122,8 @@ To see a full list of options, run `./configure --help`. Some common make targets are: +- `make tips` - show useful targets, variables and other tips for working with + the build system. - `make rustc-stage1` - build up to (and including) the first stage. For most cases we don't need to build the stage2 compiler, so we can save time by not building it. The stage1 compiler is a fully functioning compiler and diff --git a/configure b/configure index 38f3e3b00c6d8..b7053c5c54f56 100755 --- a/configure +++ b/configure @@ -599,6 +599,7 @@ opt debug-assertions 0 "build with debugging assertions" opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" +opt local-rebuild 0 "use an installed rustc matching the current version, for rebuilds" opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM" opt rpath 1 "build rpaths into rustc itself" opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0" @@ -847,6 +848,16 @@ then BIN_SUF=.exe fi +# --enable-local-rebuild implies --enable-local-rust too +if [ -n "$CFG_ENABLE_LOCAL_REBUILD" ] +then + if [ -z "$CFG_ENABLE_LOCAL_RUST" ] + then + CFG_ENABLE_LOCAL_RUST=1 + putvar CFG_ENABLE_LOCAL_RUST + fi +fi + if [ -n "$CFG_ENABLE_LOCAL_RUST" ] then system_rustc=$(which rustc) diff --git a/mk/main.mk b/mk/main.mk index 493b61051331f..14504d5cf5c8f 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,7 +13,7 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.10.0 +CFG_RELEASE_NUM=1.11.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release @@ -34,7 +34,14 @@ CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(C # intentionally not "secure" by any definition, this is largely just a deterrent # from users enabling unstable features on the stable compiler. CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA) + +# The stage0 compiler needs to use the previous key recorded in src/stage0.txt, +# except for local-rebuild when it just uses the same current key. +ifdef CFG_ENABLE_LOCAL_REBUILD +CFG_BOOTSTRAP_KEY_STAGE0=$(CFG_BOOTSTRAP_KEY) +else CFG_BOOTSTRAP_KEY_STAGE0=$(shell grep 'rustc_key' $(S)src/stage0.txt | sed 's/rustc_key: '//) +endif ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" @@ -526,6 +533,11 @@ ifneq ($(strip $(CFG_BUILD)),$(strip $(3))) CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 RPATH_VAR$(1)_T_$(2)_H_$(3) := $$(TARGET_RPATH_VAR1_T_$(2)_H_$$(CFG_BUILD)) +else +ifdef CFG_ENABLE_LOCAL_REBUILD +# Assume the local-rebuild rustc already has stage1 features too. +CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 +endif endif endif diff --git a/src/bootstrap/build/config.rs b/src/bootstrap/build/config.rs index 3c35b9a95169a..e155bf356a0d8 100644 --- a/src/bootstrap/build/config.rs +++ b/src/bootstrap/build/config.rs @@ -65,8 +65,9 @@ pub struct Config { pub build: String, pub host: Vec, pub target: Vec, - pub rustc: Option, - pub cargo: Option, + pub rustc: Option, + pub cargo: Option, + pub local_rebuild: bool, // libstd features pub debug_jemalloc: bool, @@ -207,8 +208,8 @@ impl Config { config.target.push(target.clone()); } } - config.rustc = build.rustc; - config.cargo = build.cargo; + config.rustc = build.rustc.map(PathBuf::from); + config.cargo = build.cargo.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); @@ -315,6 +316,7 @@ impl Config { ("RPATH", self.rust_rpath), ("OPTIMIZE_TESTS", self.rust_optimize_tests), ("DEBUGINFO_TESTS", self.rust_debuginfo_tests), + ("LOCAL_REBUILD", self.local_rebuild), } match key { @@ -377,6 +379,10 @@ impl Config { .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } + "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { + self.rustc = Some(PathBuf::from(value).join("bin/rustc")); + self.cargo = Some(PathBuf::from(value).join("bin/cargo")); + } _ => {} } } diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs index ebc05c5f61c50..21d12d27d92e1 100644 --- a/src/bootstrap/build/mod.rs +++ b/src/bootstrap/build/mod.rs @@ -510,6 +510,14 @@ impl Build { .arg("-j").arg(self.jobs().to_string()) .arg("--target").arg(target); + let stage; + if compiler.stage == 0 && self.config.local_rebuild { + // Assume the local-rebuild rustc already has stage1 features. + stage = 1; + } else { + stage = compiler.stage; + } + // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. @@ -518,7 +526,7 @@ impl Build { // src/bootstrap/{rustc,rustdoc.rs} cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.compiler_path(compiler)) - .env("RUSTC_STAGE", compiler.stage.to_string()) + .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) .env("RUSTC_CODEGEN_UNITS", self.config.rust_codegen_units.to_string()) @@ -744,7 +752,7 @@ impl Build { // In stage0 we're using a previously released stable compiler, so we // use the stage0 bootstrap key. Otherwise we use our own build's // bootstrap key. - let bootstrap_key = if compiler.is_snapshot(self) { + let bootstrap_key = if compiler.is_snapshot(self) && !self.config.local_rebuild { &self.bootstrap_key_stage0 } else { &self.bootstrap_key diff --git a/src/doc/book/no-stdlib.md b/src/doc/book/no-stdlib.md index 43bd0507ebbb6..9823a0b6d6355 100644 --- a/src/doc/book/no-stdlib.md +++ b/src/doc/book/no-stdlib.md @@ -84,4 +84,4 @@ which do not trigger a panic can be assured that this function is never called. The second function, `panic_fmt`, is also used by the failure mechanisms of the compiler. -[unwind]: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/unwind/gcc.rs +[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs diff --git a/src/doc/book/primitive-types.md b/src/doc/book/primitive-types.md index 2a4b7ba37f25b..b6a123bb3674c 100644 --- a/src/doc/book/primitive-types.md +++ b/src/doc/book/primitive-types.md @@ -175,8 +175,6 @@ You can use a combo of `&` and `[]` to create a slice from various things. The detail later in this section. The `[]`s, with a range, let you define the length of the slice: -[references]: references-and-borrowing.html - ```rust let a = [0, 1, 2, 3, 4]; let complete = &a[..]; // A slice containing all of the elements in a diff --git a/src/doc/reference.md b/src/doc/reference.md index ebb111a2e2e73..810138e5a2983 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2433,6 +2433,8 @@ The currently implemented features of the reference compiler are: * - `abi_vectorcall` - Allows the usage of the vectorcall calling convention (e.g. `extern "vectorcall" func fn_();`) +* - `dotdot_in_tuple_patterns` - Allows `..` in tuple (struct) patterns. + If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled the new feature (because the directive is no longer necessary). However, if a diff --git a/src/etc/unicode.py b/src/etc/unicode.py index 5a7632868e467..a99770f226140 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -25,6 +25,9 @@ import fileinput, re, os, sys, operator +bytes_old = 0 +bytes_new = 0 + preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -307,12 +310,137 @@ def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True, format_table_content(f, data, 8) f.write("\n ];\n\n") +def emit_trie_lookup_range_table(f): + f.write(""" + +// BoolTrie is a trie for representing a set of Unicode codepoints. It is +// implemented with postfix compression (sharing of identical child nodes), +// which gives both compact size and fast lookup. +// +// The space of Unicode codepoints is divided into 3 subareas, each +// represented by a trie with different depth. In the first (0..0x800), there +// is no trie structure at all; each u64 entry corresponds to a bitvector +// effectively holding 64 bool values. +// +// In the second (0x800..0x10000), each child of the root node represents a +// 64-wide subrange, but instead of storing the full 64-bit value of the leaf, +// the trie stores an 8-bit index into a shared table of leaf values. This +// exploits the fact that in reasonable sets, many such leaves can be shared. +// +// In the third (0x10000..0x110000), each child of the root node represents a +// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice +// of a child tree. Each of these 64 bytes represents an index into the table +// of shared 64-bit leaf values. This exploits the sparse structure in the +// non-BMP range of most Unicode sets. +pub struct BoolTrie { + // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences) + r1: [u64; 32], // leaves + + // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences) + r2: [u8; 992], // first level + r3: &'static [u64], // leaves + + // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences) + r4: [u8; 256], // first level + r5: &'static [u8], // second level + r6: &'static [u64], // leaves +} + +fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool { + ((bitmap_chunk >> (c & 63)) & 1) != 0 +} + +fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool { + let c = c as usize; + if c < 0x800 { + trie_range_leaf(c, r.r1[c >> 6]) + } else if c < 0x10000 { + let child = r.r2[(c >> 6) - 0x20]; + trie_range_leaf(c, r.r3[child as usize]) + } else { + let child = r.r4[(c >> 12) - 0x10]; + let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)]; + trie_range_leaf(c, r.r6[leaf as usize]) + } +}\n +""") + +def compute_trie(rawdata, chunksize): + root = [] + childmap = {} + child_data = [] + for i in range(len(rawdata) / chunksize): + data = rawdata[i * chunksize: (i + 1) * chunksize] + child = '|'.join(map(str, data)) + if child not in childmap: + childmap[child] = len(childmap) + child_data.extend(data) + root.append(childmap[child]) + return (root, child_data) + +def emit_bool_trie(f, name, t_data, is_pub=True): + global bytes_old, bytes_new + bytes_old += 8 * len(t_data) + CHUNK = 64 + rawdata = [False] * 0x110000; + for (lo, hi) in t_data: + for cp in range(lo, hi + 1): + rawdata[cp] = True + + # convert to bitmap chunks of 64 bits each + chunks = [] + for i in range(0x110000 / CHUNK): + chunk = 0 + for j in range(64): + if rawdata[i * 64 + j]: + chunk |= 1 << j + chunks.append(chunk) + + pub_string = "" + if is_pub: + pub_string = "pub " + f.write(" %sconst %s: &'static super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)) + f.write(" r1: [\n") + data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 / CHUNK]) + format_table_content(f, data, 12) + f.write("\n ],\n") + + # 0x800..0x10000 trie + (r2, r3) = compute_trie(chunks[0x800 / CHUNK : 0x10000 / CHUNK], 64 / CHUNK) + f.write(" r2: [\n") + data = ','.join(str(node) for node in r2) + format_table_content(f, data, 12) + f.write("\n ],\n") + f.write(" r3: &[\n") + data = ','.join('0x%016x' % chunk for chunk in r3) + format_table_content(f, data, 12) + f.write("\n ],\n") + + # 0x10000..0x110000 trie + (mid, r6) = compute_trie(chunks[0x10000 / CHUNK : 0x110000 / CHUNK], 64 / CHUNK) + (r4, r5) = compute_trie(mid, 64) + f.write(" r4: [\n") + data = ','.join(str(node) for node in r4) + format_table_content(f, data, 12) + f.write("\n ],\n") + f.write(" r5: &[\n") + data = ','.join(str(node) for node in r5) + format_table_content(f, data, 12) + f.write("\n ],\n") + f.write(" r6: &[\n") + data = ','.join('0x%016x' % chunk for chunk in r6) + format_table_content(f, data, 12) + f.write("\n ],\n") + + f.write(" };\n\n") + bytes_new += 256 + 992 + 256 + 8 * len(r3) + len(r5) + 8 * len(r6) + def emit_property_module(f, mod, tbl, emit): f.write("pub mod %s {\n" % mod) for cat in sorted(emit): - emit_table(f, "%s_table" % cat, tbl[cat]) + emit_bool_trie(f, "%s_table" % cat, tbl[cat]) f.write(" pub fn %s(c: char) -> bool {\n" % cat) - f.write(" super::bsearch_range_table(c, %s_table)\n" % cat) + f.write(" super::trie_lookup_range_table(c, %s_table)\n" % cat) f.write(" }\n\n") f.write("}\n\n") @@ -402,8 +530,9 @@ def emit_norm_module(f, canon, compat, combine, norm_props): norm_props = load_properties("DerivedNormalizationProps.txt", ["Full_Composition_Exclusion"]) - # bsearch_range_table is used in all the property modules below - emit_bsearch_range_table(rf) + # trie_lookup_table is used in all the property modules below + emit_trie_lookup_range_table(rf) + # emit_bsearch_range_table(rf) # category tables for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \ @@ -414,3 +543,4 @@ def emit_norm_module(f, canon, compat, combine, norm_props): # normalizations and conversions module emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props) emit_conversions_module(rf, to_upper, to_lower, to_title) + #print 'bytes before = %d, bytes after = %d' % (bytes_old, bytes_new) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 4aba567fa1c20..d0a51e320cc2f 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -592,6 +592,31 @@ impl Drop for Arc { } } +impl Weak { + /// Constructs a new `Weak` without an accompanying instance of T. + /// + /// This allocates memory for T, but does not initialize it. Calling + /// Weak::upgrade() on the return value always gives None. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Weak::new(); + /// ``` + #[stable(feature = "downgraded_weak", since = "1.10.0")] + pub fn new() -> Weak { + unsafe { + Weak { ptr: Shared::new(Box::into_raw(box ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: uninitialized(), + }))} + } + } +} + impl Weak { /// Upgrades a weak reference to a strong reference. /// @@ -682,6 +707,13 @@ impl Clone for Weak { } } +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + fn default() -> Weak { + Weak::new() + } +} + #[stable(feature = "arc_weak", since = "1.4.0")] impl Drop for Weak { /// Drops the `Weak`. @@ -907,35 +939,6 @@ impl From for Arc { } } -impl Weak { - /// Constructs a new `Weak` without an accompanying instance of T. - /// - /// This allocates memory for T, but does not initialize it. Calling - /// Weak::upgrade() on the return value always gives None. - /// - /// # Examples - /// - /// ``` - /// #![feature(downgraded_weak)] - /// - /// use std::sync::Weak; - /// - /// let empty: Weak = Weak::new(); - /// ``` - #[unstable(feature = "downgraded_weak", - reason = "recently added", - issue = "30425")] - pub fn new() -> Weak { - unsafe { - Weak { ptr: Shared::new(Box::into_raw(box ArcInner { - strong: atomic::AtomicUsize::new(0), - weak: atomic::AtomicUsize::new(1), - data: uninitialized(), - }))} - } - } -} - #[cfg(test)] mod tests { use std::clone::Clone; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index c2dad9a1ae4f9..0293d5402c4c9 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -90,7 +90,6 @@ #![feature(unique)] #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(unsize)] -#![feature(extended_compare_and_swap)] #![cfg_attr(not(test), feature(raw, fn_traits, placement_new_protocol))] #![cfg_attr(test, feature(test, box_heap))] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c2f0a96132733..b92f5af05e315 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -720,6 +720,33 @@ impl !marker::Sync for Weak {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized> for Weak {} +impl Weak { + /// Constructs a new `Weak` without an accompanying instance of T. + /// + /// This allocates memory for T, but does not initialize it. Calling + /// Weak::upgrade() on the return value always gives None. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Weak::new(); + /// ``` + #[stable(feature = "downgraded_weak", since = "1.10.0")] + pub fn new() -> Weak { + unsafe { + Weak { + ptr: Shared::new(Box::into_raw(box RcBox { + strong: Cell::new(0), + weak: Cell::new(1), + value: uninitialized(), + })), + } + } + } +} + impl Weak { /// Upgrades a weak reference to a strong reference. /// @@ -823,34 +850,10 @@ impl fmt::Debug for Weak { } } -impl Weak { - /// Constructs a new `Weak` without an accompanying instance of T. - /// - /// This allocates memory for T, but does not initialize it. Calling - /// Weak::upgrade() on the return value always gives None. - /// - /// # Examples - /// - /// ``` - /// #![feature(downgraded_weak)] - /// - /// use std::rc::Weak; - /// - /// let empty: Weak = Weak::new(); - /// ``` - #[unstable(feature = "downgraded_weak", - reason = "recently added", - issue="30425")] - pub fn new() -> Weak { - unsafe { - Weak { - ptr: Shared::new(Box::into_raw(box RcBox { - strong: Cell::new(0), - weak: Cell::new(1), - value: uninitialized(), - })), - } - } +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + fn default() -> Weak { + Weak::new() } } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index a22299c5e1a54..9eade937bfb4c 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -80,13 +80,40 @@ mod imp { if align <= MIN_ALIGN { libc::malloc(size as libc::size_t) as *mut u8 } else { - let mut out = ptr::null_mut(); - let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t); - if ret != 0 { - ptr::null_mut() - } else { - out as *mut u8 - } + aligned_malloc(size, align) + } + } + + #[cfg(target_os = "android")] + unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(align as libc::size_t, size as libc::size_t) as *mut u8 + } + + #[cfg(not(target_os = "android"))] + unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + let mut out = ptr::null_mut(); + let ret = libc::posix_memalign(&mut out, align as libc::size_t, size as libc::size_t); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 } } diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 844940020066d..ec2f4a9f7f0b8 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -286,7 +286,7 @@ pub struct Values<'a, K: 'a, V: 'a> { } /// A mutable iterator over a BTreeMap's values. -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, } @@ -1144,7 +1144,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { } } -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; @@ -1157,14 +1157,14 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { } } -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { fn next_back(&mut self) -> Option<&'a mut V> { self.inner.next_back().map(|(_, v)| v) } } -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { fn len(&self) -> usize { self.inner.len() @@ -1575,7 +1575,6 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// # #![feature(map_values_mut)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -1590,8 +1589,8 @@ impl BTreeMap { /// assert_eq!(values, [String::from("hello!"), /// String::from("goodbye!")]); /// ``` - #[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] - pub fn values_mut<'a>(&'a mut self) -> ValuesMut<'a, K, V> { + #[stable(feature = "map_values_mut", since = "1.10.0")] + pub fn values_mut(&mut self) -> ValuesMut { ValuesMut { inner: self.iter_mut() } } @@ -1656,7 +1655,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } /// Returns a reference to this entry's key. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { match *self { Occupied(ref entry) => entry.key(), @@ -1668,7 +1667,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { &self.key } @@ -1718,7 +1717,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// Gets a reference to the key in the entry. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { self.handle.reborrow().into_kv().0 } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 34e4a426d3c0d..6ab66fc217b46 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,7 +27,6 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(test), feature(slice_binary_search_by_key))] // impl [T] #![cfg_attr(not(stage0), deny(warnings))] #![feature(alloc)] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 6321d5924d51a..cef8a33703b7a 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -759,7 +759,6 @@ impl [T] { /// fourth could match any position in `[1,4]`. /// /// ```rust - /// #![feature(slice_binary_search_by_key)] /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1), /// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), /// (1, 21), (2, 34), (4, 55)]; @@ -770,7 +769,7 @@ impl [T] { /// let r = s.binary_search_by_key(&1, |&(a,b)| b); /// assert!(match r { Ok(1...4) => true, _ => false, }); /// ``` - #[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "33018")] + #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] #[inline] pub fn binary_search_by_key(&self, b: &B, f: F) -> Result where F: FnMut(&T) -> B, diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 58d4a4ed4eb08..bd1bf6e9cc375 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -966,7 +966,7 @@ impl Vec { } } - /// Appends all elements in a slice to the `Vec`. + /// Clones and appends all elements in a slice to the `Vec`. /// /// Iterates over the slice `other`, clones each element, and then appends /// it to this `Vec`. The `other` vector is traversed in-order. diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index 1858791776f0e..e19090c7599ec 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::collections::BTreeMap; -use std::collections::Bound::{Excluded, Included, Unbounded, self}; +use std::collections::Bound::{self, Excluded, Included, Unbounded}; use std::collections::btree_map::Entry::{Occupied, Vacant}; use std::rc::Rc; @@ -20,41 +20,41 @@ fn test_basic_large() { assert_eq!(map.len(), 0); for i in 0..size { - assert_eq!(map.insert(i, 10*i), None); + assert_eq!(map.insert(i, 10 * i), None); assert_eq!(map.len(), i + 1); } for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*10)); + assert_eq!(map.get(&i).unwrap(), &(i * 10)); } - for i in size..size*2 { + for i in size..size * 2 { assert_eq!(map.get(&i), None); } for i in 0..size { - assert_eq!(map.insert(i, 100*i), Some(10*i)); + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); assert_eq!(map.len(), size); } for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*100)); + assert_eq!(map.get(&i).unwrap(), &(i * 100)); } - for i in 0..size/2 { - assert_eq!(map.remove(&(i*2)), Some(i*200)); + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); assert_eq!(map.len(), size - i - 1); } - for i in 0..size/2 { - assert_eq!(map.get(&(2*i)), None); - assert_eq!(map.get(&(2*i+1)).unwrap(), &(i*200 + 100)); + for i in 0..size / 2 { + assert_eq!(map.get(&(2 * i)), None); + assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100)); } - for i in 0..size/2 { - assert_eq!(map.remove(&(2*i)), None); - assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); - assert_eq!(map.len(), size/2 - i - 1); + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); } } @@ -81,7 +81,9 @@ fn test_iter() { // Forwards let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - fn test(size: usize, mut iter: T) where T: Iterator { + fn test(size: usize, mut iter: T) + where T: Iterator + { for i in 0..size { assert_eq!(iter.size_hint(), (size - i, Some(size - i))); assert_eq!(iter.next().unwrap(), (i, i)); @@ -101,7 +103,9 @@ fn test_iter_rev() { // Forwards let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - fn test(size: usize, mut iter: T) where T: Iterator { + fn test(size: usize, mut iter: T) + where T: Iterator + { for i in 0..size { assert_eq!(iter.size_hint(), (size - i, Some(size - i))); assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); @@ -125,8 +129,7 @@ fn test_values_mut() { } let values: Vec = a.values().cloned().collect(); - assert_eq!(values, [String::from("hello!"), - String::from("goodbye!")]); + assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]); } #[test] @@ -137,7 +140,8 @@ fn test_iter_mixed() { let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test(size: usize, mut iter: T) - where T: Iterator + DoubleEndedIterator { + where T: Iterator + DoubleEndedIterator + { for i in 0..size / 4 { assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); assert_eq!(iter.next().unwrap(), (i, i)); @@ -202,7 +206,7 @@ fn test_range() { for i in 0..size { for j in i..size { let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); - let mut pairs = (i..j+1).map(|i| (i, i)); + let mut pairs = (i..j + 1).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { assert_eq!(kv, pair); @@ -242,7 +246,7 @@ fn test_borrow() { } #[test] -fn test_entry(){ +fn test_entry() { let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); @@ -341,17 +345,23 @@ fn test_bad_zst() { struct Bad; impl PartialEq for Bad { - fn eq(&self, _: &Self) -> bool { false } + fn eq(&self, _: &Self) -> bool { + false + } } impl Eq for Bad {} impl PartialOrd for Bad { - fn partial_cmp(&self, _: &Self) -> Option { Some(Ordering::Less) } + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Less) + } } impl Ord for Bad { - fn cmp(&self, _: &Self) -> Ordering { Ordering::Less } + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Less + } } let mut m = BTreeMap::new(); @@ -368,27 +378,27 @@ fn test_clone() { assert_eq!(map.len(), 0); for i in 0..size { - assert_eq!(map.insert(i, 10*i), None); + assert_eq!(map.insert(i, 10 * i), None); assert_eq!(map.len(), i + 1); assert_eq!(map, map.clone()); } for i in 0..size { - assert_eq!(map.insert(i, 100*i), Some(10*i)); + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); assert_eq!(map.len(), size); assert_eq!(map, map.clone()); } - for i in 0..size/2 { - assert_eq!(map.remove(&(i*2)), Some(i*200)); + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); assert_eq!(map.len(), size - i - 1); assert_eq!(map, map.clone()); } - for i in 0..size/2 { - assert_eq!(map.remove(&(2*i)), None); - assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); - assert_eq!(map.len(), size/2 - i - 1); + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); assert_eq!(map, map.clone()); } } @@ -398,16 +408,36 @@ fn test_clone() { fn test_variance() { use std::collections::btree_map::{Iter, IntoIter, Range, Keys, Values}; - fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { v } - fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { v } - fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { v } - fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { v } - fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { v } - fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { v } - fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { v } - fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { v } - fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { v } - fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { v } + fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { + v + } + fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { + v + } + fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { + v + } + fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { + v + } + fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { + v + } + fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { + v + } + fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { + v + } + fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { + v + } + fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { + v + } + fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { + v + } } #[test] @@ -440,7 +470,7 @@ fn test_vacant_entry_key() { Vacant(e) => { assert_eq!(key, *e.key()); e.insert(value.clone()); - }, + } } assert_eq!(a.len(), 1); assert_eq!(a[key], value); diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs index b073c2f3ae4dd..972361326d7bb 100644 --- a/src/libcollectionstest/enum_set.rs +++ b/src/libcollectionstest/enum_set.rs @@ -17,7 +17,9 @@ use self::Foo::*; #[derive(Copy, Clone, PartialEq, Debug)] #[repr(usize)] enum Foo { - A, B, C + A, + B, + C, } impl CLike for Foo { @@ -157,15 +159,15 @@ fn test_iterator() { e1.insert(C); let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,C]); + assert_eq!(elems, [A, C]); e1.insert(C); let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,C]); + assert_eq!(elems, [A, C]); e1.insert(B); let elems: Vec<_> = e1.iter().collect(); - assert_eq!(elems, [A,B,C]); + assert_eq!(elems, [A, B, C]); } /////////////////////////////////////////////////////////////////////////// @@ -183,7 +185,7 @@ fn test_operators() { let e_union = e1 | e2; let elems: Vec<_> = e_union.iter().collect(); - assert_eq!(elems, [A,B,C]); + assert_eq!(elems, [A, B, C]); let e_intersection = e1 & e2; let elems: Vec<_> = e_intersection.iter().collect(); @@ -201,17 +203,17 @@ fn test_operators() { // Bitwise XOR of two sets, aka symmetric difference let e_symmetric_diff = e1 ^ e2; let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); + assert_eq!(elems, [A, B]); // Another way to express symmetric difference let e_symmetric_diff = (e1 - e2) | (e2 - e1); let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); + assert_eq!(elems, [A, B]); // Yet another way to express symmetric difference let e_symmetric_diff = (e1 | e2) - (e1 & e2); let elems: Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(elems, [A,B]); + assert_eq!(elems, [A, B]); } #[test] diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index e4152b99d2c6f..bae21f1bd9b8f 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -22,8 +22,6 @@ #![feature(enumset)] #![feature(iter_arith)] #![feature(linked_list_contains)] -#![feature(map_entry_keys)] -#![feature(map_values_mut)] #![feature(pattern)] #![feature(rand)] #![feature(step_by)] diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs index 7265d53be4837..956d75a95a58e 100644 --- a/src/libcollectionstest/linked_list.rs +++ b/src/libcollectionstest/linked_list.rs @@ -54,7 +54,7 @@ fn test_basic() { #[cfg(test)] fn generate_test() -> LinkedList { - list_from(&[0,1,2,3,4,5,6]) + list_from(&[0, 1, 2, 3, 4, 5, 6]) } #[cfg(test)] @@ -78,7 +78,7 @@ fn test_split_off() { // not singleton, forwards { - let u = vec![1,2,3,4,5]; + let u = vec![1, 2, 3, 4, 5]; let mut m = list_from(&u); let mut n = m.split_off(2); assert_eq!(m.len(), 2); @@ -92,7 +92,7 @@ fn test_split_off() { } // not singleton, backwards { - let u = vec![1,2,3,4,5]; + let u = vec![1, 2, 3, 4, 5]; let mut m = list_from(&u); let mut n = m.split_off(4); assert_eq!(m.len(), 4); @@ -246,33 +246,33 @@ fn test_eq() { m.push_back(1); assert!(n == m); - let n = list_from(&[2,3,4]); - let m = list_from(&[1,2,3]); + let n = list_from(&[2, 3, 4]); + let m = list_from(&[1, 2, 3]); assert!(n != m); } #[test] fn test_hash() { - let mut x = LinkedList::new(); - let mut y = LinkedList::new(); + let mut x = LinkedList::new(); + let mut y = LinkedList::new(); - assert!(::hash(&x) == ::hash(&y)); + assert!(::hash(&x) == ::hash(&y)); - x.push_back(1); - x.push_back(2); - x.push_back(3); + x.push_back(1); + x.push_back(2); + x.push_back(3); - y.push_front(3); - y.push_front(2); - y.push_front(1); + y.push_front(3); + y.push_front(2); + y.push_front(1); - assert!(::hash(&x) == ::hash(&y)); + assert!(::hash(&x) == ::hash(&y)); } #[test] fn test_ord() { let n = list_from(&[]); - let m = list_from(&[1,2,3]); + let m = list_from(&[1, 2, 3]); assert!(n < m); assert!(m > n); assert!(n <= n); @@ -281,7 +281,7 @@ fn test_ord() { #[test] fn test_ord_nan() { - let nan = 0.0f64/0.0; + let nan = 0.0f64 / 0.0; let n = list_from(&[nan]); let m = list_from(&[nan]); assert!(!(n < m)); @@ -296,15 +296,15 @@ fn test_ord_nan() { assert!(!(n <= one)); assert!(!(n >= one)); - let u = list_from(&[1.0f64,2.0,nan]); - let v = list_from(&[1.0f64,2.0,3.0]); + let u = list_from(&[1.0f64, 2.0, nan]); + let v = list_from(&[1.0f64, 2.0, 3.0]); assert!(!(u < v)); assert!(!(u > v)); assert!(!(u <= v)); assert!(!(u >= v)); - let s = list_from(&[1.0f64,2.0,4.0,2.0]); - let t = list_from(&[1.0f64,2.0,3.0,2.0]); + let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); + let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); assert!(!(s < t)); assert!(s > one); assert!(!(s <= one)); @@ -317,7 +317,8 @@ fn test_show() { assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); + assert_eq!(format!("{:?}", list), + "[\"just\", \"one\", \"test\", \"more\"]"); } #[test] diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 236c151891d11..71416f2069fa0 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -13,9 +13,13 @@ use std::mem; use std::__rand::{Rng, thread_rng}; use std::rc::Rc; -fn square(n: usize) -> usize { n * n } +fn square(n: usize) -> usize { + n * n +} -fn is_odd(n: &usize) -> bool { *n % 2 == 1 } +fn is_odd(n: &usize) -> bool { + *n % 2 == 1 +} #[test] fn test_from_fn() { @@ -76,9 +80,9 @@ fn test_is_empty() { #[test] fn test_len_divzero() { type Z = [i8; 0]; - let v0 : &[Z] = &[]; - let v1 : &[Z] = &[[]]; - let v2 : &[Z] = &[[], []]; + let v0: &[Z] = &[]; + let v1: &[Z] = &[[]]; + let v2: &[Z] = &[[], []]; assert_eq!(mem::size_of::(), 0); assert_eq!(v0.len(), 0); assert_eq!(v1.len(), 1); @@ -295,7 +299,7 @@ fn test_push() { #[test] fn test_truncate() { - let mut v: Vec> = vec![box 6,box 5,box 4]; + let mut v: Vec> = vec![box 6, box 5, box 4]; v.truncate(1); let v = v; assert_eq!(v.len(), 1); @@ -305,7 +309,7 @@ fn test_truncate() { #[test] fn test_clear() { - let mut v: Vec> = vec![box 6,box 5,box 4]; + let mut v: Vec> = vec![box 6, box 5, box 4]; v.clear(); assert_eq!(v.len(), 0); // If the unsafe block didn't drop things properly, we blow up here. @@ -320,12 +324,12 @@ fn test_dedup() { } case(vec![], vec![]); case(vec![1], vec![1]); - case(vec![1,1], vec![1]); - case(vec![1,2,3], vec![1,2,3]); - case(vec![1,1,2,3], vec![1,2,3]); - case(vec![1,2,2,3], vec![1,2,3]); - case(vec![1,2,3,3], vec![1,2,3]); - case(vec![1,1,2,2,2,3,3], vec![1,2,3]); + case(vec![1, 1], vec![1]); + case(vec![1, 2, 3], vec![1, 2, 3]); + case(vec![1, 1, 2, 3], vec![1, 2, 3]); + case(vec![1, 2, 2, 3], vec![1, 2, 3]); + case(vec![1, 2, 3, 3], vec![1, 2, 3]); + case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]); } #[test] @@ -336,10 +340,8 @@ fn test_dedup_unique() { v1.dedup(); let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; v2.dedup(); - /* - * If the boxed pointers were leaked or otherwise misused, valgrind - * and/or rt should raise errors. - */ + // If the boxed pointers were leaked or otherwise misused, valgrind + // and/or rt should raise errors. } #[test] @@ -350,10 +352,8 @@ fn test_dedup_shared() { v1.dedup(); let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; v2.dedup(); - /* - * If the pointers were leaked or otherwise misused, valgrind and/or - * rt should raise errors. - */ + // If the pointers were leaked or otherwise misused, valgrind and/or + // rt should raise errors. } #[test] @@ -365,31 +365,31 @@ fn test_retain() { #[test] fn test_binary_search() { - assert_eq!([1,2,3,4,5].binary_search(&5).ok(), Some(4)); - assert_eq!([1,2,3,4,5].binary_search(&4).ok(), Some(3)); - assert_eq!([1,2,3,4,5].binary_search(&3).ok(), Some(2)); - assert_eq!([1,2,3,4,5].binary_search(&2).ok(), Some(1)); - assert_eq!([1,2,3,4,5].binary_search(&1).ok(), Some(0)); - - assert_eq!([2,4,6,8,10].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8,10].binary_search(&10).ok(), Some(4)); - - assert_eq!([2,4,6,8].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8].binary_search(&8).ok(), Some(3)); - - assert_eq!([2,4,6].binary_search(&1).ok(), None); - assert_eq!([2,4,6].binary_search(&5).ok(), None); - assert_eq!([2,4,6].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6].binary_search(&6).ok(), Some(2)); - - assert_eq!([2,4].binary_search(&1).ok(), None); - assert_eq!([2,4].binary_search(&5).ok(), None); - assert_eq!([2,4].binary_search(&2).ok(), Some(0)); - assert_eq!([2,4].binary_search(&4).ok(), Some(1)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&5).ok(), Some(4)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&4).ok(), Some(3)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&3).ok(), Some(2)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&2).ok(), Some(1)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&1).ok(), Some(0)); + + assert_eq!([2, 4, 6, 8, 10].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6, 8, 10].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6, 8, 10].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6, 8, 10].binary_search(&10).ok(), Some(4)); + + assert_eq!([2, 4, 6, 8].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6, 8].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6, 8].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6, 8].binary_search(&8).ok(), Some(3)); + + assert_eq!([2, 4, 6].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6].binary_search(&6).ok(), Some(2)); + + assert_eq!([2, 4].binary_search(&1).ok(), None); + assert_eq!([2, 4].binary_search(&5).ok(), None); + assert_eq!([2, 4].binary_search(&2).ok(), Some(0)); + assert_eq!([2, 4].binary_search(&4).ok(), Some(1)); assert_eq!([2].binary_search(&1).ok(), None); assert_eq!([2].binary_search(&5).ok(), None); @@ -398,14 +398,14 @@ fn test_binary_search() { assert_eq!([].binary_search(&1).ok(), None); assert_eq!([].binary_search(&5).ok(), None); - assert!([1,1,1,1,1].binary_search(&1).ok() != None); - assert!([1,1,1,1,2].binary_search(&1).ok() != None); - assert!([1,1,1,2,2].binary_search(&1).ok() != None); - assert!([1,1,2,2,2].binary_search(&1).ok() != None); - assert_eq!([1,2,2,2,2].binary_search(&1).ok(), Some(0)); + assert!([1, 1, 1, 1, 1].binary_search(&1).ok() != None); + assert!([1, 1, 1, 1, 2].binary_search(&1).ok() != None); + assert!([1, 1, 1, 2, 2].binary_search(&1).ok() != None); + assert!([1, 1, 2, 2, 2].binary_search(&1).ok() != None); + assert_eq!([1, 2, 2, 2, 2].binary_search(&1).ok(), Some(0)); - assert_eq!([1,2,3,4,5].binary_search(&6).ok(), None); - assert_eq!([1,2,3,4,5].binary_search(&0).ok(), None); + assert_eq!([1, 2, 3, 4, 5].binary_search(&6).ok(), None); + assert_eq!([1, 2, 3, 4, 5].binary_search(&0).ok(), None); } #[test] @@ -460,15 +460,17 @@ fn test_sort_stability() { // the second item represents which occurrence of that // number this element is, i.e. the second elements // will occur in sorted order. - let mut v: Vec<_> = (0..len).map(|_| { - let n = thread_rng().gen::() % 10; - counts[n] += 1; - (n, counts[n]) - }).collect(); + let mut v: Vec<_> = (0..len) + .map(|_| { + let n = thread_rng().gen::() % 10; + counts[n] += 1; + (n, counts[n]) + }) + .collect(); // only sort on the first element, so an unstable sort // may mix up the counts. - v.sort_by(|&(a,_), &(b,_)| a.cmp(&b)); + v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); // this comparison includes the count (the second item // of the tuple), so elements with equal first items @@ -679,7 +681,7 @@ fn test_rev_iterator() { #[test] fn test_mut_rev_iterator() { let mut xs = [1, 2, 3, 4, 5]; - for (i,x) in xs.iter_mut().rev().enumerate() { + for (i, x) in xs.iter_mut().rev().enumerate() { *x += i; } assert!(xs == [5, 5, 5, 5, 5]) @@ -687,35 +689,32 @@ fn test_mut_rev_iterator() { #[test] fn test_move_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10*a + b), 12345); + let xs = vec![1, 2, 3, 4, 5]; + assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b), + 12345); } #[test] fn test_move_rev_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10*a + b), 54321); + let xs = vec![1, 2, 3, 4, 5]; + assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b), + 54321); } #[test] fn test_splitator() { - let xs = &[1,2,3,4,5]; + let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1], &[3], &[5]]; - assert_eq!(xs.split(|x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 1).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4], &[]]; - assert_eq!(xs.split(|x| *x == 5).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).collect::>(), - splits); + assert_eq!(xs.split(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4], &[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 10).collect::>(), splits); let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; - assert_eq!(xs.split(|_| true).collect::>(), - splits); + assert_eq!(xs.split(|_| true).collect::>(), splits); let xs: &[i32] = &[]; let splits: &[&[i32]] = &[&[]]; @@ -724,17 +723,14 @@ fn test_splitator() { #[test] fn test_splitnator() { - let xs = &[1,2,3,4,5]; + let xs = &[1, 2, 3, 4, 5]; - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[1], &[3,4,5]]; - assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; - assert_eq!(xs.splitn(4, |_| true).collect::>(), - splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[3, 4, 5]]; + assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[], &[], &[4, 5]]; + assert_eq!(xs.splitn(4, |_| true).collect::>(), splits); let xs: &[i32] = &[]; let splits: &[&[i32]] = &[&[]]; @@ -743,40 +739,34 @@ fn test_splitnator() { #[test] fn test_splitnator_mut() { - let xs = &mut [1,2,3,4,5]; + let xs = &mut [1, 2, 3, 4, 5]; - let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]]; + let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]]; assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), splits); - let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; + let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]]; assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::>(), splits); - let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; - assert_eq!(xs.splitn_mut(4, |_| true).collect::>(), - splits); + let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]]; + assert_eq!(xs.splitn_mut(4, |_| true).collect::>(), splits); let xs: &mut [i32] = &mut []; - let splits: &[&mut[i32]] = &[&mut []]; - assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::>(), - splits); + let splits: &[&mut [i32]] = &[&mut []]; + assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::>(), splits); } #[test] fn test_rsplitator() { - let xs = &[1,2,3,4,5]; + let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3], &[1]]; - assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[2,3,4,5], &[]]; - assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[1,2,3,4]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), - splits); + assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[]]; + assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[], &[1, 2, 3, 4]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), splits); let xs: &[i32] = &[]; let splits: &[&[i32]] = &[&[]]; @@ -785,19 +775,16 @@ fn test_rsplitator() { #[test] fn test_rsplitnator() { - let xs = &[1,2,3,4,5]; + let xs = &[1, 2, 3, 4, 5]; - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[5], &[1,2,3]]; - assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; - assert_eq!(xs.rsplitn(4, |_| true).collect::>(), - splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[1, 2, 3]]; + assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[], &[], &[1, 2]]; + assert_eq!(xs.rsplitn(4, |_| true).collect::>(), splits); - let xs: &[i32] = &[]; + let xs: &[i32] = &[]; let splits: &[&[i32]] = &[&[]]; assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::>(), splits); assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none()); @@ -805,55 +792,55 @@ fn test_rsplitnator() { #[test] fn test_windowsator() { - let v = &[1,2,3,4]; + let v = &[1, 2, 3, 4]; - let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; + let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]]; assert_eq!(v.windows(2).collect::>(), wins); - let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; + let wins: &[&[_]] = &[&[1, 2, 3], &[2, 3, 4]]; assert_eq!(v.windows(3).collect::>(), wins); assert!(v.windows(6).next().is_none()); - let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; + let wins: &[&[_]] = &[&[3, 4], &[2, 3], &[1, 2]]; assert_eq!(v.windows(2).rev().collect::>(), wins); } #[test] #[should_panic] fn test_windowsator_0() { - let v = &[1,2,3,4]; + let v = &[1, 2, 3, 4]; let _it = v.windows(0); } #[test] fn test_chunksator() { - let v = &[1,2,3,4,5]; + let v = &[1, 2, 3, 4, 5]; assert_eq!(v.chunks(2).len(), 3); - let chunks: &[&[_]] = &[&[1,2], &[3,4], &[5]]; + let chunks: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; assert_eq!(v.chunks(2).collect::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; + let chunks: &[&[_]] = &[&[1, 2, 3], &[4, 5]]; assert_eq!(v.chunks(3).collect::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3,4,5]]; + let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]]; assert_eq!(v.chunks(6).collect::>(), chunks); - let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; + let chunks: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; assert_eq!(v.chunks(2).rev().collect::>(), chunks); } #[test] #[should_panic] fn test_chunksator_0() { - let v = &[1,2,3,4]; + let v = &[1, 2, 3, 4]; let _it = v.chunks(0); } #[test] fn test_reverse_part() { - let mut values = [1,2,3,4,5]; + let mut values = [1, 2, 3, 4, 5]; values[1..4].reverse(); - assert!(values == [1,4,3,2,5]); + assert!(values == [1, 4, 3, 2, 5]); } #[test] @@ -869,16 +856,15 @@ fn test_show() { test_show_vec!(empty, "[]"); test_show_vec!(vec![1], "[1]"); test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); - test_show_vec!(vec![vec![], vec![1], vec![1, 1]], - "[[], [1], [1, 1]]"); + test_show_vec!(vec![vec![], vec![1], vec![1, 1]], "[[], [1], [1, 1]]"); - let empty_mut: &mut [i32] = &mut[]; + let empty_mut: &mut [i32] = &mut []; test_show_vec!(empty_mut, "[]"); - let v = &mut[1]; + let v = &mut [1]; test_show_vec!(v, "[1]"); - let v = &mut[1, 2, 3]; + let v = &mut [1, 2, 3]; test_show_vec!(v, "[1, 2, 3]"); - let v: &mut[&mut[_]] = &mut[&mut[], &mut[1], &mut[1, 1]]; + let v: &mut [&mut [_]] = &mut [&mut [], &mut [1], &mut [1, 1]]; test_show_vec!(v, "[[], [1], [1, 1]]"); } @@ -914,7 +900,7 @@ fn test_overflow_does_not_cause_segfault_managed() { #[test] fn test_mut_split_at() { - let mut values = [1,2,3,4,5]; + let mut values = [1, 2, 3, 4, 5]; { let (left, right) = values.split_at_mut(2); { @@ -1021,32 +1007,32 @@ fn test_ends_with() { #[test] fn test_mut_splitator() { - let mut xs = [0,1,0,2,3,0,0,4,5,0]; + let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0]; assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); for slice in xs.split_mut(|x| *x == 0) { slice.reverse(); } - assert!(xs == [0,1,0,3,2,0,0,5,4,0]); + assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0]); - let mut xs = [0,1,0,2,3,0,0,4,5,0,6,7]; + let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0, 6, 7]; for slice in xs.split_mut(|x| *x == 0).take(5) { slice.reverse(); } - assert!(xs == [0,1,0,3,2,0,0,5,4,0,6,7]); + assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0, 6, 7]); } #[test] fn test_mut_splitator_rev() { - let mut xs = [1,2,0,3,4,0,0,5,6,0]; + let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0]; for slice in xs.split_mut(|x| *x == 0).rev().take(4) { slice.reverse(); } - assert!(xs == [1,2,0,4,3,0,0,6,5,0]); + assert!(xs == [1, 2, 0, 4, 3, 0, 0, 6, 5, 0]); } #[test] fn test_get_mut() { - let mut v = [0,1,2]; + let mut v = [0, 1, 2]; assert_eq!(v.get_mut(3), None); v.get_mut(1).map(|e| *e = 7); assert_eq!(v[1], 7); @@ -1119,7 +1105,7 @@ fn test_box_slice_clone_panics() { struct Canary { count: Arc, - panics: bool + panics: bool, } impl Drop for Canary { @@ -1130,27 +1116,37 @@ fn test_box_slice_clone_panics() { impl Clone for Canary { fn clone(&self) -> Self { - if self.panics { panic!() } + if self.panics { + panic!() + } Canary { count: self.count.clone(), - panics: self.panics + panics: self.panics, } } } let drop_count = Arc::new(AtomicUsize::new(0)); - let canary = Canary { count: drop_count.clone(), panics: false }; - let panic = Canary { count: drop_count.clone(), panics: true }; + let canary = Canary { + count: drop_count.clone(), + panics: false, + }; + let panic = Canary { + count: drop_count.clone(), + panics: true, + }; spawn(move || { // When xs is dropped, +5. - let xs = vec![canary.clone(), canary.clone(), canary.clone(), - panic, canary].into_boxed_slice(); + let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary] + .into_boxed_slice(); // When panic is cloned, +3. xs.clone(); - }).join().unwrap_err(); + }) + .join() + .unwrap_err(); // Total = 8 assert_eq!(drop_count.load(Ordering::SeqCst), 8); @@ -1198,7 +1194,9 @@ mod bench { sum += *x; } // sum == 11806, to stop dead code elimination. - if sum == 0 {panic!()} + if sum == 0 { + panic!() + } }) } @@ -1217,8 +1215,7 @@ mod bench { #[bench] fn concat(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); + let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); b.iter(|| { xss.concat(); }); @@ -1226,11 +1223,8 @@ mod bench { #[bench] fn join(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.join(&0) - }); + let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| xss.join(&0)); } #[bench] @@ -1245,17 +1239,13 @@ mod bench { #[bench] fn starts_with_same_vector(b: &mut Bencher) { let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.starts_with(&vec) - }) + b.iter(|| vec.starts_with(&vec)) } #[bench] fn starts_with_single_element(b: &mut Bencher) { let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.starts_with(&vec) - }) + b.iter(|| vec.starts_with(&vec)) } #[bench] @@ -1263,25 +1253,19 @@ mod bench { let vec: Vec<_> = (0..100).collect(); let mut match_vec: Vec<_> = (0..99).collect(); match_vec.push(0); - b.iter(|| { - vec.starts_with(&match_vec) - }) + b.iter(|| vec.starts_with(&match_vec)) } #[bench] fn ends_with_same_vector(b: &mut Bencher) { let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.ends_with(&vec) - }) + b.iter(|| vec.ends_with(&vec)) } #[bench] fn ends_with_single_element(b: &mut Bencher) { let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.ends_with(&vec) - }) + b.iter(|| vec.ends_with(&vec)) } #[bench] @@ -1289,24 +1273,18 @@ mod bench { let vec: Vec<_> = (0..100).collect(); let mut match_vec: Vec<_> = (0..100).collect(); match_vec[0] = 200; - b.iter(|| { - vec.starts_with(&match_vec) - }) + b.iter(|| vec.starts_with(&match_vec)) } #[bench] fn contains_last_element(b: &mut Bencher) { let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.contains(&99) - }) + b.iter(|| vec.contains(&99)) } #[bench] fn zero_1kb_from_elem(b: &mut Bencher) { - b.iter(|| { - vec![0u8; 1024] - }); + b.iter(|| vec![0u8; 1024]); } #[bench] @@ -1356,8 +1334,7 @@ mod bench { let mut v = vec![(0, 0); 30]; for _ in 0..100 { let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); + v.insert(rng.gen::() % (l + 1), (1, 1)); } }) } @@ -1418,7 +1395,8 @@ mod bench { fn sort_big_random_small(b: &mut Bencher) { let mut rng = thread_rng(); b.iter(|| { - let mut v = rng.gen_iter::().take(5) + let mut v = rng.gen_iter::() + .take(5) .collect::>(); v.sort(); }); @@ -1429,7 +1407,8 @@ mod bench { fn sort_big_random_medium(b: &mut Bencher) { let mut rng = thread_rng(); b.iter(|| { - let mut v = rng.gen_iter::().take(100) + let mut v = rng.gen_iter::() + .take(100) .collect::>(); v.sort(); }); @@ -1440,7 +1419,8 @@ mod bench { fn sort_big_random_large(b: &mut Bencher) { let mut rng = thread_rng(); b.iter(|| { - let mut v = rng.gen_iter::().take(10000) + let mut v = rng.gen_iter::() + .take(10000) .collect::>(); v.sort(); }); diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index c2eafa1b90f12..7f0fd282ae5e9 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -31,8 +31,8 @@ impl<'a> IntoCow<'a, str> for &'a str { #[test] fn test_from_str() { - let owned: Option<::std::string::String> = "string".parse().ok(); - assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); + let owned: Option<::std::string::String> = "string".parse().ok(); + assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); } #[test] @@ -44,8 +44,7 @@ fn test_unsized_to_string() { #[test] fn test_from_utf8() { let xs = b"hello".to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from("hello")); + assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello")); let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); assert_eq!(String::from_utf8(xs).unwrap(), @@ -87,56 +86,40 @@ fn test_from_utf8_lossy() { String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()); let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\ - foo\u{10000}bar").into_cow()); + assert_eq!(String::from_utf8_lossy(xs), + String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()); // surrogates let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\ - \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); + assert_eq!(String::from_utf8_lossy(xs), + String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); } #[test] fn test_from_utf16() { - let pairs = - [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), - vec![0xd800, 0xdf45, 0xd800, 0xdf3f, - 0xd800, 0xdf3b, 0xd800, 0xdf46, - 0xd800, 0xdf39, 0xd800, 0xdf3b, - 0xd800, 0xdf30, 0x000a]), - - (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), - vec![0xd801, 0xdc12, 0xd801, - 0xdc49, 0xd801, 0xdc2e, 0xd801, - 0xdc40, 0xd801, 0xdc32, 0xd801, - 0xdc4b, 0x0020, 0xd801, 0xdc0f, - 0xd801, 0xdc32, 0xd801, 0xdc4d, - 0x000a]), - - (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), - vec![0xd800, 0xdf00, 0xd800, 0xdf16, - 0xd800, 0xdf0b, 0xd800, 0xdf04, - 0xd800, 0xdf11, 0xd800, 0xdf09, - 0x00b7, 0xd800, 0xdf0c, 0xd800, - 0xdf04, 0xd800, 0xdf15, 0xd800, - 0xdf04, 0xd800, 0xdf0b, 0xd800, - 0xdf09, 0xd800, 0xdf11, 0x000a ]), - - (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), - vec![0xd801, 0xdc8b, 0xd801, 0xdc98, - 0xd801, 0xdc88, 0xd801, 0xdc91, - 0xd801, 0xdc9b, 0xd801, 0xdc92, - 0x0020, 0xd801, 0xdc95, 0xd801, - 0xdc93, 0x0020, 0xd801, 0xdc88, - 0xd801, 0xdc9a, 0xd801, 0xdc8d, - 0x0020, 0xd801, 0xdc8f, 0xd801, - 0xdc9c, 0xd801, 0xdc92, 0xd801, - 0xdc96, 0xd801, 0xdc86, 0x0020, - 0xd801, 0xdc95, 0xd801, 0xdc86, - 0x000a ]), - // Issue #12318, even-numbered non-BMP planes - (String::from("\u{20000}"), - vec![0xD840, 0xDC00])]; + let pairs = [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), + vec![0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, + 0xdf39, 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a]), + + (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), + vec![0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, + 0xdc32, 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, + 0xdc4d, 0x000a]), + + (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), + vec![0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, + 0xdf11, 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, + 0xdf15, 0xd800, 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, + 0x000a]), + + (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), + vec![0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, + 0xdc9b, 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, + 0xd801, 0xdc88, 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, + 0xd801, 0xdc9c, 0xd801, 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, + 0xd801, 0xdc95, 0xd801, 0xdc86, 0x000a]), + // Issue #12318, even-numbered non-BMP planes + (String::from("\u{20000}"), vec![0xD840, 0xDC00])]; for p in &pairs { let (s, u) = (*p).clone(); @@ -173,13 +156,15 @@ fn test_utf16_invalid() { fn test_from_utf16_lossy() { // completely positive cases tested above. // lead + eof - assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}")); + assert_eq!(String::from_utf16_lossy(&[0xD800]), + String::from("\u{FFFD}")); // lead + lead assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}")); // isolated trail - assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}")); + assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), + String::from("a\u{FFFD}")); // general assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), @@ -288,7 +273,8 @@ fn remove() { assert_eq!(s, "ไทย中华Vit Nam; foobar"); } -#[test] #[should_panic] +#[test] +#[should_panic] fn remove_bad() { "ศ".to_string().remove(1); } @@ -302,8 +288,16 @@ fn insert() { assert_eq!(s, "ệfooยbar"); } -#[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); } -#[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); } +#[test] +#[should_panic] +fn insert_bad1() { + "".to_string().insert(1, 't'); +} +#[test] +#[should_panic] +fn insert_bad2() { + "ệ".to_string().insert(1, 't'); +} #[test] fn test_slicing() { @@ -331,8 +325,7 @@ fn test_vectors() { assert_eq!(format!("{:?}", x), "[]"); assert_eq!(format!("{:?}", vec![1]), "[1]"); assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); - assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == - "[[], [1], [1, 1]]"); + assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]"); } #[test] @@ -390,9 +383,7 @@ fn test_into_boxed_str() { #[bench] fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| { - String::with_capacity(100) - }); + b.iter(|| String::with_capacity(100)); } #[bench] @@ -495,25 +486,19 @@ fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { fn bench_from_str(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| { - String::from(s) - }) + b.iter(|| String::from(s)) } #[bench] fn bench_from(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| { - String::from(s) - }) + b.iter(|| String::from(s)) } #[bench] fn bench_to_string(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| { - s.to_string() - }) + b.iter(|| s.to_string()) } diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 0fb00543ddd97..cb99659cc0ead 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -15,7 +15,7 @@ use std::mem::size_of; use test::Bencher; struct DropCounter<'a> { - count: &'a mut u32 + count: &'a mut u32, } impl<'a> Drop for DropCounter<'a> { @@ -33,17 +33,17 @@ fn test_small_vec_struct() { fn test_double_drop() { struct TwoVec { x: Vec, - y: Vec + y: Vec, } let (mut count_x, mut count_y) = (0, 0); { let mut tv = TwoVec { x: Vec::new(), - y: Vec::new() + y: Vec::new(), }; - tv.x.push(DropCounter {count: &mut count_x}); - tv.y.push(DropCounter {count: &mut count_y}); + tv.x.push(DropCounter { count: &mut count_x }); + tv.y.push(DropCounter { count: &mut count_y }); // If Vec had a drop flag, here is where it would be zeroed. // Instead, it should rely on its internal state to prevent @@ -85,12 +85,16 @@ fn test_extend() { let mut w = Vec::new(); v.extend(0..3); - for i in 0..3 { w.push(i) } + for i in 0..3 { + w.push(i) + } assert_eq!(v, w); v.extend(3..10); - for i in 3..10 { w.push(i) } + for i in 3..10 { + w.push(i) + } assert_eq!(v, w); @@ -117,7 +121,7 @@ fn test_extend_ref() { fn test_slice_from_mut() { let mut values = vec![1, 2, 3, 4, 5]; { - let slice = &mut values[2 ..]; + let slice = &mut values[2..]; assert!(slice == [3, 4, 5]); for p in slice { *p += 2; @@ -131,7 +135,7 @@ fn test_slice_from_mut() { fn test_slice_to_mut() { let mut values = vec![1, 2, 3, 4, 5]; { - let slice = &mut values[.. 2]; + let slice = &mut values[..2]; assert!(slice == [1, 2]); for p in slice { *p += 1; @@ -169,7 +173,7 @@ fn test_split_at_mut() { #[test] fn test_clone() { let v: Vec = vec![]; - let w = vec!(1, 2, 3); + let w = vec![1, 2, 3]; assert_eq!(v, v.clone()); @@ -181,9 +185,9 @@ fn test_clone() { #[test] fn test_clone_from() { - let mut v = vec!(); - let three: Vec> = vec!(box 1, box 2, box 3); - let two: Vec> = vec!(box 4, box 5); + let mut v = vec![]; + let three: Vec> = vec![box 1, box 2, box 3]; + let two: Vec> = vec![box 4, box 5]; // zero, long v.clone_from(&three); assert_eq!(v, three); @@ -235,16 +239,22 @@ fn zero_sized_values() { assert_eq!(v.iter_mut().count(), 4); for &mut () in &mut v {} - unsafe { v.set_len(0); } + unsafe { + v.set_len(0); + } assert_eq!(v.iter_mut().count(), 0); } #[test] fn test_partition() { - assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); + assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), + (vec![], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), + (vec![1, 2, 3], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), + (vec![1], vec![2, 3])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), + (vec![], vec![1, 2, 3])); } #[test] @@ -264,7 +274,9 @@ fn test_vec_truncate_drop() { struct Elem(i32); impl Drop for Elem { fn drop(&mut self) { - unsafe { drops += 1; } + unsafe { + drops += 1; + } } } @@ -344,7 +356,7 @@ fn test_slice_out_of_bounds_5() { #[test] #[should_panic] fn test_swap_remove_empty() { - let mut vec= Vec::::new(); + let mut vec = Vec::::new(); vec.swap_remove(0); } @@ -386,7 +398,7 @@ fn test_drain_items() { vec2.push(i); } assert_eq!(vec, []); - assert_eq!(vec2, [ 1, 2, 3 ]); + assert_eq!(vec2, [1, 2, 3]); } #[test] @@ -472,7 +484,7 @@ fn test_into_iter_count() { #[test] fn test_into_iter_clone() { - fn iter_equal>(it: I, slice: &[i32]) { + fn iter_equal>(it: I, slice: &[i32]) { let v: Vec = it.collect(); assert_eq!(&v[..], slice); } diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index 05af9bd704dc8..a02666a50c225 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -52,7 +52,7 @@ fn test_simple() { } #[cfg(test)] -fn test_parameterized(a: T, b: T, c: T, d: T) { +fn test_parameterized(a: T, b: T, c: T, d: T) { let mut deq = VecDeque::new(); assert_eq!(deq.len(), 0); deq.push_front(a.clone()); @@ -186,7 +186,7 @@ enum Taggypar { struct RecCy { x: i32, y: i32, - t: Taggy + t: Taggy, } #[test] @@ -209,10 +209,26 @@ fn test_param_taggypar() { #[test] fn test_param_reccy() { - let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; - let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; - let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; - let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; + let reccy1 = RecCy { + x: 1, + y: 2, + t: One(1), + }; + let reccy2 = RecCy { + x: 345, + y: 2, + t: Two(1, 2), + }; + let reccy3 = RecCy { + x: 1, + y: 777, + t: Three(1, 2, 3), + }; + let reccy4 = RecCy { + x: 19, + y: 252, + t: Two(17, 42), + }; test_parameterized::(reccy1, reccy2, reccy3, reccy4); } @@ -257,13 +273,13 @@ fn test_with_capacity_non_power_two() { // underlying Vec which didn't hold and lead // to corruption. // (Vec grows to next power of two) - //good- [9, 12, 15, X, X, X, X, |6] - //bug- [15, 12, X, X, X, |6, X, X] + // good- [9, 12, 15, X, X, X, X, |6] + // bug- [15, 12, X, X, X, |6, X, X] assert_eq!(d3.pop_front(), Some(6)); // Which leads us to the following state which // would be a failure case. - //bug- [15, 12, X, X, X, X, |X, X] + // bug- [15, 12, X, X, X, X, |X, X] assert_eq!(d3.front(), Some(&9)); } @@ -301,7 +317,7 @@ fn test_iter() { d.push_back(i); } { - let b: &[_] = &[&0,&1,&2,&3,&4]; + let b: &[_] = &[&0, &1, &2, &3, &4]; assert_eq!(d.iter().collect::>(), b); } @@ -309,7 +325,7 @@ fn test_iter() { d.push_front(i); } { - let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; + let b: &[_] = &[&8, &7, &6, &0, &1, &2, &3, &4]; assert_eq!(d.iter().collect::>(), b); } @@ -318,7 +334,10 @@ fn test_iter() { loop { match it.next() { None => break, - _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } + _ => { + len -= 1; + assert_eq!(it.size_hint(), (len, Some(len))) + } } } } @@ -332,14 +351,14 @@ fn test_rev_iter() { d.push_back(i); } { - let b: &[_] = &[&4,&3,&2,&1,&0]; + let b: &[_] = &[&4, &3, &2, &1, &0]; assert_eq!(d.iter().rev().collect::>(), b); } for i in 6..9 { d.push_front(i); } - let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; + let b: &[_] = &[&4, &3, &2, &1, &0, &6, &7, &8]; assert_eq!(d.iter().rev().collect::>(), b); } @@ -424,7 +443,7 @@ fn test_into_iter() { d.push_back(i); } - let b = vec![0,1,2,3,4]; + let b = vec![0, 1, 2, 3, 4]; assert_eq!(d.into_iter().collect::>(), b); } @@ -438,7 +457,7 @@ fn test_into_iter() { d.push_front(i); } - let b = vec![8,7,6,0,1,2,3,4]; + let b = vec![8, 7, 6, 0, 1, 2, 3, 4]; assert_eq!(d.into_iter().collect::>(), b); } @@ -502,7 +521,7 @@ fn test_drain() { d.push_front(i); } - assert_eq!(d.drain(..).collect::>(), [8,7,6,0,1,2,3,4]); + assert_eq!(d.drain(..).collect::>(), [8, 7, 6, 0, 1, 2, 3, 4]); assert!(d.is_empty()); } @@ -532,7 +551,7 @@ fn test_drain() { #[test] fn test_from_iter() { - let v = vec!(1,2,3,4,5,6,7); + let v = vec![1, 2, 3, 4, 5, 6, 7]; let deq: VecDeque<_> = v.iter().cloned().collect(); let u: Vec<_> = deq.iter().cloned().collect(); assert_eq!(u, v); @@ -540,7 +559,7 @@ fn test_from_iter() { let seq = (0..).step_by(2).take(256); let deq: VecDeque<_> = seq.collect(); for (i, &x) in deq.iter().enumerate() { - assert_eq!(2*i, x); + assert_eq!(2 * i, x); } assert_eq!(deq.len(), 256); } @@ -585,20 +604,20 @@ fn test_eq() { #[test] fn test_hash() { - let mut x = VecDeque::new(); - let mut y = VecDeque::new(); + let mut x = VecDeque::new(); + let mut y = VecDeque::new(); - x.push_back(1); - x.push_back(2); - x.push_back(3); + x.push_back(1); + x.push_back(2); + x.push_back(3); - y.push_back(0); - y.push_back(1); - y.pop_front(); - y.push_back(2); - y.push_back(3); + y.push_back(0); + y.push_back(1); + y.pop_front(); + y.push_back(2); + y.push_back(3); - assert!(::hash(&x) == ::hash(&y)); + assert!(::hash(&x) == ::hash(&y)); } #[test] @@ -665,10 +684,12 @@ fn test_show() { let ringbuf: VecDeque<_> = (0..10).collect(); assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter() - .cloned() - .collect(); - assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); + let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"] + .iter() + .cloned() + .collect(); + assert_eq!(format!("{:?}", ringbuf), + "[\"just\", \"one\", \"test\", \"more\"]"); } #[test] @@ -677,7 +698,9 @@ fn test_drop() { struct Elem; impl Drop for Elem { fn drop(&mut self) { - unsafe { drops += 1; } + unsafe { + drops += 1; + } } } @@ -688,7 +711,7 @@ fn test_drop() { ring.push_front(Elem); drop(ring); - assert_eq!(unsafe {drops}, 4); + assert_eq!(unsafe { drops }, 4); } #[test] @@ -697,7 +720,9 @@ fn test_drop_with_pop() { struct Elem; impl Drop for Elem { fn drop(&mut self) { - unsafe { drops += 1; } + unsafe { + drops += 1; + } } } @@ -709,10 +734,10 @@ fn test_drop_with_pop() { drop(ring.pop_back()); drop(ring.pop_front()); - assert_eq!(unsafe {drops}, 2); + assert_eq!(unsafe { drops }, 2); drop(ring); - assert_eq!(unsafe {drops}, 4); + assert_eq!(unsafe { drops }, 4); } #[test] @@ -721,7 +746,9 @@ fn test_drop_clear() { struct Elem; impl Drop for Elem { fn drop(&mut self) { - unsafe { drops += 1; } + unsafe { + drops += 1; + } } } @@ -731,10 +758,10 @@ fn test_drop_clear() { ring.push_back(Elem); ring.push_front(Elem); ring.clear(); - assert_eq!(unsafe {drops}, 4); + assert_eq!(unsafe { drops }, 4); drop(ring); - assert_eq!(unsafe {drops}, 4); + assert_eq!(unsafe { drops }, 4); } #[test] @@ -822,7 +849,7 @@ fn test_get_mut() { match ring.get_mut(1) { Some(x) => *x = -1, - None => () + None => (), }; assert_eq!(ring.get_mut(0), Some(&mut 0)); @@ -852,13 +879,13 @@ fn test_front() { fn test_as_slices() { let mut ring: VecDeque = VecDeque::with_capacity(127); let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; + let first = cap / 2; + let last = cap - first; for i in 0..first { ring.push_back(i); let (left, right) = ring.as_slices(); - let expected: Vec<_> = (0..i+1).collect(); + let expected: Vec<_> = (0..i + 1).collect(); assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -866,7 +893,7 @@ fn test_as_slices() { for j in -last..0 { ring.push_front(j); let (left, right) = ring.as_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_left: Vec<_> = (-last..j + 1).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); assert_eq!(left, &expected_left[..]); assert_eq!(right, &expected_right[..]); @@ -880,13 +907,13 @@ fn test_as_slices() { fn test_as_mut_slices() { let mut ring: VecDeque = VecDeque::with_capacity(127); let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; + let first = cap / 2; + let last = cap - first; for i in 0..first { ring.push_back(i); let (left, right) = ring.as_mut_slices(); - let expected: Vec<_> = (0..i+1).collect(); + let expected: Vec<_> = (0..i + 1).collect(); assert_eq!(left, &expected[..]); assert_eq!(right, []); } @@ -894,7 +921,7 @@ fn test_as_mut_slices() { for j in -last..0 { ring.push_front(j); let (left, right) = ring.as_mut_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_left: Vec<_> = (-last..j + 1).rev().collect(); let expected_right: Vec<_> = (0..first).collect(); assert_eq!(left, &expected_left[..]); assert_eq!(right, &expected_right[..]); diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 65b9a27bb68e2..d80b456181ae4 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -15,11 +15,9 @@ #![allow(non_snake_case)] #![stable(feature = "core_char", since = "1.2.0")] -use iter::Iterator; +use prelude::v1::*; + use mem::transmute; -use option::Option::{None, Some}; -use option::Option; -use slice::SliceExt; // UTF-8 ranges and tags for encoding characters const TAG_CONT: u8 = 0b1000_0000; @@ -413,14 +411,17 @@ pub struct EscapeUnicode { hex_digit_idx: usize, } +// The enum values are ordered so that their representation is the +// same as the remaining length (besides the hexadecimal digits). This +// likely makes `len()` a single load from memory) and inline-worth. #[derive(Clone, Debug)] enum EscapeUnicodeState { - Backslash, - Type, - LeftBrace, - Value, - RightBrace, Done, + RightBrace, + Value, + LeftBrace, + Type, + Backslash, } #[stable(feature = "rust1", since = "1.0.0")] @@ -459,19 +460,17 @@ impl Iterator for EscapeUnicode { } } + #[inline] fn size_hint(&self) -> (usize, Option) { - let n = match self.state { - EscapeUnicodeState::Backslash => 5, - EscapeUnicodeState::Type => 4, - EscapeUnicodeState::LeftBrace => 3, - EscapeUnicodeState::Value => 2, - EscapeUnicodeState::RightBrace => 1, - EscapeUnicodeState::Done => 0, - }; - let n = n + self.hex_digit_idx; + let n = self.len(); (n, Some(n)) } + #[inline] + fn count(self) -> usize { + self.len() + } + fn last(self) -> Option { match self.state { EscapeUnicodeState::Done => None, @@ -485,6 +484,22 @@ impl Iterator for EscapeUnicode { } } +#[stable(feature = "exact_size_escape", since = "1.11.0")] +impl ExactSizeIterator for EscapeUnicode { + #[inline] + fn len(&self) -> usize { + // The match is a single memory access with no branching + self.hex_digit_idx + match self.state { + EscapeUnicodeState::Done => 0, + EscapeUnicodeState::RightBrace => 1, + EscapeUnicodeState::Value => 2, + EscapeUnicodeState::LeftBrace => 3, + EscapeUnicodeState::Type => 4, + EscapeUnicodeState::Backslash => 5, + } + } +} + /// An iterator that yields the literal escape code of a `char`. /// /// This `struct` is created by the [`escape_default()`] method on [`char`]. See @@ -500,9 +515,9 @@ pub struct EscapeDefault { #[derive(Clone, Debug)] enum EscapeDefaultState { - Backslash(char), - Char(char), Done, + Char(char), + Backslash(char), Unicode(EscapeUnicode), } @@ -525,22 +540,15 @@ impl Iterator for EscapeDefault { } } + #[inline] fn size_hint(&self) -> (usize, Option) { - match self.state { - EscapeDefaultState::Char(_) => (1, Some(1)), - EscapeDefaultState::Backslash(_) => (2, Some(2)), - EscapeDefaultState::Unicode(ref iter) => iter.size_hint(), - EscapeDefaultState::Done => (0, Some(0)), - } + let n = self.len(); + (n, Some(n)) } + #[inline] fn count(self) -> usize { - match self.state { - EscapeDefaultState::Char(_) => 1, - EscapeDefaultState::Unicode(iter) => iter.count(), - EscapeDefaultState::Done => 0, - EscapeDefaultState::Backslash(_) => 2, - } + self.len() } fn nth(&mut self, n: usize) -> Option { @@ -580,6 +588,18 @@ impl Iterator for EscapeDefault { } } +#[stable(feature = "exact_size_escape", since = "1.11.0")] +impl ExactSizeIterator for EscapeDefault { + fn len(&self) -> usize { + match self.state { + EscapeDefaultState::Done => 0, + EscapeDefaultState::Char(_) => 1, + EscapeDefaultState::Backslash(_) => 2, + EscapeDefaultState::Unicode(ref iter) => iter.len(), + } + } +} + /// An iterator over `u8` entries represending the UTF-8 encoding of a `char` /// value. /// diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index e8ea993c6940a..e8cd36f3cd70b 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -46,14 +46,42 @@ use marker::Sized; -/// A common trait for cloning an object. +/// A common trait for the ability to explicitly duplicate an object. /// -/// This trait can be used with `#[derive]`. +/// Differs from `Copy` in that `Copy` is implicit and extremely inexpensive, while +/// `Clone` is always explicit and may or may not be expensive. In order to enforce +/// these characteristics, Rust does not allow you to reimplement `Copy`, but you +/// may reimplement `Clone` and run arbitrary code. +/// +/// Since `Clone` is more general than `Copy`, you can automatically make anything +/// `Copy` be `Clone` as well. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d +/// implementation of `clone()` calls `clone()` on each field. +/// +/// ## How can I implement `Clone`? /// /// Types that are `Copy` should have a trivial implementation of `Clone`. More formally: /// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`. /// Manual implementations should be careful to uphold this invariant; however, unsafe code /// must not rely on it to ensure memory safety. +/// +/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard +/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of +/// `Clone` cannot be `derive`d, but can be implemented as: +/// +/// ``` +/// #[derive(Copy)] +/// struct Stats { +/// frequencies: [i32; 100], +/// } +/// +/// impl Clone for Stats { +/// fn clone(&self) -> Stats { *self } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Clone : Sized { /// Returns a copy of the value. diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index d3481ba3f0523..8764766b2ef86 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -53,12 +53,43 @@ use option::Option::{self, Some}; /// symmetrically and transitively: if `T: PartialEq` and `U: PartialEq` /// then `U: PartialEq` and `T: PartialEq`. /// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d on structs, two +/// instances are equal if all fields are equal, and not equal if any fields +/// are not equal. When `derive`d on enums, each variant is equal to itself +/// and not equal to the other variants. +/// +/// ## How can I implement `PartialEq`? +/// /// PartialEq only requires the `eq` method to be implemented; `ne` is defined /// in terms of it by default. Any manual implementation of `ne` *must* respect /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and /// only if `a != b`. /// -/// This trait can be used with `#[derive]`. +/// An example implementation for a domain in which two books are considered +/// the same book if their ISBN matches, even if the formats differ: +/// +/// ``` +/// enum BookFormat { Paperback, Hardback, Ebook } +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// let b3 = Book { isbn: 10, format: BookFormat::Paperback }; +/// +/// assert!(b1 == b2); +/// assert!(b1 != b3); +/// ``` /// /// # Examples /// @@ -96,7 +127,32 @@ pub trait PartialEq { /// This property cannot be checked by the compiler, and therefore `Eq` implies /// `PartialEq`, and has no extra methods. /// -/// This trait can be used with `#[derive]`. +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has +/// no extra methods, it is only informing the compiler that this is an +/// equivalence relation rather than a partial equivalence relation. Note that +/// the `derive` strategy requires all fields are `PartialEq`, which isn't +/// always desired. +/// +/// ## How can I implement `Eq`? +/// +/// If you cannot use the `derive` strategy, specify that your type implements +/// `Eq`, which has no methods: +/// +/// ``` +/// enum BookFormat { Paperback, Hardback, Ebook } +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// impl Eq for Book {} +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Eq: PartialEq { // FIXME #13101: this method is used solely by #[deriving] to @@ -190,8 +246,49 @@ impl Ordering { /// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. /// +/// ## Derivable +/// /// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic /// ordering based on the top-to-bottom declaration order of the struct's members. +/// +/// ## How can I implement `Ord`? +/// +/// `Ord` requires that the type also be `PartialOrd` and `Eq` (which requires `PartialEq`). +/// +/// Then you must define an implementation for `cmp()`. You may find it useful to use +/// `cmp()` on your type's fields. +/// +/// Here's an example where you want to sort people by height only, disregarding `id` +/// and `name`: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Eq)] +/// struct Person { +/// id: u32, +/// name: String, +/// height: u32, +/// } +/// +/// impl Ord for Person { +/// fn cmp(&self, other: &Person) -> Ordering { +/// self.height.cmp(&other.height) +/// } +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Ord: Eq + PartialOrd { /// This method returns an `Ordering` between `self` and `other`. @@ -242,6 +339,13 @@ impl PartialOrd for Ordering { /// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: /// PartialOrd`. /// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic +/// ordering based on the top-to-bottom declaration order of the struct's members. +/// +/// ## How can I implement `Ord`? +/// /// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated /// from default implementations. /// @@ -249,8 +353,64 @@ impl PartialOrd for Ordering { /// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == /// false` (cf. IEEE 754-2008 section 5.11). /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce an ordering -/// based on the top-to-bottom declaration order of the struct's members. +/// `PartialOrd` requires your type to be `PartialEq`. +/// +/// If your type is `Ord`, you can implement `partial_cmp()` by using `cmp()`: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Eq)] +/// struct Person { +/// id: u32, +/// name: String, +/// height: u32, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl Ord for Person { +/// fn cmp(&self, other: &Person) -> Ordering { +/// self.height.cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` +/// +/// You may also find it useful to use `partial_cmp()` on your type`s fields. Here +/// is an example of `Person` types who have a floating-point `height` field that +/// is the only field to be used for sorting: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// height: f64, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// self.height.partial_cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` /// /// # Examples /// diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 12c4a5ca200ad..485ddae07fbff 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -9,76 +9,6 @@ // except according to those terms. //! The `Default` trait for types which may have meaningful default values. -//! -//! Sometimes, you want to fall back to some kind of default value, and -//! don't particularly care what it is. This comes up often with `struct`s -//! that define a set of options: -//! -//! ``` -//! # #[allow(dead_code)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! } -//! ``` -//! -//! How can we define some default values? You can use `Default`: -//! -//! ``` -//! # #[allow(dead_code)] -//! #[derive(Default)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! } -//! -//! -//! fn main() { -//! let options: SomeOptions = Default::default(); -//! } -//! ``` -//! -//! Now, you get all of the default values. Rust implements `Default` for various primitives types. -//! If you have your own type, you need to implement `Default` yourself: -//! -//! ``` -//! # #![allow(dead_code)] -//! enum Kind { -//! A, -//! B, -//! C, -//! } -//! -//! impl Default for Kind { -//! fn default() -> Kind { Kind::A } -//! } -//! -//! #[derive(Default)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! baz: Kind, -//! } -//! -//! -//! fn main() { -//! let options: SomeOptions = Default::default(); -//! } -//! ``` -//! -//! If you want to override a particular option, but still retain the other defaults: -//! -//! ``` -//! # #[allow(dead_code)] -//! # #[derive(Default)] -//! # struct SomeOptions { -//! # foo: i32, -//! # bar: f32, -//! # } -//! fn main() { -//! let options = SomeOptions { foo: 42, ..Default::default() }; -//! } -//! ``` #![stable(feature = "rust1", since = "1.0.0")] @@ -86,8 +16,72 @@ use marker::Sized; /// A trait for giving a type a useful default value. /// -/// A struct can derive default implementations of `Default` for basic types using -/// `#[derive(Default)]`. +/// Sometimes, you want to fall back to some kind of default value, and +/// don't particularly care what it is. This comes up often with `struct`s +/// that define a set of options: +/// +/// ``` +/// # #[allow(dead_code)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// ``` +/// +/// How can we define some default values? You can use `Default`: +/// +/// ``` +/// # #[allow(dead_code)] +/// #[derive(Default)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// +/// +/// fn main() { +/// let options: SomeOptions = Default::default(); +/// } +/// ``` +/// +/// Now, you get all of the default values. Rust implements `Default` for various primitives types. +/// +/// If you want to override a particular option, but still retain the other defaults: +/// +/// ``` +/// # #[allow(dead_code)] +/// # #[derive(Default)] +/// # struct SomeOptions { +/// # foo: i32, +/// # bar: f32, +/// # } +/// fn main() { +/// let options = SomeOptions { foo: 42, ..Default::default() }; +/// } +/// ``` +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all of the type's fields implement +/// `Default`. When `derive`d, it will use the default value for each field's type. +/// +/// ## How can I implement `Default`? +/// +/// Provide an implementation for the `default()` method that returns the value of +/// your type that should be the default: +/// +/// ``` +/// # #![allow(dead_code)] +/// enum Kind { +/// A, +/// B, +/// C, +/// } +/// +/// impl Default for Kind { +/// fn default() -> Kind { Kind::A } +/// } +/// ``` /// /// # Examples /// diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index dde4d03dad8ac..6579e5dab5432 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -318,7 +318,11 @@ impl<'a> Display for Arguments<'a> { /// /// [module]: ../../std/fmt/index.html /// -/// This trait can be used with `#[derive]`. +/// This trait can be used with `#[derive]` if all fields implement `Debug`. When +/// `derive`d for structs, it will use the name of the `struct`, then `{`, then a +/// comma-separated list of each field's name and `Debug` value, then `}`. For +/// `enum`s, it will use the name of the variant and, if applicable, `(`, then the +/// `Debug` values of the fields, then `)`. /// /// # Examples /// diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 4d0fed9833436..051eb974895ce 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -38,7 +38,7 @@ //! ``` //! //! If you need more control over how a value is hashed, you need to implement -//! the trait `Hash`: +//! the `Hash` trait: //! //! ```rust //! use std::hash::{Hash, Hasher, SipHasher}; @@ -97,7 +97,33 @@ mod sip; /// In other words, if two keys are equal, their hashes should also be equal. /// `HashMap` and `HashSet` both rely on this behavior. /// -/// This trait can be used with `#[derive]`. +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all fields implement `Hash`. +/// When `derive`d, the resulting hash will be the combination of the values +/// from calling `.hash()` on each field. +/// +/// ## How can I implement `Hash`? +/// +/// If you need more control over how a value is hashed, you need to implement +/// the `Hash` trait: +/// +/// ``` +/// use std::hash::{Hash, Hasher}; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// phone: u64, +/// } +/// +/// impl Hash for Person { +/// fn hash(&self, state: &mut H) { +/// self.id.hash(state); +/// self.phone.hash(state); +/// } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { /// Feeds this value into the state given, updating the hasher as necessary. diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8a9f662bf83aa..0350824ee359d 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -168,6 +168,16 @@ extern "rust-intrinsic" { pub fn atomic_singlethreadfence_rel(); pub fn atomic_singlethreadfence_acqrel(); + /// Magic intrinsic that derives its meaning from attributes + /// attached to the function. + /// + /// For example, dataflow uses this to inject static assertions so + /// that `rustc_peek(potentially_uninitialized)` would actually + /// double-check that dataflow did indeed compute that it is + /// uninitialized at that point in the control flow. + #[cfg(not(stage0))] + pub fn rustc_peek(_: T) -> T; + /// Aborts the execution of the process. pub fn abort() -> !; diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 17f7c0a773e68..f964527b4b41f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1125,6 +1125,7 @@ impl Peekable { /// ``` #[unstable(feature = "peekable_is_empty", issue = "32111")] #[inline] + #[rustc_deprecated(since = "1.10.0", reason = "replaced by .peek().is_none()")] pub fn is_empty(&mut self) -> bool { self.peek().is_none() } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 1ed2a219fac3a..c18d230be31af 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -136,6 +136,26 @@ pub trait Unsize { /// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` /// ``` /// +/// ## When can my type _not_ be `Copy`? +/// +/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased +/// mutable reference, and copying `String` would result in two attempts to free the same buffer. +/// +/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's +/// managing some resource besides its own `size_of::()` bytes. +/// +/// ## When should my type be `Copy`? +/// +/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing +/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, +/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking +/// change: that second example would fail to compile if we made `Foo` non-`Copy`. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all of its components implement `Copy` and the type +/// implements `Clone`. The implementation will copy the bytes of each field using `memcpy`. +/// /// ## How can I implement `Copy`? /// /// There are two ways to implement `Copy` on your type: @@ -155,25 +175,6 @@ pub trait Unsize { /// /// There is a small difference between the two: the `derive` strategy will also place a `Copy` /// bound on type parameters, which isn't always desired. -/// -/// ## When can my type _not_ be `Copy`? -/// -/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased -/// mutable reference, and copying `String` would result in two attempts to free the same buffer. -/// -/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's -/// managing some resource besides its own `size_of::()` bytes. -/// -/// ## When should my type be `Copy`? -/// -/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing -/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, -/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking -/// change: that second example would fail to compile if we made `Foo` non-`Copy`. -/// -/// # Derivable -/// -/// This trait can be used with `#[derive]`. #[stable(feature = "rust1", since = "1.0.0")] #[lang = "copy"] pub trait Copy : Clone { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 542dfcbe6284f..a0e978f783d73 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -106,6 +106,10 @@ pub trait SliceExt { #[stable(feature = "core", since = "1.6.0")] fn binary_search_by(&self, f: F) -> Result where F: FnMut(&Self::Item) -> Ordering; + #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] + fn binary_search_by_key(&self, b: &B, f: F) -> Result + where F: FnMut(&Self::Item) -> B, + B: Ord; #[stable(feature = "core", since = "1.6.0")] fn len(&self) -> usize; #[stable(feature = "core", since = "1.6.0")] @@ -157,11 +161,6 @@ pub trait SliceExt { fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone; #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; - - #[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "33018")] - fn binary_search_by_key(&self, b: &B, f: F) -> Result - where F: FnMut(&Self::Item) -> B, - B: Ord; } // Use macros to be generic over const/mut diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 1bdab88d71da0..d0a64de07e51c 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -299,7 +299,6 @@ impl AtomicBool { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); @@ -318,7 +317,7 @@ impl AtomicBool { /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] - #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] pub fn compare_exchange(&self, current: bool, new: bool, @@ -347,7 +346,6 @@ impl AtomicBool { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let val = AtomicBool::new(false); @@ -362,7 +360,7 @@ impl AtomicBool { /// } /// ``` #[inline] - #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] pub fn compare_exchange_weak(&self, current: bool, new: bool, @@ -645,7 +643,6 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; @@ -658,7 +655,7 @@ impl AtomicPtr { /// Ordering::SeqCst, Ordering::Relaxed); /// ``` #[inline] - #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] pub fn compare_exchange(&self, current: *mut T, new: *mut T, @@ -693,7 +690,6 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// /// let some_ptr = AtomicPtr::new(&mut 5); @@ -708,7 +704,7 @@ impl AtomicPtr { /// } /// ``` #[inline] - #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")] + #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] pub fn compare_exchange_weak(&self, current: *mut T, new: *mut T, @@ -901,7 +897,6 @@ macro_rules! atomic_int { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicIsize, Ordering}; /// /// let some_isize = AtomicIsize::new(5); @@ -945,7 +940,6 @@ macro_rules! atomic_int { /// # Examples /// /// ``` - /// # #![feature(extended_compare_and_swap)] /// use std::sync::atomic::{AtomicIsize, Ordering}; /// /// let val = AtomicIsize::new(4); @@ -1115,14 +1109,14 @@ atomic_int! { #[cfg(any(stage0, target_has_atomic = "ptr"))] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), - unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767"), + stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(any(stage0, target_has_atomic = "ptr"))] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), - unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767"), + stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), usize AtomicUsize ATOMIC_USIZE_INIT } diff --git a/src/libcoretest/any.rs b/src/libcoretest/any.rs index a9fc8913182b3..1ff1d470064aa 100644 --- a/src/libcoretest/any.rs +++ b/src/libcoretest/any.rs @@ -35,7 +35,9 @@ fn any_referenced() { #[test] fn any_owning() { - let (a, b, c) = (box 5_usize as Box, box TEST as Box, box Test as Box); + let (a, b, c) = (box 5_usize as Box, + box TEST as Box, + box Test as Box); assert!(a.is::()); assert!(!b.is::()); @@ -56,12 +58,12 @@ fn any_downcast_ref() { match a.downcast_ref::() { Some(&5) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a.downcast_ref::() { None => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } } @@ -79,7 +81,7 @@ fn any_downcast_mut() { assert_eq!(*x, 5); *x = 612; } - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { @@ -87,27 +89,27 @@ fn any_downcast_mut() { assert_eq!(*x, 7); *x = 413; } - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a_r.downcast_mut::() { None => (), - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { None => (), - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a_r.downcast_mut::() { Some(&mut 612) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { Some(&mut 413) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } } diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs index b6bb5fddf4a4b..d3871b46f2465 100644 --- a/src/libcoretest/atomic.rs +++ b/src/libcoretest/atomic.rs @@ -24,8 +24,8 @@ fn bool_() { #[test] fn bool_and() { let a = AtomicBool::new(true); - assert_eq!(a.fetch_and(false, SeqCst),true); - assert_eq!(a.load(SeqCst),false); + assert_eq!(a.fetch_and(false, SeqCst), true); + assert_eq!(a.load(SeqCst), false); } #[test] @@ -72,7 +72,7 @@ fn int_xor() { static S_FALSE: AtomicBool = AtomicBool::new(false); static S_TRUE: AtomicBool = AtomicBool::new(true); -static S_INT: AtomicIsize = AtomicIsize::new(0); +static S_INT: AtomicIsize = AtomicIsize::new(0); static S_UINT: AtomicUsize = AtomicUsize::new(0); #[test] diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index c0b22274ee9d6..9c2493c800065 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -214,7 +214,9 @@ fn as_unsafe_cell() { assert_eq!(1, unsafe { *c1.as_unsafe_cell().get() }); let c2: Cell = Cell::new(0); - unsafe { *c2.as_unsafe_cell().get() = 1; } + unsafe { + *c2.as_unsafe_cell().get() = 1; + } assert_eq!(1, c2.get()); let r1: RefCell = RefCell::new(0); @@ -222,7 +224,9 @@ fn as_unsafe_cell() { assert_eq!(1, unsafe { *r1.as_unsafe_cell().get() }); let r2: RefCell = RefCell::new(0); - unsafe { *r2.as_unsafe_cell().get() = 1; } + unsafe { + *r2.as_unsafe_cell().get() = 1; + } assert_eq!(1, *r2.borrow()); } @@ -279,5 +283,3 @@ fn refcell_ref_coercion() { assert_eq!(&*coerced, comp); } } - - diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs index e959e71daf73f..73943407b9f99 100644 --- a/src/libcoretest/char.rs +++ b/src/libcoretest/char.rs @@ -115,12 +115,12 @@ fn test_is_control() { #[test] fn test_is_digit() { - assert!('2'.is_numeric()); - assert!('7'.is_numeric()); - assert!(!'c'.is_numeric()); - assert!(!'i'.is_numeric()); - assert!(!'z'.is_numeric()); - assert!(!'Q'.is_numeric()); + assert!('2'.is_numeric()); + assert!('7'.is_numeric()); + assert!(!'c'.is_numeric()); + assert!(!'i'.is_numeric()); + assert!(!'z'.is_numeric()); + assert!(!'Q'.is_numeric()); } #[test] @@ -158,7 +158,9 @@ fn test_escape_default() { #[test] fn test_escape_unicode() { - fn string(c: char) -> String { c.escape_unicode().collect() } + fn string(c: char) -> String { + c.escape_unicode().collect() + } let s = string('\x00'); assert_eq!(s, "\\u{0}"); @@ -216,8 +218,8 @@ fn test_len_utf16() { fn test_decode_utf16() { fn check(s: &[u16], expected: &[Result]) { let v = char::decode_utf16(s.iter().cloned()) - .map(|r| r.map_err(|e| e.unpaired_surrogate())) - .collect::>(); + .map(|r| r.map_err(|e| e.unpaired_surrogate())) + .collect::>(); assert_eq!(v, expected); } check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]); @@ -276,6 +278,12 @@ fn eu_iterator_specializations() { // Check last assert_eq!(iter.clone().last(), Some('}')); + // Check len + assert_eq!(iter.len(), len - offset); + + // Check size_hint (= len in ExactSizeIterator) + assert_eq!(iter.size_hint(), (iter.len(), Some(iter.len()))); + // Check counting assert_eq!(iter.clone().count(), len - offset); diff --git a/src/libcoretest/cmp.rs b/src/libcoretest/cmp.rs index 051356cad1640..11147639f3bcc 100644 --- a/src/libcoretest/cmp.rs +++ b/src/libcoretest/cmp.rs @@ -45,7 +45,7 @@ fn test_ordering_order() { fn test_user_defined_eq() { // Our type. struct SketchyNum { - num : isize + num: isize, } // Our implementation of `PartialEq` to support `==` and `!=`. @@ -57,6 +57,6 @@ fn test_user_defined_eq() { } // Now these binary operators will work when applied! - assert!(SketchyNum {num: 37} == SketchyNum {num: 34}); - assert!(SketchyNum {num: 25} != SketchyNum {num: 57}); + assert!(SketchyNum { num: 37 } == SketchyNum { num: 34 }); + assert!(SketchyNum { num: 25 } != SketchyNum { num: 57 }); } diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 4ea42644ecdfd..67621f201a938 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -29,7 +29,9 @@ impl Hasher for MyHasher { self.hash += *byte as u64; } } - fn finish(&self) -> u64 { self.hash } + fn finish(&self) -> u64 { + self.hash + } } @@ -61,15 +63,15 @@ fn test_writer_hasher() { assert_eq!(hash(&'a'), 97); let s: &str = "a"; - assert_eq!(hash(& s), 97 + 0xFF); + assert_eq!(hash(&s), 97 + 0xFF); // FIXME (#18283) Enable test - //let s: Box = box "a"; - //assert_eq!(hasher.hash(& s), 97 + 0xFF); + // let s: Box = box "a"; + // assert_eq!(hasher.hash(& s), 97 + 0xFF); let cs: &[u8] = &[1, 2, 3]; - assert_eq!(hash(& cs), 9); + assert_eq!(hash(&cs), 9); // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let cs: Box<[u8]> = Box::new([1, 2, 3]); - assert_eq!(hash(& cs), 9); + assert_eq!(hash(&cs), 9); // FIXME (#18248) Add tests for hashing Rc and Rc<[T]> @@ -80,13 +82,23 @@ fn test_writer_hasher() { assert_eq!(hash(&ptr), 5); } -struct Custom { hash: u64 } -struct CustomHasher { output: u64 } +struct Custom { + hash: u64, +} +struct CustomHasher { + output: u64, +} impl Hasher for CustomHasher { - fn finish(&self) -> u64 { self.output } - fn write(&mut self, _: &[u8]) { panic!() } - fn write_u64(&mut self, data: u64) { self.output = data; } + fn finish(&self) -> u64 { + self.output + } + fn write(&mut self, _: &[u8]) { + panic!() + } + fn write_u64(&mut self, data: u64) { + self.output = data; + } } impl Default for CustomHasher { diff --git a/src/libcoretest/hash/sip.rs b/src/libcoretest/hash/sip.rs index 9b6cedd25b741..24d11707e41e6 100644 --- a/src/libcoretest/hash/sip.rs +++ b/src/libcoretest/hash/sip.rs @@ -66,72 +66,70 @@ fn hash_bytes(x: &[u8]) -> u64 { #[test] #[allow(unused_must_use)] fn test_siphash() { - let vecs : [[u8; 8]; 64] = [ - [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], - [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], - [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], - [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], - [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], - [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], - [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], - [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], - [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], - [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], - [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], - [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], - [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], - [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], - [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], - [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], - [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], - [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], - [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], - [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], - [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], - [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], - [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], - [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], - [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], - [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], - [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], - [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], - [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], - [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], - [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], - [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], - [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], - [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], - [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], - [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], - [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], - [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], - [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], - [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], - [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], - [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], - [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], - [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], - [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], - [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], - [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], - [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], - [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], - [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], - [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], - [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], - [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], - [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], - [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], - [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], - [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], - [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], - [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], - [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], - [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], - [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], - [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], - [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] - ]; + let vecs: [[u8; 8]; 64] = [[0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72], + [0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74], + [0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d], + [0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85], + [0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf], + [0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18], + [0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb], + [0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab], + [0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93], + [0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e], + [0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a], + [0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4], + [0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75], + [0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14], + [0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7], + [0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1], + [0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f], + [0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69], + [0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b], + [0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb], + [0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe], + [0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0], + [0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93], + [0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8], + [0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8], + [0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc], + [0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17], + [0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f], + [0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde], + [0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6], + [0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad], + [0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32], + [0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71], + [0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7], + [0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12], + [0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15], + [0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31], + [0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02], + [0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca], + [0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a], + [0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e], + [0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad], + [0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18], + [0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4], + [0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9], + [0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9], + [0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb], + [0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0], + [0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6], + [0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7], + [0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee], + [0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1], + [0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a], + [0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81], + [0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f], + [0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24], + [0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7], + [0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea], + [0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60], + [0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66], + [0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c], + [0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f], + [0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5], + [0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95]]; let k0 = 0x_07_06_05_04_03_02_01_00; let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; @@ -157,19 +155,22 @@ fn test_siphash() { } } -#[test] #[cfg(target_arch = "arm")] +#[test] +#[cfg(target_arch = "arm")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert!(hash(&(val as u64)) != hash(&(val as usize))); assert_eq!(hash(&(val as u32)), hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86_64")] +#[test] +#[cfg(target_arch = "x86_64")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert_eq!(hash(&(val as u64)), hash(&(val as usize))); assert!(hash(&(val as u32)) != hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86")] +#[test] +#[cfg(target_arch = "x86")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert!(hash(&(val as u64)) != hash(&(val as usize))); @@ -276,9 +277,7 @@ officia deserunt mollit anim id est laborum."; fn bench_u32(b: &mut Bencher) { let u = 162629500u32; let u = black_box(u); - b.iter(|| { - hash(&u) - }); + b.iter(|| hash(&u)); b.bytes = 8; } @@ -288,9 +287,7 @@ fn bench_u32_keyed(b: &mut Bencher) { let u = black_box(u); let k1 = black_box(0x1); let k2 = black_box(0x2); - b.iter(|| { - hash_with_keys(k1, k2, &u) - }); + b.iter(|| hash_with_keys(k1, k2, &u)); b.bytes = 8; } @@ -298,62 +295,48 @@ fn bench_u32_keyed(b: &mut Bencher) { fn bench_u64(b: &mut Bencher) { let u = 16262950014981195938u64; let u = black_box(u); - b.iter(|| { - hash(&u) - }); + b.iter(|| hash(&u)); b.bytes = 8; } #[bench] fn bench_bytes_4(b: &mut Bencher) { let data = black_box([b' '; 4]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 4; } #[bench] fn bench_bytes_7(b: &mut Bencher) { let data = black_box([b' '; 7]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 7; } #[bench] fn bench_bytes_8(b: &mut Bencher) { let data = black_box([b' '; 8]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 8; } #[bench] fn bench_bytes_a_16(b: &mut Bencher) { let data = black_box([b' '; 16]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 16; } #[bench] fn bench_bytes_b_32(b: &mut Bencher) { let data = black_box([b' '; 32]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 32; } #[bench] fn bench_bytes_c_128(b: &mut Bencher) { let data = black_box([b' '; 128]); - b.iter(|| { - hash_bytes(&data) - }); + b.iter(|| hash_bytes(&data)); b.bytes = 128; } diff --git a/src/libcoretest/intrinsics.rs b/src/libcoretest/intrinsics.rs index 2b380abf63c58..55c14c1d0ea4b 100644 --- a/src/libcoretest/intrinsics.rs +++ b/src/libcoretest/intrinsics.rs @@ -12,7 +12,8 @@ use core::any::TypeId; #[test] fn test_typeid_sized_types() { - struct X; struct Y(u32); + struct X; + struct Y(u32); assert_eq!(TypeId::of::(), TypeId::of::()); assert_eq!(TypeId::of::(), TypeId::of::()); @@ -22,7 +23,8 @@ fn test_typeid_sized_types() { #[test] fn test_typeid_unsized_types() { trait Z {} - struct X(str); struct Y(Z + 'static); + struct X(str); + struct Y(Z + 'static); assert_eq!(TypeId::of::(), TypeId::of::()); assert_eq!(TypeId::of::(), TypeId::of::()); diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 56b10d0b79b41..54fca291e5ec2 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -902,15 +902,6 @@ fn test_range_step() { assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } -#[test] -fn test_peekable_is_empty() { - let a = [1]; - let mut it = a.iter().peekable(); - assert!( !it.is_empty() ); - it.next(); - assert!( it.is_empty() ); -} - #[test] fn test_repeat() { let mut it = repeat(42); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 603dda2c96d2f..88d73df937f7e 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -24,7 +24,6 @@ #![feature(iter_arith)] #![feature(libc)] #![feature(nonzero)] -#![feature(peekable_is_empty)] #![feature(rand)] #![feature(raw)] #![feature(slice_patterns)] diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 5bc08376d257c..b3f3d803c1804 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -92,7 +92,8 @@ fn test_transmute_copy() { #[test] fn test_transmute() { - trait Foo { fn dummy(&self) { } } + trait Foo { + fn dummy(&self) {} } impl Foo for isize {} let a = box 100isize as Box; @@ -112,7 +113,7 @@ fn test_transmute() { // Static/dynamic method dispatch struct Struct { - field: isize + field: isize, } trait Trait { @@ -129,17 +130,13 @@ impl Trait for Struct { fn trait_vtable_method_call(b: &mut Bencher) { let s = Struct { field: 10 }; let t = &s as &Trait; - b.iter(|| { - t.method() - }); + b.iter(|| t.method()); } #[bench] fn trait_static_method_call(b: &mut Bencher) { let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); + b.iter(|| s.method()); } // Overhead of various match forms @@ -150,14 +147,14 @@ fn match_option_some(b: &mut Bencher) { b.iter(|| { match x { Some(y) => y, - None => 11 + None => 11, } }); } #[bench] fn match_vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; + let x = [1, 2, 3, 4, 5, 6]; b.iter(|| { match x { [1,2,3,..] => 10, diff --git a/src/libcoretest/nonzero.rs b/src/libcoretest/nonzero.rs index 7a367ddeec8d4..ce86e5aba3abe 100644 --- a/src/libcoretest/nonzero.rs +++ b/src/libcoretest/nonzero.rs @@ -15,9 +15,7 @@ use std::mem::size_of; #[test] fn test_create_nonzero_instance() { - let _a = unsafe { - NonZero::new(21) - }; + let _a = unsafe { NonZero::new(21) }; } #[test] @@ -27,17 +25,15 @@ fn test_size_nonzero_in_option() { #[test] fn test_match_on_nonzero_option() { - let a = Some(unsafe { - NonZero::new(42) - }); + let a = Some(unsafe { NonZero::new(42) }); match a { Some(val) => assert_eq!(*val, 42), - None => panic!("unexpected None while matching on Some(NonZero(_))") + None => panic!("unexpected None while matching on Some(NonZero(_))"), } match unsafe { Some(NonZero::new(43)) } { Some(val) => assert_eq!(*val, 43), - None => panic!("unexpected None while matching on Some(NonZero(_))") + None => panic!("unexpected None while matching on Some(NonZero(_))"), } } @@ -55,7 +51,7 @@ fn test_match_option_vec() { let a = Some(vec![1, 2, 3, 4]); match a { Some(v) => assert_eq!(v, [1, 2, 3, 4]), - None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])") + None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])"), } } @@ -66,7 +62,7 @@ fn test_match_option_rc() { let five = Rc::new(5); match Some(five) { Some(r) => assert_eq!(*r, 5), - None => panic!("unexpected None while matching on Some(Rc::new(5))") + None => panic!("unexpected None while matching on Some(Rc::new(5))"), } } @@ -77,7 +73,7 @@ fn test_match_option_arc() { let five = Arc::new(5); match Some(five) { Some(a) => assert_eq!(*a, 5), - None => panic!("unexpected None while matching on Some(Arc::new(5))") + None => panic!("unexpected None while matching on Some(Arc::new(5))"), } } @@ -95,6 +91,6 @@ fn test_match_option_string() { let five = "Five".to_string(); match Some(five) { Some(s) => assert_eq!(s, "Five"), - None => panic!("unexpected None while matching on Some(String { ... })") + None => panic!("unexpected None while matching on Some(String { ... })"), } } diff --git a/src/libcoretest/num/bignum.rs b/src/libcoretest/num/bignum.rs index 58a9dd1b128ce..e05396693c758 100644 --- a/src/libcoretest/num/bignum.rs +++ b/src/libcoretest/num/bignum.rs @@ -19,12 +19,18 @@ fn test_from_u64_overflow() { #[test] fn test_add() { - assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7)); - assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3)); - assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3)); - assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001)); - assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665)); - assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665)); + assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), + Big::from_small(7)); + assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), + Big::from_small(3)); + assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), + Big::from_small(3)); + assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), + Big::from_u64(0x10001)); + assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), + Big::from_u64(0x10665)); + assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), + Big::from_u64(0x10665)); } #[test] @@ -46,7 +52,8 @@ fn test_add_small() { assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3)); assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257)); assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000)); - assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033)); + assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), + Big::from_u64(0x3033)); assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165)); } @@ -58,11 +65,16 @@ fn test_add_small_overflow() { #[test] fn test_sub() { - assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3)); - assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc)); - assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789)); - assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1)); - assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0)); + assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), + Big::from_small(3)); + assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), + Big::from_u64(0xfedc)); + assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), + Big::from_u64(0x789)); + assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), + Big::from_small(1)); + assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), + Big::from_small(0)); } #[test] @@ -80,8 +92,10 @@ fn test_sub_underflow_2() { #[test] fn test_mul_small() { assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35)); - assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01)); - assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff)); + assert_eq!(*Big::from_small(0xff).mul_small(0xff), + Big::from_u64(0xfe01)); + assert_eq!(*Big::from_u64(0xffffff / 13).mul_small(13), + Big::from_u64(0xffffff)); } #[test] @@ -141,12 +155,18 @@ fn test_mul_pow5_overflow_2() { #[test] fn test_mul_digits() { assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15)); - assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01)); - assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2)); - assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3)); - assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e)); - assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff)); - assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff)); + assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), + Big::from_u64(0xfe01)); + assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), + Big::from_u64(0x4edc2)); + assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), + Big::from_u64(0x7530c3)); + assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), + Big::from_u64(0x3ae13e)); + assert_eq!(*Big::from_u64(0xffffff / 13).mul_digits(&[13]), + Big::from_u64(0xffffff)); + assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), + Big::from_u64(0xffffff)); } #[test] @@ -164,9 +184,12 @@ fn test_mul_digits_overflow_2() { #[test] fn test_div_rem_small() { let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r); - assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0)); - assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15)); - assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3)); + assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), + (Big::from_small(17), 0)); + assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), + (Big::from_small(15), 15)); + assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), + (Big::from_small(0), 3)); assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)), (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8)); assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)), @@ -186,10 +209,14 @@ fn test_div_rem() { assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1))); assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0))); assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4))); - assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25))); - assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0))); - assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee))); - assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0))); + assert_eq!(div_rem(123456, 77), + (Big::from_u64(1603), Big::from_small(25))); + assert_eq!(div_rem(0xffff, 1), + (Big::from_u64(0xffff), Big::from_small(0))); + assert_eq!(div_rem(0xeeee, 0xffff), + (Big::from_small(0), Big::from_u64(0xeeee))); + assert_eq!(div_rem(2_000_000, 2), + (Big::from_u64(1_000_000), Big::from_u64(0))); } #[test] @@ -246,4 +273,3 @@ fn test_fmt() { assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45"); assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56"); } - diff --git a/src/libcoretest/num/dec2flt/parse.rs b/src/libcoretest/num/dec2flt/parse.rs index 09acf2bc517b0..e56a03ea5892c 100644 --- a/src/libcoretest/num/dec2flt/parse.rs +++ b/src/libcoretest/num/dec2flt/parse.rs @@ -30,7 +30,9 @@ fn invalid_chars() { let mut input = String::new(); input.push_str(s); input.insert(i, c); - assert!(parse_decimal(&input) == Invalid, "did not reject invalid {:?}", input); + assert!(parse_decimal(&input) == Invalid, + "did not reject invalid {:?}", + input); } } } @@ -38,14 +40,18 @@ fn invalid_chars() { #[test] fn valid() { - assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789))); - assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789))); - assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789))); + assert_eq!(parse_decimal("123.456e789"), + Valid(Decimal::new(b"123", b"456", 789))); + assert_eq!(parse_decimal("123.456e+789"), + Valid(Decimal::new(b"123", b"456", 789))); + assert_eq!(parse_decimal("123.456e-789"), + Valid(Decimal::new(b"123", b"456", -789))); assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0))); assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0))); assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300))); assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300))); - assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33))); + assert_eq!(parse_decimal("101e-33"), + Valid(Decimal::new(b"101", b"", -33))); let zeros: String = iter::repeat('0').take(25).collect(); let s = format!("1.5e{}", zeros); assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0))); diff --git a/src/libcoretest/num/dec2flt/rawfp.rs b/src/libcoretest/num/dec2flt/rawfp.rs index 4c0a403e574a3..33fd2c0f4b558 100644 --- a/src/libcoretest/num/dec2flt/rawfp.rs +++ b/src/libcoretest/num/dec2flt/rawfp.rs @@ -53,27 +53,40 @@ fn fp_to_float_half_to_even() { fn integers_to_f64() { assert_eq!(fp_to_float::(Fp { f: 1, e: 0 }), 1.0); assert_eq!(fp_to_float::(Fp { f: 42, e: 7 }), (42 << 7) as f64); - assert_eq!(fp_to_float::(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64); + assert_eq!(fp_to_float::(Fp { + f: 1 << 20, + e: 30, + }), + (1u64 << 50) as f64); assert_eq!(fp_to_float::(Fp { f: 4, e: -3 }), 0.5); } -const SOME_FLOATS: [f64; 9] = - [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997, - 9843579834.35892, 12456.0e-150, 54389573.0e-150]; +const SOME_FLOATS: [f64; 9] = [0.1f64, + 33.568, + 42.1e-5, + 777.0e9, + 1.1111, + 0.347997, + 9843579834.35892, + 12456.0e-150, + 54389573.0e-150]; #[test] fn human_f64_roundtrip() { for &x in &SOME_FLOATS { let (f, e, _) = x.integer_decode(); - let fp = Fp { f: f, e: e}; + let fp = Fp { f: f, e: e }; assert_eq!(fp_to_float::(fp), x); } } #[test] fn rounding_overflow() { - let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 }; + let x = Fp { + f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, + e: 42, + }; let rounded = round_normal::(x); let adjusted_k = x.e + 64 - 53; assert_eq!(rounded.sig, 1 << 52); diff --git a/src/libcoretest/num/flt2dec/estimator.rs b/src/libcoretest/num/flt2dec/estimator.rs index 21260c520f623..3bed4143cf35b 100644 --- a/src/libcoretest/num/flt2dec/estimator.rs +++ b/src/libcoretest/num/flt2dec/estimator.rs @@ -39,7 +39,8 @@ fn test_estimate_scaling_factor() { assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5); assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4); assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4); - assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3); + assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), + -3); assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0); assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0); assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1); @@ -58,4 +59,3 @@ fn test_estimate_scaling_factor() { assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16); } } - diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs index 1a592f3ad4249..9aad741707eed 100644 --- a/src/libcoretest/num/flt2dec/mod.rs +++ b/src/libcoretest/num/flt2dec/mod.rs @@ -16,8 +16,8 @@ use rand::distributions::{IndependentSample, Range}; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; use core::num::flt2dec::{MAX_SIG_DIGITS, round_up, Part, Formatted, Sign}; -use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str, - to_exact_exp_str, to_exact_fixed_str}; +use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str, to_exact_exp_str, + to_exact_fixed_str}; pub use test::Bencher; @@ -30,7 +30,7 @@ mod strategy { pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { FullDecoded::Finite(decoded) => decoded, - full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + full_decoded => panic!("expected finite, got {:?} instead", full_decoded), } } @@ -90,7 +90,9 @@ macro_rules! try_fixed { } fn check_exact(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16) - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ // use a large enough buffer let mut buf = [b'_'; 1024]; let mut expected_ = [b'_'; 1024]; @@ -105,14 +107,15 @@ fn check_exact(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16 if expected[i] >= b'5' { // check if this is a rounding-to-even case. // we avoid rounding ...x5000... (with infinite zeroes) to ...(x+1) when x is even. - if !(i+1 < expected.len() && expected[i-1] & 1 == 0 && - expected[i] == b'5' && - expected[i+1] == b' ') { + if !(i + 1 < expected.len() && expected[i - 1] & 1 == 0 && expected[i] == b'5' && + expected[i + 1] == b' ') { // if this returns true, expected_[..i] is all `9`s and being rounded up. // we should always return `100..00` (`i` digits) instead, since that's // what we can came up with `i` digits anyway. `round_up` assumes that // the adjustment to the length is done by caller, which we simply ignore. - if let Some(_) = round_up(&mut expected_, i) { expectedk_ += 1; } + if let Some(_) = round_up(&mut expected_, i) { + expectedk_ += 1; + } } } @@ -146,9 +149,11 @@ fn check_exact(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16 // check infinite zero digits if let Some(cut) = cut { - for i in cut..expected.len()-1 { + for i in cut..expected.len() - 1 { expected_[..cut].copy_from_slice(&expected[..cut]); - for c in &mut expected_[cut..i] { *c = b'0'; } + for c in &mut expected_[cut..i] { + *c = b'0'; + } try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk; "exact infzero mismatch for v={v}, i={i}: \ @@ -169,16 +174,21 @@ trait TestableFloat : DecodableFloat + fmt::Display { } impl TestableFloat for f32 { - fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } + fn ldexpi(f: i64, exp: isize) -> Self { + f as Self * (exp as Self).exp2() + } } impl TestableFloat for f64 { - fn ldexpi(f: i64, exp: isize) -> Self { f as Self * (exp as Self).exp2() } + fn ldexpi(f: i64, exp: isize) -> Self { + f as Self * (exp as Self).exp2() + } } fn check_exact_one(mut f: F, x: i64, e: isize, tstr: &str, expected: &[u8], expectedk: i16) - where T: TestableFloat, - F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where T: TestableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ // use a large enough buffer let mut buf = [b'_'; 1024]; let v: T = TestableFloat::ldexpi(x, e); @@ -212,7 +222,9 @@ macro_rules! check_exact_one { // [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion // ftp://ftp.ee.lbl.gov/testbase-report.ps.Z -pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn f32_shortest_sanity_test(mut f: F) + where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ // 0.0999999940395355224609375 // 0.100000001490116119384765625 // 0.10000000894069671630859375 @@ -257,7 +269,8 @@ pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) } pub fn f32_exact_sanity_test(mut f: F) - where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ let minf32 = f32::ldexp(1.0, -149); check_exact!(f(0.1f32) => b"100000001490116119384765625 ", 0); @@ -298,7 +311,9 @@ pub fn f32_exact_sanity_test(mut f: F) check_exact_one!(f(13248074, 95; f32) => b"524810279937", 36); } -pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn f64_shortest_sanity_test(mut f: F) + where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ // 0.0999999999999999777955395074968691915273... // 0.1000000000000000055511151231257827021181... // 0.1000000000000000333066907387546962127089... @@ -362,7 +377,8 @@ pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) } pub fn f64_exact_sanity_test(mut f: F) - where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ let minf64 = f64::ldexp(1.0, -1074); check_exact!(f(0.1f64) => b"1000000000000000055511151231257827021181", 0); @@ -446,7 +462,9 @@ pub fn f64_exact_sanity_test(mut f: F) check_exact_one!(f(8549497411294502, -448; f64) => b"1176257830728540379990", -118); } -pub fn more_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn more_shortest_sanity_test(mut f: F) + where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1, exp: 0, inclusive: true} => b"1", 18); check_shortest!(f{mant: 99_999_999_999_999_999, minus: 1, plus: 1, @@ -454,9 +472,10 @@ pub fn more_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8] } fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), - V: FnMut(usize) -> Decoded { + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), + V: FnMut(usize) -> Decoded +{ assert!(k <= 1024); let mut npassed = 0; // f(x) = Some(g(x)) @@ -465,7 +484,11 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V for i in 0..n { if (i & 0xfffff) == 0 { println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})", - i, n, nignored, npassed, i - nignored - npassed); + i, + n, + nignored, + npassed, + i - nignored - npassed); } let decoded = v(i); @@ -477,48 +500,63 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V npassed += 1; } else { println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", - i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1, - str::from_utf8(&buf2[..len2]).unwrap(), e2); + i, + n, + decoded, + str::from_utf8(&buf1[..len1]).unwrap(), + e1, + str::from_utf8(&buf2[..len2]).unwrap(), + e2); } } else { nignored += 1; } } println!("{}({}): done, ignored={} passed={} failed={}", - func, k, nignored, npassed, n - nignored - npassed); + func, + k, + nignored, + npassed, + n - nignored - npassed); assert!(nignored + npassed == n, "{}({}): {} out of {} values returns an incorrect value!", - func, k, n - nignored - npassed, n); + func, + k, + n - nignored - npassed, + n); (npassed, nignored) } pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); let f32_range = Range::new(0x0000_0001u32, 0x7f80_0000); iterate("f32_random_equivalence_test", k, n, f, g, |_| { let i: u32 = f32_range.ind_sample(&mut rng); - let x: f32 = unsafe {mem::transmute(i)}; + let x: f32 = unsafe { mem::transmute(i) }; decode_finite(x) }); } pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ let mut rng: XorShiftRng = Rand::rand(&mut rand::thread_rng()); let f64_range = Range::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); iterate("f64_random_equivalence_test", k, n, f, g, |_| { let i: u64 = f64_range.ind_sample(&mut rng); - let x: f64 = unsafe {mem::transmute(i)}; + let x: f64 = unsafe { mem::transmute(i) }; decode_finite(x) }); } pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values, // so why not simply testing all of them? // @@ -527,15 +565,20 @@ pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e. all finite ranges let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", - k, 0x7f7f_ffff, f, g, |i: usize| { - let x: f32 = unsafe {mem::transmute(i as u32 + 1)}; - decode_finite(x) - }); + k, + 0x7f7f_ffff, + f, + g, + |i: usize| { + let x: f32 = unsafe { mem::transmute(i as u32 + 1) }; + decode_finite(x) + }); assert_eq!((npassed, nignored), (2121451881, 17643158)); } fn to_string_with_parts(mut f: F) -> String - where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> { + where F: for<'a> FnMut(&'a mut [u8], &'a mut [Part<'a>]) -> Formatted<'a> +{ let mut buf = [0; 1024]; let mut parts = [Part::Zero(0); 16]; let formatted = f(&mut buf, &mut parts); @@ -545,81 +588,94 @@ fn to_string_with_parts(mut f: F) -> String } pub fn to_shortest_str_test(mut f_: F) - where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ use core::num::flt2dec::Sign::*; fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - to_string_with_parts(|buf, parts| to_shortest_str(|d,b| f(d,b), v, sign, - frac_digits, upper, buf, parts)) + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) + { + to_string_with_parts(|buf, parts| { + to_shortest_str(|d, b| f(d, b), v, sign, frac_digits, upper, buf, parts) + }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); + assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); + assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); - - assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 0, true), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 0, false), "+inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 0, true), "+inf"); - assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN"); - assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, 0, false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3.14"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3.14"); - assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3.14"); + assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); + assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); + assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); + + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0, false), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 0, true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 0, false), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 0, true), "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1, true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64, true), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1, true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, 0, false), "3.14"); + assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3.14"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3.14"); + assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3.14"); assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14"); - assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); - assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); - - assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0.000000000075"); - assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000000000075"); + assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.14"); + assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); + + assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0.000000000075"); + assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000000000075"); assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075"); assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750"); - assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000"); - assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0"); - assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000"); + assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), + "199710000000000000000"); + assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), + "199710000000000000000.0"); + assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), + "199710000000000000000.00000000"); - assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", "")); - assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", "")); - assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", "")); + assert_eq!(to_string(f, f32::MAX, Minus, 0, false), + format!("34028235{:0>31}", "")); + assert_eq!(to_string(f, f32::MAX, Minus, 1, false), + format!("34028235{:0>31}.0", "")); + assert_eq!(to_string(f, f32::MAX, Minus, 8, false), + format!("34028235{:0>31}.00000000", "")); let minf32 = f32::ldexp(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, 0, false), format!("0.{:0>44}1", "")); - assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", "")); - assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", "")); + assert_eq!(to_string(f, minf32, Minus, 0, false), + format!("0.{:0>44}1", "")); + assert_eq!(to_string(f, minf32, Minus, 45, false), + format!("0.{:0>44}1", "")); + assert_eq!(to_string(f, minf32, Minus, 46, false), + format!("0.{:0>44}10", "")); assert_eq!(to_string(f, f64::MAX, Minus, 0, false), format!("17976931348623157{:0>292}", "")); @@ -629,113 +685,130 @@ pub fn to_shortest_str_test(mut f_: F) format!("17976931348623157{:0>292}.00000000", "")); let minf64 = f64::ldexp(1.0, -1074); - assert_eq!(to_string(f, minf64, Minus, 0, false), format!("0.{:0>323}5", "")); - assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", "")); - assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", "")); + assert_eq!(to_string(f, minf64, Minus, 0, false), + format!("0.{:0>323}5", "")); + assert_eq!(to_string(f, minf64, Minus, 324, false), + format!("0.{:0>323}5", "")); + assert_eq!(to_string(f, minf64, Minus, 325, false), + format!("0.{:0>323}50", "")); // very large output - assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", "")); + assert_eq!(to_string(f, 1.1, Minus, 80000, false), + format!("1.1{:0>79999}", "")); } pub fn to_shortest_exp_str_test(mut f_: F) - where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ use core::num::flt2dec::Sign::*; fn to_string(f: &mut F, v: T, sign: Sign, exp_bounds: (i16, i16), upper: bool) -> String - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { - to_string_with_parts(|buf, parts| to_shortest_exp_str(|d,b| f(d,b), v, sign, - exp_bounds, upper, buf, parts)) + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) + { + to_string_with_parts(|buf, parts| { + to_shortest_exp_str(|d, b| f(d, b), v, sign, exp_bounds, upper, buf, parts) + }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0"); - assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0"); + assert_eq!(to_string(f, 0.0, Minus, (-4, 16), false), "0"); + assert_eq!(to_string(f, 0.0, MinusRaw, (-4, 16), false), "0"); + assert_eq!(to_string(f, 0.0, MinusPlus, (-4, 16), false), "+0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, (-4, 16), false), "+0"); + assert_eq!(to_string(f, -0.0, Minus, (-4, 16), false), "0"); + assert_eq!(to_string(f, -0.0, MinusRaw, (-4, 16), false), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, (-4, 16), false), "+0"); assert_eq!(to_string(f, -0.0, MinusPlusRaw, (-4, 16), false), "-0"); - assert_eq!(to_string(f, 0.0, Minus, ( 0, 0), true), "0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, ( 0, 0), false), "0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, ( 5, 9), false), "+0e0"); - assert_eq!(to_string(f, -0.0, Minus, ( 0, 0), true), "0E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, ( 0, 0), false), "-0e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, ( 5, 9), false), "-0e0"); - - assert_eq!(to_string(f, 1.0/0.0, Minus, (-4, 16), false), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusRaw, (-4, 16), true), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlus, (-4, 16), false), "+inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, (-4, 16), true), "+inf"); - assert_eq!(to_string(f, 0.0/0.0, Minus, ( 0, 0), false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusRaw, ( 0, 0), true), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlus, (-9, -5), false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, ( 5, 9), true), "NaN"); - assert_eq!(to_string(f, -1.0/0.0, Minus, ( 0, 0), false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusRaw, ( 0, 0), true), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlus, (-9, -5), false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, ( 5, 9), true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14"); - assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14"); + assert_eq!(to_string(f, 0.0, Minus, (0, 0), true), "0E0"); + assert_eq!(to_string(f, 0.0, MinusRaw, (0, 0), false), "0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, (-9, -5), true), "+0E0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, (5, 9), false), "+0e0"); + assert_eq!(to_string(f, -0.0, Minus, (0, 0), true), "0E0"); + assert_eq!(to_string(f, -0.0, MinusRaw, (0, 0), false), "-0e0"); + assert_eq!(to_string(f, -0.0, MinusPlus, (-9, -5), true), "+0E0"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, (5, 9), false), "-0e0"); + + assert_eq!(to_string(f, 1.0 / 0.0, Minus, (-4, 16), false), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, (-4, 16), true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, (-4, 16), false), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, (-4, 16), true), + "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, (0, 0), false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, (0, 0), true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, (-9, -5), false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, (5, 9), true), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, (0, 0), false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, (0, 0), true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, (-9, -5), false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, (5, 9), true), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, (-4, 16), false), "3.14"); + assert_eq!(to_string(f, 3.14, MinusRaw, (-4, 16), false), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, (-4, 16), false), "+3.14"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, (-4, 16), false), "+3.14"); + assert_eq!(to_string(f, -3.14, Minus, (-4, 16), false), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusRaw, (-4, 16), false), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusPlus, (-4, 16), false), "-3.14"); assert_eq!(to_string(f, -3.14, MinusPlusRaw, (-4, 16), false), "-3.14"); - assert_eq!(to_string(f, 3.14, Minus, ( 0, 0), true), "3.14E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, ( 0, 0), false), "3.14e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, ( 5, 9), false), "+3.14e0"); - assert_eq!(to_string(f, -3.14, Minus, ( 0, 0), true), "-3.14E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, ( 0, 0), false), "-3.14e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, ( 5, 9), false), "-3.14e0"); - - assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1"); - assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1"); - assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1"); - assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1"); - assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1"); - assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1"); - assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1"); + assert_eq!(to_string(f, 3.14, Minus, (0, 0), true), "3.14E0"); + assert_eq!(to_string(f, 3.14, MinusRaw, (0, 0), false), "3.14e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, (-9, -5), true), "+3.14E0"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, (5, 9), false), "+3.14e0"); + assert_eq!(to_string(f, -3.14, Minus, (0, 0), true), "-3.14E0"); + assert_eq!(to_string(f, -3.14, MinusRaw, (0, 0), false), "-3.14e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, (-9, -5), true), "-3.14E0"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, (5, 9), false), "-3.14e0"); + + assert_eq!(to_string(f, 0.1, Minus, (-4, 16), false), "0.1"); + assert_eq!(to_string(f, 0.1, MinusRaw, (-4, 16), false), "0.1"); + assert_eq!(to_string(f, 0.1, MinusPlus, (-4, 16), false), "+0.1"); + assert_eq!(to_string(f, 0.1, MinusPlusRaw, (-4, 16), false), "+0.1"); + assert_eq!(to_string(f, -0.1, Minus, (-4, 16), false), "-0.1"); + assert_eq!(to_string(f, -0.1, MinusRaw, (-4, 16), false), "-0.1"); + assert_eq!(to_string(f, -0.1, MinusPlus, (-4, 16), false), "-0.1"); assert_eq!(to_string(f, -0.1, MinusPlusRaw, (-4, 16), false), "-0.1"); - assert_eq!(to_string(f, 0.1, Minus, ( 0, 0), true), "1E-1"); - assert_eq!(to_string(f, 0.1, MinusRaw, ( 0, 0), false), "1e-1"); - assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1"); - assert_eq!(to_string(f, 0.1, MinusPlusRaw, ( 5, 9), false), "+1e-1"); - assert_eq!(to_string(f, -0.1, Minus, ( 0, 0), true), "-1E-1"); - assert_eq!(to_string(f, -0.1, MinusRaw, ( 0, 0), false), "-1e-1"); - assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1"); - assert_eq!(to_string(f, -0.1, MinusPlusRaw, ( 5, 9), false), "-1e-1"); - - assert_eq!(to_string(f, 7.5e-11, Minus, ( -4, 16), false), "7.5e-11"); - assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), "0.000000000075"); + assert_eq!(to_string(f, 0.1, Minus, (0, 0), true), "1E-1"); + assert_eq!(to_string(f, 0.1, MinusRaw, (0, 0), false), "1e-1"); + assert_eq!(to_string(f, 0.1, MinusPlus, (-9, -5), true), "+1E-1"); + assert_eq!(to_string(f, 0.1, MinusPlusRaw, (5, 9), false), "+1e-1"); + assert_eq!(to_string(f, -0.1, Minus, (0, 0), true), "-1E-1"); + assert_eq!(to_string(f, -0.1, MinusRaw, (0, 0), false), "-1e-1"); + assert_eq!(to_string(f, -0.1, MinusPlus, (-9, -5), true), "-1E-1"); + assert_eq!(to_string(f, -0.1, MinusPlusRaw, (5, 9), false), "-1e-1"); + + assert_eq!(to_string(f, 7.5e-11, Minus, (-4, 16), false), "7.5e-11"); + assert_eq!(to_string(f, 7.5e-11, Minus, (-11, 10), false), + "0.000000000075"); assert_eq!(to_string(f, 7.5e-11, Minus, (-10, 11), false), "7.5e-11"); - assert_eq!(to_string(f, 1.9971e20, Minus, ( -4, 16), false), "1.9971e20"); - assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), "199710000000000000000"); - assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), "1.9971e20"); + assert_eq!(to_string(f, 1.9971e20, Minus, (-4, 16), false), "1.9971e20"); + assert_eq!(to_string(f, 1.9971e20, Minus, (-20, 21), false), + "199710000000000000000"); + assert_eq!(to_string(f, 1.9971e20, Minus, (-21, 20), false), + "1.9971e20"); // the true value of 1.0e23f64 is less than 10^23, but that shouldn't matter here assert_eq!(to_string(f, 1.0e23, Minus, (22, 23), false), "1e23"); - assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000"); + assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), + "100000000000000000000000"); assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23"); - assert_eq!(to_string(f, f32::MAX, Minus, ( -4, 16), false), "3.4028235e38"); - assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38"); - assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", "")); + assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), + "3.4028235e38"); + assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), + "3.4028235e38"); + assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), + format!("34028235{:0>31}", "")); let minf32 = f32::ldexp(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, ( -4, 16), false), "1e-45"); + assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45"); assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45"); - assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", "")); + assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), + format!("0.{:0>44}1", "")); - assert_eq!(to_string(f, f64::MAX, Minus, ( -4, 16), false), + assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308"); assert_eq!(to_string(f, f64::MAX, Minus, (-308, 309), false), format!("17976931348623157{:0>292}", "")); @@ -743,119 +816,145 @@ pub fn to_shortest_exp_str_test(mut f_: F) "1.7976931348623157e308"); let minf64 = f64::ldexp(1.0, -1074); - assert_eq!(to_string(f, minf64, Minus, ( -4, 16), false), "5e-324"); - assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", "")); + assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324"); + assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), + format!("0.{:0>323}5", "")); assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324"); assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1"); } pub fn to_exact_exp_str_test(mut f_: F) - where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ use core::num::flt2dec::Sign::*; fn to_string(f: &mut F, v: T, sign: Sign, ndigits: usize, upper: bool) -> String - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { - to_string_with_parts(|buf, parts| to_exact_exp_str(|d,b,l| f(d,b,l), v, sign, - ndigits, upper, buf, parts)) + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) + { + to_string_with_parts(|buf, parts| { + to_exact_exp_str(|d, b, l| f(d, b, l), v, sign, ndigits, upper, buf, parts) + }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0"); - assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0"); + assert_eq!(to_string(f, 0.0, Minus, 1, true), "0E0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 1, false), "0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0E0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, false), "+0e0"); + assert_eq!(to_string(f, -0.0, Minus, 1, true), "0E0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 1, false), "-0e0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 1, true), "+0E0"); assert_eq!(to_string(f, -0.0, MinusPlusRaw, 1, false), "-0e0"); - assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0"); + assert_eq!(to_string(f, 0.0, Minus, 2, true), "0.0E0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 2, false), "0.0e0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 2, true), "+0.0E0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 2, false), "+0.0e0"); + assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.0000000E0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 8, false), "-0.0000000e0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.0000000E0"); assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, false), "-0.0000000e0"); - assert_eq!(to_string(f, 1.0/0.0, Minus, 1, false), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 1, false), "+inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 1, true), "+inf"); - assert_eq!(to_string(f, 0.0/0.0, Minus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 8, true), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 8, true), "NaN"); - assert_eq!(to_string(f, -1.0/0.0, Minus, 64, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 64, true), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 64, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0"); - assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0"); + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 1, false), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1, true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 1, false), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 1, true), "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 8, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 8, true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 8, true), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 64, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 64, true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 64, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, 1, true), "3E0"); + assert_eq!(to_string(f, 3.14, MinusRaw, 1, false), "3e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, 1, true), "+3E0"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 1, false), "+3e0"); + assert_eq!(to_string(f, -3.14, Minus, 2, true), "-3.1E0"); + assert_eq!(to_string(f, -3.14, MinusRaw, 2, false), "-3.1e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, 2, true), "-3.1E0"); assert_eq!(to_string(f, -3.14, MinusPlusRaw, 2, false), "-3.1e0"); - assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0"); - assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0"); - assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0"); - assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0"); - assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0"); + assert_eq!(to_string(f, 3.14, Minus, 3, true), "3.14E0"); + assert_eq!(to_string(f, 3.14, MinusRaw, 3, false), "3.14e0"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.14E0"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 3, false), "+3.14e0"); + assert_eq!(to_string(f, -3.14, Minus, 4, true), "-3.140E0"); + assert_eq!(to_string(f, -3.14, MinusRaw, 4, false), "-3.140e0"); + assert_eq!(to_string(f, -3.14, MinusPlus, 4, true), "-3.140E0"); assert_eq!(to_string(f, -3.14, MinusPlusRaw, 4, false), "-3.140e0"); - assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1"); - assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1"); - assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1"); - assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1"); - assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1"); - assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1"); - assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1"); - assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1"); - assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1"); - assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1"); - assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1"); - assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1"); - - assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1"); - assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0"); - assert_eq!(to_string(f, 9.5, Minus, 3, false), "9.50e0"); - assert_eq!(to_string(f, 9.5, Minus, 30, false), "9.50000000000000000000000000000e0"); - - assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "1e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 2, false), "1.0e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 15, false), "1.00000000000000e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 16, false), "1.000000000000000e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 17, false), "1.0000000000000001e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 18, false), "1.00000000000000009e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 19, false), "1.000000000000000091e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 20, false), "1.0000000000000000906e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 21, false), "1.00000000000000009060e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 22, false), "1.000000000000000090597e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 23, false), "1.0000000000000000905970e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 24, false), "1.00000000000000009059697e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 25, false), "1.000000000000000090596966e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 26, false), "1.0000000000000000905969664e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 27, false), "1.00000000000000009059696640e25"); - assert_eq!(to_string(f, 1.0e25, Minus, 30, false), "1.00000000000000009059696640000e25"); - - assert_eq!(to_string(f, 1.0e-6, Minus, 1, false), "1e-6"); - assert_eq!(to_string(f, 1.0e-6, Minus, 2, false), "1.0e-6"); - assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), "1.000000000000000e-6"); - assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), "9.9999999999999995e-7"); - assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), "9.99999999999999955e-7"); - assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), "9.999999999999999547e-7"); - assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), "9.9999999999999995475e-7"); - assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), "9.99999999999999954748111825886e-7"); + assert_eq!(to_string(f, 0.195, Minus, 1, false), "2e-1"); + assert_eq!(to_string(f, 0.195, MinusRaw, 1, true), "2E-1"); + assert_eq!(to_string(f, 0.195, MinusPlus, 1, false), "+2e-1"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 1, true), "+2E-1"); + assert_eq!(to_string(f, -0.195, Minus, 2, false), "-2.0e-1"); + assert_eq!(to_string(f, -0.195, MinusRaw, 2, true), "-2.0E-1"); + assert_eq!(to_string(f, -0.195, MinusPlus, 2, false), "-2.0e-1"); + assert_eq!(to_string(f, -0.195, MinusPlusRaw, 2, true), "-2.0E-1"); + assert_eq!(to_string(f, 0.195, Minus, 3, false), "1.95e-1"); + assert_eq!(to_string(f, 0.195, MinusRaw, 3, true), "1.95E-1"); + assert_eq!(to_string(f, 0.195, MinusPlus, 3, false), "+1.95e-1"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 3, true), "+1.95E-1"); + assert_eq!(to_string(f, -0.195, Minus, 4, false), "-1.950e-1"); + assert_eq!(to_string(f, -0.195, MinusRaw, 4, true), "-1.950E-1"); + assert_eq!(to_string(f, -0.195, MinusPlus, 4, false), "-1.950e-1"); + assert_eq!(to_string(f, -0.195, MinusPlusRaw, 4, true), "-1.950E-1"); + + assert_eq!(to_string(f, 9.5, Minus, 1, false), "1e1"); + assert_eq!(to_string(f, 9.5, Minus, 2, false), "9.5e0"); + assert_eq!(to_string(f, 9.5, Minus, 3, false), "9.50e0"); + assert_eq!(to_string(f, 9.5, Minus, 30, false), + "9.50000000000000000000000000000e0"); + + assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "1e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 2, false), "1.0e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 15, false), + "1.00000000000000e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 16, false), + "1.000000000000000e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 17, false), + "1.0000000000000001e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 18, false), + "1.00000000000000009e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 19, false), + "1.000000000000000091e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 20, false), + "1.0000000000000000906e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 21, false), + "1.00000000000000009060e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 22, false), + "1.000000000000000090597e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 23, false), + "1.0000000000000000905970e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 24, false), + "1.00000000000000009059697e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 25, false), + "1.000000000000000090596966e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 26, false), + "1.0000000000000000905969664e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 27, false), + "1.00000000000000009059696640e25"); + assert_eq!(to_string(f, 1.0e25, Minus, 30, false), + "1.00000000000000009059696640000e25"); + + assert_eq!(to_string(f, 1.0e-6, Minus, 1, false), "1e-6"); + assert_eq!(to_string(f, 1.0e-6, Minus, 2, false), "1.0e-6"); + assert_eq!(to_string(f, 1.0e-6, Minus, 16, false), + "1.000000000000000e-6"); + assert_eq!(to_string(f, 1.0e-6, Minus, 17, false), + "9.9999999999999995e-7"); + assert_eq!(to_string(f, 1.0e-6, Minus, 18, false), + "9.99999999999999955e-7"); + assert_eq!(to_string(f, 1.0e-6, Minus, 19, false), + "9.999999999999999547e-7"); + assert_eq!(to_string(f, 1.0e-6, Minus, 20, false), + "9.9999999999999995475e-7"); + assert_eq!(to_string(f, 1.0e-6, Minus, 30, false), + "9.99999999999999954748111825886e-7"); assert_eq!(to_string(f, 1.0e-6, Minus, 40, false), "9.999999999999999547481118258862586856139e-7"); assert_eq!(to_string(f, 1.0e-6, Minus, 50, false), @@ -865,35 +964,41 @@ pub fn to_exact_exp_str_test(mut f_: F) assert_eq!(to_string(f, 1.0e-6, Minus, 70, false), "9.999999999999999547481118258862586856139387236908078193664550781250000e-7"); - assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38"); - assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38"); - assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38"); - assert_eq!(to_string(f, f32::MAX, Minus, 8, false), "3.4028235e38"); - assert_eq!(to_string(f, f32::MAX, Minus, 16, false), "3.402823466385289e38"); - assert_eq!(to_string(f, f32::MAX, Minus, 32, false), "3.4028234663852885981170418348452e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 8, false), "3.4028235e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 16, false), + "3.402823466385289e38"); + assert_eq!(to_string(f, f32::MAX, Minus, 32, false), + "3.4028234663852885981170418348452e38"); assert_eq!(to_string(f, f32::MAX, Minus, 64, false), "3.402823466385288598117041834845169254400000000000000000000000000e38"); let minf32 = f32::ldexp(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45"); - assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45"); - assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45"); - assert_eq!(to_string(f, minf32, Minus, 8, false), "1.4012985e-45"); - assert_eq!(to_string(f, minf32, Minus, 16, false), "1.401298464324817e-45"); - assert_eq!(to_string(f, minf32, Minus, 32, false), "1.4012984643248170709237295832899e-45"); - assert_eq!(to_string(f, minf32, Minus, 64, false), + assert_eq!(to_string(f, minf32, Minus, 1, false), "1e-45"); + assert_eq!(to_string(f, minf32, Minus, 2, false), "1.4e-45"); + assert_eq!(to_string(f, minf32, Minus, 4, false), "1.401e-45"); + assert_eq!(to_string(f, minf32, Minus, 8, false), "1.4012985e-45"); + assert_eq!(to_string(f, minf32, Minus, 16, false), + "1.401298464324817e-45"); + assert_eq!(to_string(f, minf32, Minus, 32, false), + "1.4012984643248170709237295832899e-45"); + assert_eq!(to_string(f, minf32, Minus, 64, false), "1.401298464324817070923729583289916131280261941876515771757068284e-45"); assert_eq!(to_string(f, minf32, Minus, 128, false), "1.401298464324817070923729583289916131280261941876515771757068283\ 8897910826858606014866381883621215820312500000000000000000000000e-45"); - assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 8, false), "1.7976931e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 16, false), "1.797693134862316e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 32, false), "1.7976931348623157081452742373170e308"); - assert_eq!(to_string(f, f64::MAX, Minus, 64, false), + assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 8, false), "1.7976931e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 16, false), + "1.797693134862316e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 32, false), + "1.7976931348623157081452742373170e308"); + assert_eq!(to_string(f, f64::MAX, Minus, 64, false), "1.797693134862315708145274237317043567980705675258449965989174768e308"); assert_eq!(to_string(f, f64::MAX, Minus, 128, false), "1.797693134862315708145274237317043567980705675258449965989174768\ @@ -915,23 +1020,25 @@ pub fn to_exact_exp_str_test(mut f_: F) // okay, this is becoming tough. fortunately for us, this is almost the worst case. let minf64 = f64::ldexp(1.0, -1074); - assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324"); - assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324"); - assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324"); - assert_eq!(to_string(f, minf64, Minus, 8, false), "4.9406565e-324"); - assert_eq!(to_string(f, minf64, Minus, 16, false), "4.940656458412465e-324"); - assert_eq!(to_string(f, minf64, Minus, 32, false), "4.9406564584124654417656879286822e-324"); - assert_eq!(to_string(f, minf64, Minus, 64, false), + assert_eq!(to_string(f, minf64, Minus, 1, false), "5e-324"); + assert_eq!(to_string(f, minf64, Minus, 2, false), "4.9e-324"); + assert_eq!(to_string(f, minf64, Minus, 4, false), "4.941e-324"); + assert_eq!(to_string(f, minf64, Minus, 8, false), "4.9406565e-324"); + assert_eq!(to_string(f, minf64, Minus, 16, false), + "4.940656458412465e-324"); + assert_eq!(to_string(f, minf64, Minus, 32, false), + "4.9406564584124654417656879286822e-324"); + assert_eq!(to_string(f, minf64, Minus, 64, false), "4.940656458412465441765687928682213723650598026143247644255856825e-324"); - assert_eq!(to_string(f, minf64, Minus, 128, false), + assert_eq!(to_string(f, minf64, Minus, 128, false), "4.940656458412465441765687928682213723650598026143247644255856825\ 0067550727020875186529983636163599237979656469544571773092665671e-324"); - assert_eq!(to_string(f, minf64, Minus, 256, false), + assert_eq!(to_string(f, minf64, Minus, 256, false), "4.940656458412465441765687928682213723650598026143247644255856825\ 0067550727020875186529983636163599237979656469544571773092665671\ 0355939796398774796010781878126300713190311404527845817167848982\ 1036887186360569987307230500063874091535649843873124733972731696e-324"); - assert_eq!(to_string(f, minf64, Minus, 512, false), + assert_eq!(to_string(f, minf64, Minus, 512, false), "4.940656458412465441765687928682213723650598026143247644255856825\ 0067550727020875186529983636163599237979656469544571773092665671\ 0355939796398774796010781878126300713190311404527845817167848982\ @@ -959,151 +1066,180 @@ pub fn to_exact_exp_str_test(mut f_: F) 0000000000000000000000000000000000000000000000000000000000000000e-324"); // very large output - assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", "")); - assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", "")); - assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", "")); - assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false), + assert_eq!(to_string(f, 0.0, Minus, 80000, false), + format!("0.{:0>79999}e0", "")); + assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), + format!("1.{:0>79999}e1", "")); + assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), + format!("1.{:0>79999}e0", "")); + assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false), format!("1.000000000000000055511151231257827021181583404541015625{:0>79945}\ - e-1", "")); + e-1", + "")); assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false), format!("9.999999999999999451532714542095716517295037027873924471077157760\ - 66783064379706047475337982177734375{:0>79901}e-21", "")); + 66783064379706047475337982177734375{:0>79901}e-21", + "")); } pub fn to_exact_fixed_str_test(mut f_: F) - where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { + where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ use core::num::flt2dec::Sign::*; fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { - to_string_with_parts(|buf, parts| to_exact_fixed_str(|d,b,l| f(d,b,l), v, sign, - frac_digits, upper, buf, parts)) + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) + { + to_string_with_parts(|buf, parts| { + to_exact_fixed_str(|d, b, l| f(d, b, l), + v, + sign, + frac_digits, + upper, + buf, + parts) + }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); + assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); + assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); - - assert_eq!(to_string(f, 1.0/0.0, Minus, 0, false), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusRaw, 1, true), "inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlus, 8, false), "+inf"); - assert_eq!(to_string(f, 1.0/0.0, MinusPlusRaw, 64, true), "+inf"); - assert_eq!(to_string(f, 0.0/0.0, Minus, 0, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusRaw, 1, true), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0/0.0, MinusPlusRaw, 64, true), "NaN"); - assert_eq!(to_string(f, -1.0/0.0, Minus, 0, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusRaw, 1, true), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlus, 8, false), "-inf"); - assert_eq!(to_string(f, -1.0/0.0, MinusPlusRaw, 64, true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, 0, false), "3"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3"); - assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3"); - assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3"); - assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3"); + assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); + assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); + assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); + + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0, false), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1, true), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 8, false), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 64, true), "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1, true), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64, true), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1, true), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8, false), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, 0, false), "3"); + assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3"); + assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3"); + assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3"); + assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3"); + assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3"); assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3"); - assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.1"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); - assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); - - assert_eq!(to_string(f, 0.195, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.195, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.195, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.195, Minus, 0, false), "-0"); - assert_eq!(to_string(f, -0.195, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.195, MinusPlus, 0, false), "-0"); + assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.1"); + assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); + + assert_eq!(to_string(f, 0.195, Minus, 0, false), "0"); + assert_eq!(to_string(f, 0.195, MinusRaw, 0, false), "0"); + assert_eq!(to_string(f, 0.195, MinusPlus, 0, false), "+0"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0, false), "+0"); + assert_eq!(to_string(f, -0.195, Minus, 0, false), "-0"); + assert_eq!(to_string(f, -0.195, MinusRaw, 0, false), "-0"); + assert_eq!(to_string(f, -0.195, MinusPlus, 0, false), "-0"); assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.195, Minus, 1, true), "0.2"); - assert_eq!(to_string(f, 0.195, MinusRaw, 2, true), "0.20"); - assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+0.195"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4, true), "+0.1950"); - assert_eq!(to_string(f, -0.195, Minus, 5, true), "-0.19500"); - assert_eq!(to_string(f, -0.195, MinusRaw, 6, true), "-0.195000"); - assert_eq!(to_string(f, -0.195, MinusPlus, 7, true), "-0.1950000"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8, true), "-0.19500000"); - - assert_eq!(to_string(f, 999.5, Minus, 0, false), "1000"); - assert_eq!(to_string(f, 999.5, Minus, 1, false), "999.5"); - assert_eq!(to_string(f, 999.5, Minus, 2, false), "999.50"); - assert_eq!(to_string(f, 999.5, Minus, 3, false), "999.500"); - assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000"); + assert_eq!(to_string(f, 0.195, Minus, 1, true), "0.2"); + assert_eq!(to_string(f, 0.195, MinusRaw, 2, true), "0.20"); + assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+0.195"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4, true), "+0.1950"); + assert_eq!(to_string(f, -0.195, Minus, 5, true), "-0.19500"); + assert_eq!(to_string(f, -0.195, MinusRaw, 6, true), "-0.195000"); + assert_eq!(to_string(f, -0.195, MinusPlus, 7, true), "-0.1950000"); + assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8, true), "-0.19500000"); + + assert_eq!(to_string(f, 999.5, Minus, 0, false), "1000"); + assert_eq!(to_string(f, 999.5, Minus, 1, false), "999.5"); + assert_eq!(to_string(f, 999.5, Minus, 2, false), "999.50"); + assert_eq!(to_string(f, 999.5, Minus, 3, false), "999.500"); + assert_eq!(to_string(f, 999.5, Minus, 30, false), + "999.500000000000000000000000000000"); assert_eq!(to_string(f, 0.5, Minus, 0, false), "1"); assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5"); assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50"); assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500"); - assert_eq!(to_string(f, 0.95, Minus, 0, false), "1"); - assert_eq!(to_string(f, 0.95, Minus, 1, false), "0.9"); // because it really is less than 0.95 - assert_eq!(to_string(f, 0.95, Minus, 2, false), "0.95"); - assert_eq!(to_string(f, 0.95, Minus, 3, false), "0.950"); + assert_eq!(to_string(f, 0.95, Minus, 0, false), "1"); + assert_eq!(to_string(f, 0.95, Minus, 1, false), "0.9"); // because it really is less than 0.95 + assert_eq!(to_string(f, 0.95, Minus, 2, false), "0.95"); + assert_eq!(to_string(f, 0.95, Minus, 3, false), "0.950"); assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000"); - assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994"); - - assert_eq!(to_string(f, 0.095, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.095, Minus, 1, false), "0.1"); - assert_eq!(to_string(f, 0.095, Minus, 2, false), "0.10"); - assert_eq!(to_string(f, 0.095, Minus, 3, false), "0.095"); - assert_eq!(to_string(f, 0.095, Minus, 4, false), "0.0950"); + assert_eq!(to_string(f, 0.95, Minus, 30, false), + "0.949999999999999955591079014994"); + + assert_eq!(to_string(f, 0.095, Minus, 0, false), "0"); + assert_eq!(to_string(f, 0.095, Minus, 1, false), "0.1"); + assert_eq!(to_string(f, 0.095, Minus, 2, false), "0.10"); + assert_eq!(to_string(f, 0.095, Minus, 3, false), "0.095"); + assert_eq!(to_string(f, 0.095, Minus, 4, false), "0.0950"); assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000"); - assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625"); - - assert_eq!(to_string(f, 0.0095, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0095, Minus, 1, false), "0.0"); - assert_eq!(to_string(f, 0.0095, Minus, 2, false), "0.01"); - assert_eq!(to_string(f, 0.0095, Minus, 3, false), "0.009"); // really is less than 0.0095 - assert_eq!(to_string(f, 0.0095, Minus, 4, false), "0.0095"); - assert_eq!(to_string(f, 0.0095, Minus, 5, false), "0.00950"); + assert_eq!(to_string(f, 0.095, Minus, 30, false), + "0.095000000000000001110223024625"); + + assert_eq!(to_string(f, 0.0095, Minus, 0, false), "0"); + assert_eq!(to_string(f, 0.0095, Minus, 1, false), "0.0"); + assert_eq!(to_string(f, 0.0095, Minus, 2, false), "0.01"); + assert_eq!(to_string(f, 0.0095, Minus, 3, false), "0.009"); // really is less than 0.0095 + assert_eq!(to_string(f, 0.0095, Minus, 4, false), "0.0095"); + assert_eq!(to_string(f, 0.0095, Minus, 5, false), "0.00950"); assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000"); - assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267"); + assert_eq!(to_string(f, 0.0095, Minus, 30, false), + "0.009499999999999999764077607267"); - assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0"); - assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000"); + assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0"); + assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000"); assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001"); assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075"); assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750"); - assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000"); - assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501"); - - assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664"); - assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0"); - assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000"); - - assert_eq!(to_string(f, 1.0e-6, Minus, 0, false), "0"); - assert_eq!(to_string(f, 1.0e-6, Minus, 3, false), "0.000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 6, false), "0.000001"); - assert_eq!(to_string(f, 1.0e-6, Minus, 9, false), "0.000001000"); + assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), + "0.00000000007500000000"); + assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), + "0.000000000074999999999999999501"); + + assert_eq!(to_string(f, 1.0e25, Minus, 0, false), + "10000000000000000905969664"); + assert_eq!(to_string(f, 1.0e25, Minus, 1, false), + "10000000000000000905969664.0"); + assert_eq!(to_string(f, 1.0e25, Minus, 3, false), + "10000000000000000905969664.000"); + + assert_eq!(to_string(f, 1.0e-6, Minus, 0, false), "0"); + assert_eq!(to_string(f, 1.0e-6, Minus, 3, false), "0.000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 6, false), "0.000001"); + assert_eq!(to_string(f, 1.0e-6, Minus, 9, false), "0.000001000"); assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995"); - assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955"); - assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547"); - assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589"); + assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), + "0.0000010000000000000000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), + "0.00000099999999999999995"); + assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), + "0.000000999999999999999955"); + assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), + "0.0000009999999999999999547"); + assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), + "0.00000099999999999999995474811182589"); assert_eq!(to_string(f, 1.0e-6, Minus, 45, false), "0.000000999999999999999954748111825886258685614"); assert_eq!(to_string(f, 1.0e-6, Minus, 55, false), @@ -1121,14 +1257,15 @@ pub fn to_exact_fixed_str_test(mut f_: F) "340282346638528859811704183484516925440.00"); let minf32 = f32::ldexp(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, 0, false), "0"); - assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0"); - assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00"); - assert_eq!(to_string(f, minf32, Minus, 4, false), "0.0000"); - assert_eq!(to_string(f, minf32, Minus, 8, false), "0.00000000"); - assert_eq!(to_string(f, minf32, Minus, 16, false), "0.0000000000000000"); - assert_eq!(to_string(f, minf32, Minus, 32, false), "0.00000000000000000000000000000000"); - assert_eq!(to_string(f, minf32, Minus, 64, false), + assert_eq!(to_string(f, minf32, Minus, 0, false), "0"); + assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0"); + assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00"); + assert_eq!(to_string(f, minf32, Minus, 4, false), "0.0000"); + assert_eq!(to_string(f, minf32, Minus, 8, false), "0.00000000"); + assert_eq!(to_string(f, minf32, Minus, 16, false), "0.0000000000000000"); + assert_eq!(to_string(f, minf32, Minus, 32, false), + "0.00000000000000000000000000000000"); + assert_eq!(to_string(f, minf32, Minus, 64, false), "0.0000000000000000000000000000000000000000000014012984643248170709"); assert_eq!(to_string(f, minf32, Minus, 128, false), "0.0000000000000000000000000000000000000000000014012984643248170709\ @@ -1178,13 +1315,17 @@ pub fn to_exact_fixed_str_test(mut f_: F) 1014510378627381672509558373897335989937"); // very large output - assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("10.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false), - format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "")); + assert_eq!(to_string(f, 0.0, Minus, 80000, false), + format!("0.{:0>80000}", "")); + assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), + format!("10.{:0>80000}", "")); + assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), + format!("1.{:0>80000}", "")); + assert_eq!(to_string(f, 1.0e-1, Minus, 80000, false), + format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", + "")); assert_eq!(to_string(f, 1.0e-20, Minus, 80000, false), format!("0.0000000000000000000099999999999999994515327145420957165172950370\ - 2787392447107715776066783064379706047475337982177734375{:0>79881}", "")); + 2787392447107715776066783064379706047475337982177734375{:0>79881}", + "")); } - diff --git a/src/libcoretest/num/flt2dec/strategy/dragon.rs b/src/libcoretest/num/flt2dec/strategy/dragon.rs index 79dcca7671a2d..ea954f9cd336b 100644 --- a/src/libcoretest/num/flt2dec/strategy/dragon.rs +++ b/src/libcoretest/num/flt2dec/strategy/dragon.rs @@ -129,4 +129,3 @@ fn test_to_exact_exp_str() { fn test_to_exact_fixed_str() { to_exact_fixed_str_test(format_exact); } - diff --git a/src/libcoretest/num/flt2dec/strategy/grisu.rs b/src/libcoretest/num/flt2dec/strategy/grisu.rs index 2d4afceda191f..08744b6fcdb19 100644 --- a/src/libcoretest/num/flt2dec/strategy/grisu.rs +++ b/src/libcoretest/num/flt2dec/strategy/grisu.rs @@ -18,12 +18,16 @@ fn test_cached_power() { assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E); assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E); - for e in -1137..961 { // full range for f64 + for e in -1137..961 { + // full range for f64 let low = ALPHA - e - 64; let high = GAMMA - e - 64; let (_k, cached) = cached_power(low, high); assert!(low <= cached.e && cached.e <= high, - "cached_power({}, {}) = {:?} is incorrect", low, high, cached); + "cached_power({}, {}) = {:?} is incorrect", + low, + high, + cached); } } @@ -53,7 +57,8 @@ fn shortest_random_equivalence_test() { f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); } -#[test] #[ignore] // it is too expensive +#[test] +#[ignore] // it is too expensive fn shortest_f32_exhaustive_equivalence_test() { // it is hard to directly test the optimality of the output, but we can at least test if // two different algorithms agree to each other. @@ -66,13 +71,13 @@ fn shortest_f32_exhaustive_equivalence_test() { f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS); } -#[test] #[ignore] // it is too expensive +#[test] +#[ignore] // it is too expensive fn shortest_f64_hard_random_equivalence_test() { // this again probably has to use appropriate rustc flags. use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, - MAX_SIG_DIGITS, 100_000_000); + f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 100_000_000); } #[test] @@ -90,7 +95,9 @@ fn exact_f32_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; for k in 1..21 { f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + |d, buf| fallback(d, buf, i16::MIN), + k, + 1_000); } } @@ -99,7 +106,9 @@ fn exact_f64_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; for k in 1..21 { f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + |d, buf| fallback(d, buf, i16::MIN), + k, + 1_000); } } @@ -178,4 +187,3 @@ fn test_to_exact_exp_str() { fn test_to_exact_fixed_str() { to_exact_fixed_str_test(format_exact); } - diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 4834c0e072c9e..6924629f11eb3 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -44,18 +44,18 @@ pub fn test_num(ten: T, two: T) where + Rem + Debug + Copy { - assert_eq!(ten.add(two), ten + two); - assert_eq!(ten.sub(two), ten - two); - assert_eq!(ten.mul(two), ten * two); - assert_eq!(ten.div(two), ten / two); - assert_eq!(ten.rem(two), ten % two); + assert_eq!(ten.add(two), ten + two); + assert_eq!(ten.sub(two), ten - two); + assert_eq!(ten.mul(two), ten * two); + assert_eq!(ten.div(two), ten / two); + assert_eq!(ten.rem(two), ten % two); } #[test] fn from_str_issue7588() { - let u : Option = u8::from_str_radix("1000", 10).ok(); + let u: Option = u8::from_str_radix("1000", 10).ok(); assert_eq!(u, None); - let s : Option = i16::from_str_radix("80000", 10).ok(); + let s: Option = i16::from_str_radix("80000", 10).ok(); assert_eq!(s, None); } @@ -97,7 +97,8 @@ fn test_int_from_str_overflow() { #[test] fn test_leading_plus() { assert_eq!("+127".parse::().ok(), Some(127)); - assert_eq!("+9223372036854775807".parse::().ok(), Some(9223372036854775807)); + assert_eq!("+9223372036854775807".parse::().ok(), + Some(9223372036854775807)); } #[test] diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index 33674a3abd870..d4b1f2f8692b6 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -14,18 +14,17 @@ use core::ops::{Range, RangeFull, RangeFrom, RangeTo}; // Overhead of dtors struct HasDtor { - _x: isize + _x: isize, } impl Drop for HasDtor { - fn drop(&mut self) { - } + fn drop(&mut self) {} } #[bench] fn alloc_obj_with_dtor(b: &mut Bencher) { b.iter(|| { - HasDtor { _x : 10 }; + HasDtor { _x: 10 }; }) } @@ -33,7 +32,10 @@ fn alloc_obj_with_dtor(b: &mut Bencher) { #[test] fn test_range() { - let r = Range { start: 2, end: 10 }; + let r = Range { + start: 2, + end: 10, + }; let mut count = 0; for (i, ri) in r.enumerate() { assert!(ri == i + 2); diff --git a/src/libcoretest/option.rs b/src/libcoretest/option.rs index 51b0655f680f6..939446d8016b0 100644 --- a/src/libcoretest/option.rs +++ b/src/libcoretest/option.rs @@ -40,11 +40,11 @@ fn test_get_resource() { use core::cell::RefCell; struct R { - i: Rc>, + i: Rc>, } - impl Drop for R { - fn drop(&mut self) { + impl Drop for R { + fn drop(&mut self) { let ii = &*self.i; let i = *ii.borrow(); *ii.borrow_mut() = i + 1; @@ -52,9 +52,7 @@ fn test_get_resource() { } fn r(i: Rc>) -> R { - R { - i: i - } + R { i: i } } let i = Rc::new(RefCell::new(0)); @@ -78,7 +76,8 @@ fn test_option_dance() { assert!(y.is_none()); } -#[test] #[should_panic] +#[test] +#[should_panic] fn test_option_too_much_dance() { struct A; let mut y = Some(A); @@ -218,7 +217,7 @@ fn test_mut_iter() { fn test_ord() { let small = Some(1.0f64); let big = Some(5.0f64); - let nan = Some(0.0f64/0.0); + let nan = Some(0.0f64 / 0.0); assert!(!(nan < big)); assert!(!(nan > big)); assert!(small < big); @@ -234,14 +233,21 @@ fn test_collect() { let v: Option> = (0..3).map(|x| Some(x)).collect(); assert!(v == Some(vec![0, 1, 2])); - let v: Option> = (0..3).map(|x| { - if x > 1 { None } else { Some(x) } - }).collect(); + let v: Option> = (0..3) + .map(|x| { + if x > 1 { + None + } else { + Some(x) + } + }) + .collect(); assert!(v == None); // test that it does not take more elements than it needs - let mut functions: [Box Option<()>>; 3] = - [box || Some(()), box || None, box || panic!()]; + let mut functions: [Box Option<()>>; 3] = [box || Some(()), + box || None, + box || panic!()]; let v: Option> = functions.iter_mut().map(|f| (*f)()).collect(); diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 343db93d4a970..bf49e4294060d 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -15,9 +15,9 @@ fn test() { unsafe { struct Pair { fst: isize, - snd: isize + snd: isize, }; - let mut p = Pair {fst: 10, snd: 20}; + let mut p = Pair { fst: 10, snd: 20 }; let pptr: *mut Pair = &mut p; let iptr: *mut isize = pptr as *mut isize; assert_eq!(*iptr, 10); @@ -25,7 +25,7 @@ fn test() { assert_eq!(*iptr, 30); assert_eq!(p.fst, 30); - *pptr = Pair {fst: 50, snd: 60}; + *pptr = Pair { fst: 50, snd: 60 }; assert_eq!(*iptr, 50); assert_eq!(p.fst, 50); assert_eq!(p.snd, 60); @@ -34,17 +34,11 @@ fn test() { let mut v1 = vec![0u16, 0u16, 0u16]; copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1); - assert!((v1[0] == 0u16 && - v1[1] == 32001u16 && - v1[2] == 0u16)); + assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1); - assert!((v1[0] == 32002u16 && - v1[1] == 32001u16 && - v1[2] == 0u16)); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16)); copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1); - assert!((v1[0] == 32002u16 && - v1[1] == 32001u16 && - v1[2] == 32000u16)); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16)); } } @@ -133,7 +127,7 @@ fn test_ptr_addition() { #[test] fn test_ptr_subtraction() { unsafe { - let xs = vec![0,1,2,3,4,5,6,7,8,9]; + let xs = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let mut idx = 9; let ptr = xs.as_ptr(); @@ -151,7 +145,7 @@ fn test_ptr_subtraction() { m_ptr = m_ptr.offset(-1); } - assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]); + assert_eq!(xs_mut, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]); } } @@ -159,7 +153,9 @@ fn test_ptr_subtraction() { fn test_set_memory() { let mut xs = [0u8; 20]; let ptr = xs.as_mut_ptr(); - unsafe { write_bytes(ptr, 5u8, xs.len()); } + unsafe { + write_bytes(ptr, 5u8, xs.len()); + } assert!(xs == [5u8; 20]); } diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs index 6e9f653dcd8ac..a9919ea4f514c 100644 --- a/src/libcoretest/result.rs +++ b/src/libcoretest/result.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn op1() -> Result { Ok(666) } -fn op2() -> Result { Err("sadface") } +fn op1() -> Result { + Ok(666) +} +fn op2() -> Result { + Err("sadface") +} #[test] fn test_and() { @@ -18,13 +22,14 @@ fn test_and() { "bad"); assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface"); - assert_eq!(op2().and(Err::("bad")).unwrap_err(), + assert_eq!(op2().and(Err::("bad")).unwrap_err(), "sadface"); } #[test] fn test_and_then() { - assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); + assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), + 667); assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), "bad"); @@ -45,10 +50,13 @@ fn test_or() { #[test] fn test_or_else() { - assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); - assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), 666); + assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), + 666); + assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), + 666); - assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); + assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), + 667); assert_eq!(op2().or_else(|e| Err::(e)).unwrap_err(), "sadface"); } @@ -73,14 +81,21 @@ fn test_collect() { let v: Result, ()> = (0..3).map(|x| Ok::(x)).collect(); assert!(v == Ok(vec![0, 1, 2])); - let v: Result, isize> = (0..3).map(|x| { - if x > 1 { Err(x) } else { Ok(x) } - }).collect(); + let v: Result, isize> = (0..3) + .map(|x| { + if x > 1 { + Err(x) + } else { + Ok(x) + } + }) + .collect(); assert!(v == Err(2)); // test that it does not take more elements than it needs - let mut functions: [Box Result<(), isize>>; 3] = - [box || Ok(()), box || Err(1), box || panic!()]; + let mut functions: [Box Result<(), isize>>; 3] = [box || Ok(()), + box || Err(1), + box || panic!()]; let v: Result, isize> = functions.iter_mut().map(|f| (*f)()).collect(); assert!(v == Err(1)); @@ -135,7 +150,7 @@ pub fn test_unwrap_or_else_panic() { } let bad_err: Result = Err("Unrecoverable mess."); - let _ : isize = bad_err.unwrap_or_else(handler); + let _: isize = bad_err.unwrap_or_else(handler); } diff --git a/src/libcoretest/tuple.rs b/src/libcoretest/tuple.rs index 4fe5e0a740bf7..17d5d4a987ea1 100644 --- a/src/libcoretest/tuple.rs +++ b/src/libcoretest/tuple.rs @@ -21,7 +21,7 @@ fn test_clone() { fn test_tuple_cmp() { let (small, big) = ((1, 2, 3), (3, 2, 1)); - let nan = 0.0f64/0.0; + let nan = 0.0f64 / 0.0; // PartialEq assert_eq!(small, small); diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 011f5a744dc84..517cd016e8a35 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -170,10 +170,7 @@ #![deny(missing_docs)] #![cfg_attr(not(stage0), deny(warnings))] -#![feature(box_syntax)] -#![feature(const_fn)] #![feature(staged_api)] -#![feature(static_mutex)] use std::cell::RefCell; use std::fmt; @@ -181,9 +178,8 @@ use std::io::{self, Stderr}; use std::io::prelude::*; use std::mem; use std::env; -use std::ptr; use std::slice; -use std::sync::{Once, StaticMutex}; +use std::sync::{Mutex, ONCE_INIT, Once}; use directive::LOG_LEVEL_NAMES; @@ -199,18 +195,13 @@ pub const MAX_LOG_LEVEL: u32 = 255; /// The default logging level of a crate if no other is specified. const DEFAULT_LOG_LEVEL: u32 = 1; -static LOCK: StaticMutex = StaticMutex::new(); +static mut LOCK: *mut Mutex<(Vec, Option)> = 0 as *mut _; /// An unsafe constant that is the maximum logging level of any module /// specified. This is the first line of defense to determining whether a /// logging statement should be run. static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL; -static mut DIRECTIVES: *mut Vec = ptr::null_mut(); - -/// Optional filter. -static mut FILTER: *mut String = ptr::null_mut(); - /// Debug log level pub const DEBUG: u32 = 4; /// Info log level @@ -287,14 +278,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { // Test the literal string from args against the current filter, if there // is one. unsafe { - let _g = LOCK.lock(); - match FILTER as usize { - 0 => {} - n => { - let filter = mem::transmute::<_, &String>(n); - if !args.to_string().contains(filter) { - return; - } + let filter = (*LOCK).lock().unwrap(); + if let Some(ref filter) = filter.1 { + if !args.to_string().contains(filter) { + return; } } } @@ -302,10 +289,8 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { // Completely remove the local logger from TLS in case anyone attempts to // frob the slot while we're doing the logging. This will destroy any logger // set during logging. - let mut logger: Box = LOCAL_LOGGER.with(|s| s.borrow_mut().take()) - .unwrap_or_else(|| { - box DefaultLogger { handle: io::stderr() } - }); + let logger = LOCAL_LOGGER.with(|s| s.borrow_mut().take()); + let mut logger = logger.unwrap_or_else(|| Box::new(DefaultLogger { handle: io::stderr() })); logger.log(&LogRecord { level: LogLevel(level), args: args, @@ -363,7 +348,7 @@ pub struct LogLocation { /// module's log statement should be emitted or not. #[doc(hidden)] pub fn mod_enabled(level: u32, module: &str) -> bool { - static INIT: Once = Once::new(); + static INIT: Once = ONCE_INIT; INIT.call_once(init); // It's possible for many threads are in this function, only one of them @@ -378,10 +363,9 @@ pub fn mod_enabled(level: u32, module: &str) -> bool { // This assertion should never get tripped unless we're in an at_exit // handler after logging has been torn down and a logging attempt was made. - let _g = LOCK.lock(); unsafe { - assert!(DIRECTIVES as usize != 0); - enabled(level, module, (*DIRECTIVES).iter()) + let directives = (*LOCK).lock().unwrap(); + enabled(level, module, directives.0.iter()) } } @@ -422,14 +406,8 @@ fn init() { unsafe { LOG_LEVEL = max_level; - assert!(FILTER.is_null()); - match filter { - Some(f) => FILTER = Box::into_raw(box f), - None => {} - } - - assert!(DIRECTIVES.is_null()); - DIRECTIVES = Box::into_raw(box directives); + assert!(LOCK.is_null()); + LOCK = Box::into_raw(Box::new(Mutex::new((directives, filter)))); } } diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 76699f13959ea..af47617ea92fd 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -100,7 +100,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex { match pat.node { PatKind::Ident(_, _, None) | - PatKind::TupleStruct(_, None) | PatKind::Path(..) | PatKind::QPath(..) | PatKind::Lit(..) | @@ -116,8 +115,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_ast_node(pat.id, &[subpat_exit]) } - PatKind::TupleStruct(_, Some(ref subpats)) | - PatKind::Tup(ref subpats) => { + PatKind::TupleStruct(_, ref subpats, _) | + PatKind::Tuple(ref subpats, _) => { let pats_exit = self.pats_all(subpats.iter(), pred); self.add_ast_node(pat.id, &[pats_exit]) } diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs index a91d16f25a2b8..641fe5f3b4747 100644 --- a/src/librustc/hir/fold.rs +++ b/src/librustc/hir/fold.rs @@ -923,9 +923,9 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { sub.map(|x| folder.fold_pat(x))) } PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), - PatKind::TupleStruct(pth, pats) => { + PatKind::TupleStruct(pth, pats, ddpos) => { PatKind::TupleStruct(folder.fold_path(pth), - pats.map(|pats| pats.move_map(|x| folder.fold_pat(x)))) + pats.move_map(|x| folder.fold_pat(x)), ddpos) } PatKind::Path(pth) => { PatKind::Path(folder.fold_path(pth)) @@ -948,7 +948,9 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { }); PatKind::Struct(pth, fs, etc) } - PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))), + PatKind::Tuple(elts, ddpos) => { + PatKind::Tuple(elts.move_map(|x| folder.fold_pat(x)), ddpos) + } PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), PatKind::Range(e1, e2) => { @@ -1009,11 +1011,15 @@ pub fn noop_fold_expr(Expr { id, node, span, attrs }: Expr, folder: & ExprWhile(cond, body, opt_name) => { ExprWhile(folder.fold_expr(cond), folder.fold_block(body), - opt_name.map(|i| folder.fold_name(i))) + opt_name.map(|label| { + respan(folder.new_span(label.span), folder.fold_name(label.node)) + })) } ExprLoop(body, opt_name) => { ExprLoop(folder.fold_block(body), - opt_name.map(|i| folder.fold_name(i))) + opt_name.map(|label| { + respan(folder.new_span(label.span), folder.fold_name(label.node)) + })) } ExprMatch(expr, arms, source) => { ExprMatch(folder.fold_expr(expr), diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2e9e433b830fc..80918ce68e26f 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -28,7 +28,7 @@ use syntax::abi::Abi; use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; use syntax::attr::ThinAttributesExt; -use syntax::codemap::Span; +use syntax::codemap::{Span, Spanned}; use hir::*; use std::cmp; @@ -203,11 +203,17 @@ pub trait Visitor<'v> : Sized { } pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option) { - for name in opt_name { + if let Some(name) = opt_name { visitor.visit_name(span, name); } } +pub fn walk_opt_sp_name<'v, V: Visitor<'v>>(visitor: &mut V, opt_sp_name: &Option>) { + if let Some(ref sp_name) = *opt_sp_name { + visitor.visit_name(sp_name.span, sp_name.node); + } +} + /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID); @@ -274,12 +280,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_path(path, item.id); } ViewPathList(ref prefix, ref list) => { - if !list.is_empty() { - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } else { - visitor.visit_path(prefix, item.id); + visitor.visit_path(prefix, item.id); + for item in list { + visitor.visit_path_list_item(prefix, item) } } } @@ -413,12 +416,8 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, - prefix: &'v Path, + _prefix: &'v Path, item: &'v PathListItem) { - for segment in &prefix.segments { - visitor.visit_path_segment(prefix.span, segment); - } - walk_opt_name(visitor, item.span, item.node.name()); walk_opt_name(visitor, item.span, item.node.rename()); } @@ -454,11 +453,9 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { match pattern.node { - PatKind::TupleStruct(ref path, ref opt_children) => { + PatKind::TupleStruct(ref path, ref children, _) => { visitor.visit_path(path, pattern.id); - if let Some(ref children) = *opt_children { - walk_list!(visitor, visit_pat, children); - } + walk_list!(visitor, visit_pat, children); } PatKind::Path(ref path) => { visitor.visit_path(path, pattern.id); @@ -474,7 +471,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_pat(&field.node.pat) } } - PatKind::Tup(ref tuple_elements) => { + PatKind::Tuple(ref tuple_elements, _) => { walk_list!(visitor, visit_pat, tuple_elements); } PatKind::Box(ref subpattern) | @@ -737,14 +734,14 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprWhile(ref subexpression, ref block, opt_name) => { + ExprWhile(ref subexpression, ref block, ref opt_sp_name) => { visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_name(visitor, expression.span, opt_name) + walk_opt_sp_name(visitor, opt_sp_name); } - ExprLoop(ref block, opt_name) => { + ExprLoop(ref block, ref opt_sp_name) => { visitor.visit_block(block); - walk_opt_name(visitor, expression.span, opt_name) + walk_opt_sp_name(visitor, opt_sp_name); } ExprMatch(ref subexpression, ref arms, _) => { visitor.visit_expr(subexpression); @@ -784,9 +781,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => { - for sp_name in opt_sp_name { - visitor.visit_name(sp_name.span, sp_name.node); - } + walk_opt_sp_name(visitor, opt_sp_name); } ExprRet(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 28506fd20fe53..ea9a76d982a3a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -192,6 +192,10 @@ impl<'a> LoweringContext<'a> { } } + fn lower_opt_sp_ident(&mut self, o_id: Option>) -> Option> { + o_id.map(|sp_ident| respan(sp_ident.span, self.lower_ident(sp_ident.node))) + } + fn lower_attrs(&mut self, attrs: &Vec) -> hir::HirVec { attrs.clone().into() } @@ -269,7 +273,7 @@ impl<'a> LoweringContext<'a> { P(hir::Ty { id: t.id, node: match t.node { - Infer => hir::TyInfer, + Infer | ImplicitSelf => hir::TyInfer, Vec(ref ty) => hir::TyVec(self.lower_ty(ty)), Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)), Rptr(ref region, ref mt) => { @@ -787,23 +791,24 @@ impl<'a> LoweringContext<'a> { } fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { - // Check for `self: _` and `self: &_` - if let SelfKind::Explicit(ref ty, _) = sig.explicit_self.node { - match sig.decl.inputs.get(0).and_then(Arg::to_self).map(|eself| eself.node) { - Some(SelfKind::Value(..)) | Some(SelfKind::Region(..)) => { - self.id_assigner.diagnostic().span_err(ty.span, - "the type placeholder `_` is not allowed within types on item signatures"); - } - _ => {} - } - } - hir::MethodSig { + let hir_sig = hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), decl: self.lower_fn_decl(&sig.decl), + }; + // Check for `self: _` and `self: &_` + if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { + match hir_sig.decl.get_self().map(|eself| eself.node) { + Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { + self.id_assigner.diagnostic().span_err(sig.decl.inputs[0].ty.span, + "the type placeholder `_` is not allowed within types on item signatures"); + } + _ => {} + } } + hir_sig } fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { @@ -872,10 +877,10 @@ impl<'a> LoweringContext<'a> { }) } PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)), - PatKind::TupleStruct(ref pth, ref pats) => { + PatKind::TupleStruct(ref pth, ref pats, ddpos) => { hir::PatKind::TupleStruct(self.lower_path(pth), - pats.as_ref() - .map(|pats| pats.iter().map(|x| self.lower_pat(x)).collect())) + pats.iter().map(|x| self.lower_pat(x)).collect(), + ddpos) } PatKind::Path(ref pth) => { hir::PatKind::Path(self.lower_path(pth)) @@ -903,8 +908,8 @@ impl<'a> LoweringContext<'a> { .collect(); hir::PatKind::Struct(pth, fs, etc) } - PatKind::Tup(ref elts) => { - hir::PatKind::Tup(elts.iter().map(|x| self.lower_pat(x)).collect()) + PatKind::Tuple(ref elts, ddpos) => { + hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos) } PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), PatKind::Ref(ref inner, mutbl) => { @@ -1122,11 +1127,10 @@ impl<'a> LoweringContext<'a> { } ExprKind::While(ref cond, ref body, opt_ident) => { hir::ExprWhile(self.lower_expr(cond), self.lower_block(body), - opt_ident.map(|ident| self.lower_ident(ident))) + self.lower_opt_sp_ident(opt_ident)) } ExprKind::Loop(ref body, opt_ident) => { - hir::ExprLoop(self.lower_block(body), - opt_ident.map(|ident| self.lower_ident(ident))) + hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident)) } ExprKind::Match(ref expr, ref arms) => { hir::ExprMatch(self.lower_expr(expr), @@ -1243,12 +1247,8 @@ impl<'a> LoweringContext<'a> { }; hir::ExprPath(hir_qself, self.lower_path_full(path, rename)) } - ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| { - respan(sp_ident.span, self.lower_ident(sp_ident.node)) - })), - ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| { - respan(sp_ident.span, self.lower_ident(sp_ident.node)) - })), + ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)), + ExprKind::Again(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))), ExprKind::InlineAsm(InlineAsm { ref inputs, @@ -1422,8 +1422,7 @@ impl<'a> LoweringContext<'a> { // `[opt_ident]: loop { ... }` let loop_block = self.block_expr(match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| self.lower_ident(ident))); + let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident)); // add attributes to the outer returned expr node let attrs = e.attrs.clone(); return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs }); @@ -1503,8 +1502,7 @@ impl<'a> LoweringContext<'a> { // `[opt_ident]: loop { ... }` let loop_block = self.block_expr(match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| self.lower_ident(ident))); + let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident)); let loop_expr = P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None }); @@ -1857,7 +1855,7 @@ impl<'a> LoweringContext<'a> { let pt = if subpats.is_empty() { hir::PatKind::Path(path) } else { - hir::PatKind::TupleStruct(path, Some(subpats)) + hir::PatKind::TupleStruct(path, subpats, None) }; let pat = self.pat(span, pt); self.resolver.record_resolution(pat.id, def); diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 4af37fe16adb1..bac96c68e4cf8 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -133,7 +133,13 @@ struct ClosureParts<'a> { impl<'a> ClosureParts<'a> { fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { - ClosureParts { decl: d, body: b, id: id, span: s, attrs: attrs } + ClosureParts { + decl: d, + body: b, + id: id, + span: s, + attrs: attrs, + } } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 9f55f46541cfd..99e5f32e263f2 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -19,10 +19,13 @@ use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax::codemap::Span; -/// A Visitor that walks over the HIR and collects Node's into a HIR map. +/// A Visitor that walks over the HIR and collects Nodes into a HIR map pub struct NodeCollector<'ast> { + /// The crate pub krate: &'ast Crate, + /// The node map pub map: Vec>, + /// The parent of this node pub parent_node: NodeId, } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 457511cdbc3b1..d66df3e4e8fd2 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -15,6 +15,7 @@ use syntax::ast; use syntax::parse::token::InternedString; use util::nodemap::NodeMap; +/// The definition table containing node definitions #[derive(Clone)] pub struct Definitions { data: Vec, @@ -139,31 +140,47 @@ pub struct InlinedRootPath { pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. + /// The crate root (marker) CrateRoot, + /// An inlined root InlinedRoot(Box), // Catch-all for random DefId things like DUMMY_NODE_ID Misc, // Different kinds of items and item-like things: + /// An impl Impl, - TypeNs(ast::Name), // something in the type NS - ValueNs(ast::Name), // something in the value NS + /// Something in the type NS + TypeNs(ast::Name), + /// Something in the value NS + ValueNs(ast::Name), + /// A module declaration Module(ast::Name), + /// A macro rule MacroDef(ast::Name), + /// A closure expression ClosureExpr, // Subportions of items + /// A type parameter (generic parameter) TypeParam(ast::Name), + /// A lifetime definition LifetimeDef(ast::Name), + /// A variant of a enum EnumVariant(ast::Name), + /// A struct field Field(ast::Name), - StructCtor, // implicit ctor for a tuple-like struct - Initializer, // initializer for a const - Binding(ast::Name), // pattern binding + /// Implicit ctor for a tuple-like struct + StructCtor, + /// Initializer for a const + Initializer, + /// Pattern binding + Binding(ast::Name), } impl Definitions { + /// Create new empty definition map. pub fn new() -> Definitions { Definitions { data: vec![], @@ -172,6 +189,7 @@ impl Definitions { } } + /// Get the number of definitions. pub fn len(&self) -> usize { self.data.len() } @@ -214,6 +232,7 @@ impl Definitions { } } + /// Add a definition with a parent definition. pub fn create_def_with_parent(&mut self, parent: Option, node_id: ast::NodeId, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 39a6ec9f3af27..ea52a393da6c7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -470,7 +470,7 @@ impl Pat { PatKind::Struct(_, ref fields, _) => { fields.iter().all(|field| field.node.pat.walk_(it)) } - PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => { + PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { s.iter().all(|p| p.walk_(it)) } PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { @@ -485,7 +485,6 @@ impl Pat { PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::Ident(_, _, _) | - PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(_, _) => { true @@ -539,9 +538,10 @@ pub enum PatKind { /// The `bool` is `true` in the presence of a `..`. Struct(Path, HirVec>, bool), - /// A tuple struct/variant pattern `Variant(x, y, z)`. - /// "None" means a `Variant(..)` pattern where we don't bind the fields to names. - TupleStruct(Path, Option>>), + /// A tuple struct/variant pattern `Variant(x, y, .., z)`. + /// If the `..` pattern fragment is present, then `Option` denotes its position. + /// 0 <= position <= subpats.len() + TupleStruct(Path, HirVec>, Option), /// A path pattern. /// Such pattern can be resolved to a unit struct/variant or a constant. @@ -553,8 +553,10 @@ pub enum PatKind { /// PatKind::Path, and the resolver will have to sort that out. QPath(QSelf, Path), - /// A tuple pattern `(a, b)` - Tup(HirVec>), + /// A tuple pattern `(a, b)`. + /// If the `..` pattern fragment is present, then `Option` denotes its position. + /// 0 <= position <= subpats.len() + Tuple(HirVec>, Option), /// A `box` pattern Box(P), /// A reference pattern, e.g. `&mut (a, b)` @@ -873,11 +875,11 @@ pub enum Expr_ { /// A while loop, with an optional label /// /// `'label: while expr { block }` - ExprWhile(P, P, Option), + ExprWhile(P, P, Option>), /// Conditionless loop (can be exited with break, continue, or return) /// /// `'label: loop { block }` - ExprLoop(P, Option), + ExprLoop(P, Option>), /// A `match` block, with a source that indicates whether or not it is /// the result of a desugaring, and if so, which kind. ExprMatch(P, HirVec, MatchSource), @@ -1175,6 +1177,9 @@ pub struct FnDecl { } impl FnDecl { + pub fn get_self(&self) -> Option { + self.inputs.get(0).and_then(Arg::to_self) + } pub fn has_self(&self) -> bool { self.inputs.get(0).map(Arg::is_self).unwrap_or(false) } diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 15f2310607ffe..1008ba7a6e6a0 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -18,9 +18,43 @@ use hir::{self, PatKind}; use syntax::codemap::{respan, Span, Spanned, DUMMY_SP}; use std::cell::RefCell; +use std::iter::{Enumerate, ExactSizeIterator}; pub type PatIdMap = FnvHashMap; +pub struct EnumerateAndAdjust { + enumerate: Enumerate, + gap_pos: usize, + gap_len: usize, +} + +impl Iterator for EnumerateAndAdjust where I: Iterator { + type Item = (usize, ::Item); + + fn next(&mut self) -> Option<(usize, ::Item)> { + self.enumerate.next().map(|(i, elem)| { + (if i < self.gap_pos { i } else { i + self.gap_len }, elem) + }) + } +} + +pub trait EnumerateAndAdjustIterator { + fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option) + -> EnumerateAndAdjust where Self: Sized; +} + +impl EnumerateAndAdjustIterator for T { + fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option) + -> EnumerateAndAdjust where Self: Sized { + let actual_len = self.len(); + EnumerateAndAdjust { + enumerate: self.enumerate(), + gap_pos: if let Some(gap_pos) = gap_pos { gap_pos } else { expected_len }, + gap_len: expected_len - actual_len, + } + } +} + // This is used because same-named variables in alternative patterns need to // use the NodeId of their namesake in the first pattern. pub fn pat_id_map(dm: &RefCell, pat: &hir::Pat) -> PatIdMap { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4455c7da3ba3f..a9ed83d9dc315 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1351,9 +1351,9 @@ impl<'a> State<'a> { hir::ExprIf(ref test, ref blk, ref elseopt) => { self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?; } - hir::ExprWhile(ref test, ref blk, opt_name) => { - if let Some(name) = opt_name { - self.print_name(name)?; + hir::ExprWhile(ref test, ref blk, opt_sp_name) => { + if let Some(sp_name) = opt_sp_name { + self.print_name(sp_name.node)?; self.word_space(":")?; } self.head("while")?; @@ -1361,9 +1361,9 @@ impl<'a> State<'a> { space(&mut self.s)?; self.print_block(&blk)?; } - hir::ExprLoop(ref blk, opt_name) => { - if let Some(name) = opt_name { - self.print_name(name)?; + hir::ExprLoop(ref blk, opt_sp_name) => { + if let Some(sp_name) = opt_sp_name { + self.print_name(sp_name.node)?; self.word_space(":")?; } self.head("loop")?; @@ -1736,16 +1736,23 @@ impl<'a> State<'a> { None => (), } } - PatKind::TupleStruct(ref path, ref args_) => { + PatKind::TupleStruct(ref path, ref elts, ddpos) => { self.print_path(path, true, 0)?; - match *args_ { - None => word(&mut self.s, "(..)")?, - Some(ref args) => { - self.popen()?; - self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p))?; - self.pclose()?; + self.popen()?; + if let Some(ddpos) = ddpos { + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?; + if ddpos != 0 { + self.word_space(",")?; + } + word(&mut self.s, "..")?; + if ddpos != elts.len() { + word(&mut self.s, ",")?; + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } + } else { + try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))); } + try!(self.pclose()); } PatKind::Path(ref path) => { self.print_path(path, true, 0)?; @@ -1778,11 +1785,23 @@ impl<'a> State<'a> { space(&mut self.s)?; word(&mut self.s, "}")?; } - PatKind::Tup(ref elts) => { + PatKind::Tuple(ref elts, ddpos) => { self.popen()?; - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; - if elts.len() == 1 { - word(&mut self.s, ",")?; + if let Some(ddpos) = ddpos { + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?; + if ddpos != 0 { + self.word_space(",")?; + } + word(&mut self.s, "..")?; + if ddpos != elts.len() { + word(&mut self.s, ",")?; + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; + } + } else { + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; + if elts.len() == 1 { + word(&mut self.s, ",")?; + } } self.pclose()?; } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 41982ddc78b65..7c9c52baa63e4 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -163,6 +163,11 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // If the number of errors increases, that's also a sign (line // `tained_by_errors`) to avoid reporting certain kinds of errors. err_count_on_creation: usize, + + // This flag is used for debugging, and is set to true if there are + // any obligations set during the current snapshot. In that case, the + // snapshot can't be rolled back. + pub obligations_in_snapshot: Cell, } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -476,7 +481,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { normalize: false, projection_mode: ProjectionMode::AnyFinal, tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: self.sess.err_count() + err_count_on_creation: self.sess.err_count(), + obligations_in_snapshot: Cell::new(false), } } } @@ -515,7 +521,8 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { normalize: normalize, projection_mode: projection_mode, tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: tcx.sess.err_count() + err_count_on_creation: tcx.sess.err_count(), + obligations_in_snapshot: Cell::new(false), })) } } @@ -542,6 +549,7 @@ pub struct CombinedSnapshot { int_snapshot: unify::Snapshot, float_snapshot: unify::Snapshot, region_vars_snapshot: RegionSnapshot, + obligations_in_snapshot: bool, } /// Helper trait for shortening the lifetimes inside a @@ -809,11 +817,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn start_snapshot(&self) -> CombinedSnapshot { + let obligations_in_snapshot = self.obligations_in_snapshot.get(); + self.obligations_in_snapshot.set(false); + CombinedSnapshot { type_snapshot: self.type_variables.borrow_mut().snapshot(), int_snapshot: self.int_unification_table.borrow_mut().snapshot(), float_snapshot: self.float_unification_table.borrow_mut().snapshot(), region_vars_snapshot: self.region_vars.start_snapshot(), + obligations_in_snapshot: obligations_in_snapshot, } } @@ -822,7 +834,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let CombinedSnapshot { type_snapshot, int_snapshot, float_snapshot, - region_vars_snapshot } = snapshot; + region_vars_snapshot, + obligations_in_snapshot } = snapshot; + + assert!(!self.obligations_in_snapshot.get()); + self.obligations_in_snapshot.set(obligations_in_snapshot); self.type_variables .borrow_mut() @@ -842,7 +858,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let CombinedSnapshot { type_snapshot, int_snapshot, float_snapshot, - region_vars_snapshot } = snapshot; + region_vars_snapshot, + obligations_in_snapshot } = snapshot; + + self.obligations_in_snapshot.set(obligations_in_snapshot); self.type_variables .borrow_mut() @@ -904,12 +923,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let CombinedSnapshot { type_snapshot, int_snapshot, float_snapshot, - region_vars_snapshot } = self.start_snapshot(); + region_vars_snapshot, + obligations_in_snapshot } = self.start_snapshot(); let r = self.commit_if_ok(|_| f()); debug!("commit_regions_if_ok: rolling back everything but regions"); + assert!(!self.obligations_in_snapshot.get()); + self.obligations_in_snapshot.set(obligations_in_snapshot); + // Roll back any non-region bindings - they should be resolved // inside `f`, with, e.g. `resolve_type_vars_if_possible`. self.type_variables diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 0801f8f4ac7ef..94f17ea779ac8 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1043,11 +1043,6 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { run_lints!(self, check_lifetime_def, early_passes, lt); } - fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { - run_lints!(self, check_explicit_self, early_passes, es); - ast_visit::walk_explicit_self(self, es); - } - fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) { run_lints!(self, check_path, early_passes, p, id); ast_visit::walk_path(self, p); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 28994e1a7c48d..cc7fa54bd0a5e 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -167,7 +167,6 @@ pub trait LateLintPass: LintPass { fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { } fn check_lifetime(&mut self, _: &LateContext, _: &hir::Lifetime) { } fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { } - fn check_explicit_self(&mut self, _: &LateContext, _: &hir::ExplicitSelf) { } fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { } fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { } fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { } @@ -218,7 +217,6 @@ pub trait EarlyLintPass: LintPass { fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } - fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } fn check_path_list_item(&mut self, _: &EarlyContext, _: &ast::PathListItem) { } fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index e5a8c1d1b4e6f..3ede60beb7443 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -34,8 +34,7 @@ use mir::mir_map::MirMap; use session::Session; use session::config::PanicStrategy; use session::search_paths::PathKind; -use util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; -use std::cell::RefCell; +use util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use std::rc::Rc; use std::path::PathBuf; use syntax::ast; @@ -169,7 +168,6 @@ pub trait CrateStore<'tcx> { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; fn item_attrs(&self, def_id: DefId) -> Vec; - fn item_symbol(&self, def: DefId) -> String; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; fn method_arg_names(&self, did: DefId) -> Vec; @@ -205,6 +203,7 @@ pub trait CrateStore<'tcx> { fn is_impl(&self, did: DefId) -> bool; fn is_default_impl(&self, impl_did: DefId) -> bool; fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool; + fn is_foreign_item(&self, did: DefId) -> bool; fn is_static_method(&self, did: DefId) -> bool; fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool; fn is_typedef(&self, did: DefId) -> bool; @@ -274,7 +273,6 @@ pub trait CrateStore<'tcx> { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -352,7 +350,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } - fn item_symbol(&self, def: DefId) -> String { bug!("item_symbol") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> @@ -399,6 +396,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") } fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool { bug!("is_extern_item") } + fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") } fn is_static_method(&self, did: DefId) -> bool { bug!("is_static_method") } fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false } fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") } @@ -481,7 +479,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 41b27a48b29f8..4d01b59001c5d 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -660,8 +660,8 @@ fn set_bit(words: &mut [usize], bit: usize) -> bool { } fn bit_str(bit: usize) -> String { - let byte = bit >> 8; - let lobits = 1 << (bit & 0xFF); + let byte = bit >> 3; + let lobits = 1 << (bit & 0b111); format!("[{}:{}-{:02x}]", bit, byte, lobits) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 4cee8c5d89ae6..b0add5a23dc46 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1127,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // will visit the substructure recursively. } - PatKind::Wild | PatKind::Tup(..) | PatKind::Box(..) | + PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) | PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) | PatKind::Vec(..) => { // Similarly, each of these cases does not diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3999b02425de6..e933b22f60799 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -80,6 +80,7 @@ use ty::adjustment; use ty::{self, Ty, TyCtxt}; use hir::{MutImmutable, MutMutable, PatKind}; +use hir::pat_util::EnumerateAndAdjustIterator; use hir; use syntax::ast; use syntax::codemap::Span; @@ -1225,14 +1226,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // _ } - PatKind::TupleStruct(_, None) => { - // variant(..) - } - PatKind::TupleStruct(_, Some(ref subpats)) => { + PatKind::TupleStruct(_, ref subpats, ddpos) => { match opt_def { - Some(Def::Variant(..)) => { + Some(Def::Variant(enum_def, def_id)) => { // variant(x, y, z) - for (i, subpat) in subpats.iter().enumerate() { + let expected_len = self.tcx().lookup_adt_def(enum_def) + .variant_with_id(def_id).fields.len(); + for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let subcmt = @@ -1244,7 +1244,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } Some(Def::Struct(..)) => { - for (i, subpat) in subpats.iter().enumerate() { + let expected_len = match self.pat_ty(&pat) { + Ok(&ty::TyS{sty: ty::TyStruct(adt_def, _), ..}) => { + adt_def.struct_variant().fields.len() + } + ref ty => { + span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); + } + }; + + for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let cmt_field = self.cat_imm_interior( @@ -1284,9 +1293,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - PatKind::Tup(ref subpats) => { + PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) - for (i, subpat) in subpats.iter().enumerate() { + let expected_len = match self.pat_ty(&pat) { + Ok(&ty::TyS{sty: ty::TyTuple(ref tys), ..}) => tys.len(), + ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), + }; + for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let subcmt = self.cat_imm_interior( diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 56b4036b7d785..6b2c2dfcd72b4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -970,8 +970,8 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { pats3.iter().any(|p| is_binding_pat(&p)) } - PatKind::TupleStruct(_, Some(ref subpats)) | - PatKind::Tup(ref subpats) => { + PatKind::TupleStruct(_, ref subpats, _) | + PatKind::Tuple(ref subpats, _) => { subpats.iter().any(|p| is_binding_pat(&p)) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 2200d72c883ff..4cc9b0b4353a0 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -404,23 +404,23 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) { if let hir::ExprClosure(..) = ex.node { return } - if let Some(label) = expression_label(ex) { + if let Some((label, label_span)) = expression_label(ex) { for &(prior, prior_span) in &self.labels_in_fn[..] { // FIXME (#24278): non-hygienic comparison if label == prior { signal_shadowing_problem(self.sess, label, original_label(prior_span), - shadower_label(ex.span)); + shadower_label(label_span)); } } check_if_label_shadows_lifetime(self.sess, self.scope, label, - ex.span); + label_span); - self.labels_in_fn.push((label, ex.span)); + self.labels_in_fn.push((label, label_span)); } intravisit::walk_expr(self, ex) } @@ -430,10 +430,11 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) { } } - fn expression_label(ex: &hir::Expr) -> Option { + fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> { match ex.node { hir::ExprWhile(_, _, Some(label)) | - hir::ExprLoop(_, Some(label)) => Some(label.unhygienize()), + hir::ExprLoop(_, Some(label)) => Some((label.node.unhygienize(), + label.span)), _ => None, } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c2db6de03700e..fcb03aba6d12c 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -33,6 +33,7 @@ use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap}; use hir; use hir::{Item, Generics, StructField, Variant, PatKind}; use hir::intravisit::{self, Visitor}; +use hir::pat_util::EnumerateAndAdjustIterator; use std::mem::replace; use std::cmp::Ordering; @@ -614,10 +615,9 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat, }; match pat.node { // Foo(a, b, c) - // A Variant(..) pattern `PatKind::TupleStruct(_, None)` doesn't have to be recursed into. - PatKind::TupleStruct(_, Some(ref pat_fields)) => { - for (field, struct_field) in pat_fields.iter().zip(&v.fields) { - maybe_do_stability_check(tcx, struct_field.did, field.span, cb) + PatKind::TupleStruct(_, ref pat_fields, ddpos) => { + for (i, field) in pat_fields.iter().enumerate_and_adjust(v.fields.len(), ddpos) { + maybe_do_stability_check(tcx, v.fields[i].did, field.span, cb) } } // Foo { a, b, c } diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 458cb28144adb..f9a671435ffdb 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -226,7 +226,8 @@ pub struct UpvarDecl { /// list of the `Mir`. /// /// (We use a `u32` internally just to save memory.) -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, + RustcEncodable, RustcDecodable)] pub struct BasicBlock(u32); impl BasicBlock { diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 79c44b2b851c7..828a48532a2fc 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -18,7 +18,7 @@ use ty::TyCtxt; use syntax::ast::NodeId; /// Where a specific Mir comes from. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub enum MirSource { /// Functions and methods. Fn(NodeId), diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index da5555dbd6453..05ed02211097c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1104,7 +1104,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let no_analysis = debugging_opts.no_analysis; let mut output_types = HashMap::new(); - if !debugging_opts.parse_only && !no_trans { + if !debugging_opts.parse_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { let mut parts = output_type.splitn(2, '='); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 907241d1746d6..ab9187a835dad 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -9,6 +9,8 @@ // except according to those terms. use dep_graph::DepGraph; +use hir::def_id::DefIndex; +use hir::svh::Svh; use lint; use middle::cstore::CrateStore; use middle::dependency_format; @@ -312,6 +314,14 @@ impl Session { pub fn nonzeroing_move_hints(&self) -> bool { self.opts.debugging_opts.enable_nonzeroing_move_hints } + + /// Returns the symbol name for the registrar function, + /// given the crate Svh and the function DefIndex. + pub fn generate_plugin_registrar_symbol(&self, svh: &Svh, index: DefIndex) + -> String { + format!("__rustc_plugin_registrar__{}_{}", svh, index.as_usize()) + } + pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot { Some (ref sysroot) => sysroot, diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index d9d0367bdcb10..0d7d7afd120d2 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -171,6 +171,8 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { // debug output much nicer to read and so on. let obligation = infcx.resolve_type_vars_if_possible(&obligation); + infcx.obligations_in_snapshot.set(true); + if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) { return diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c5db2a8a7807b..c177ec4dbede7 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -31,7 +31,7 @@ pub use self::coherence::overlapping_impls; pub use self::coherence::OrphanCheckErr; pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation}; pub use self::project::{MismatchedProjectionTypes, ProjectionMode}; -pub use self::project::{normalize, Normalized}; +pub use self::project::{normalize, normalize_projection_type, Normalized}; pub use self::object_safety::ObjectSafetyViolation; pub use self::object_safety::MethodViolationCode; pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 5c7095beb79c8..44ec42de8cbd6 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -207,7 +207,7 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( debug!("project_and_unify_type(obligation={:?})", obligation); - let Normalized { value: normalized_ty, obligations } = + let Normalized { value: normalized_ty, mut obligations } = match opt_normalize_projection_type(selcx, obligation.predicate.projection_ty.clone(), obligation.cause.clone(), @@ -224,8 +224,9 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); match infcx.eq_types(true, origin, normalized_ty, obligation.predicate.ty) { Ok(InferOk { obligations: inferred_obligations, .. }) => { - // FIXME(#32730) propagate obligations + // FIXME(#32730) once obligations are generated in inference, drop this assertion assert!(inferred_obligations.is_empty()); + obligations.extend(inferred_obligations); Ok(Some(obligations)) }, Err(err) => Err(MismatchedProjectionTypes { err: err }), @@ -710,7 +711,8 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( origin, data_poly_trait_ref, obligation_poly_trait_ref) - // FIXME(#32730) propagate obligations + // FIXME(#32730) once obligations are propagated from unification in + // inference, drop this assertion .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) .is_ok() }); @@ -1047,8 +1049,8 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>) -> (Ty<'tcx>, Vec>) { - // FIXME(#32730) propagate obligations (fn pointer vtable nested obligations ONLY come from - // unification in inference) + // FIXME(#32730) drop this assertion once obligations are propagated from inference (fn pointer + // vtable nested obligations ONLY come from unification in inference) assert!(fn_pointer_vtable.nested.is_empty()); let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); let sig = fn_type.fn_sig(); @@ -1130,13 +1132,14 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( obligation.predicate.item_name); let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); - match infcx.eq_trait_refs(false, - origin, - obligation.predicate.trait_ref.clone(), - projection.projection_ty.trait_ref.clone()) { + let obligations = match infcx.eq_trait_refs(false, + origin, + obligation.predicate.trait_ref.clone(), + projection.projection_ty.trait_ref.clone()) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations + // FIXME(#32730) once obligations are generated in inference, remove this assertion assert!(obligations.is_empty()); + obligations } Err(e) => { span_bug!( @@ -1146,9 +1149,9 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( projection, e); } - } + }; - (projection.ty, vec!()) + (projection.ty, obligations) } fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index b2d14dab9a0b0..c7a3637557602 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -187,51 +187,49 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, source_trait_ref: ty::TraitRef<'tcx>, target_impl: DefId) -> Result<&'tcx Substs<'tcx>, ()> { - infcx.commit_if_ok(|_| { - let selcx = &mut SelectionContext::new(&infcx); - let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl); - let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, - target_impl, - &target_substs); - - // do the impls unify? If not, no specialization. - if let Err(_) = infcx.eq_trait_refs(true, - TypeOrigin::Misc(DUMMY_SP), - source_trait_ref, - target_trait_ref) { - debug!("fulfill_implication: {:?} does not unify with {:?}", - source_trait_ref, - target_trait_ref); - return Err(()); - } + let selcx = &mut SelectionContext::new(&infcx); + let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl); + let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, + target_impl, + &target_substs); + + // do the impls unify? If not, no specialization. + if let Err(_) = infcx.eq_trait_refs(true, + TypeOrigin::Misc(DUMMY_SP), + source_trait_ref, + target_trait_ref) { + debug!("fulfill_implication: {:?} does not unify with {:?}", + source_trait_ref, + target_trait_ref); + return Err(()); + } - // attempt to prove all of the predicates for impl2 given those for impl1 - // (which are packed up in penv) + // attempt to prove all of the predicates for impl2 given those for impl1 + // (which are packed up in penv) - let mut fulfill_cx = FulfillmentContext::new(); - for oblig in obligations.into_iter() { - fulfill_cx.register_predicate_obligation(&infcx, oblig); - } + let mut fulfill_cx = FulfillmentContext::new(); + for oblig in obligations.into_iter() { + fulfill_cx.register_predicate_obligation(&infcx, oblig); + } - if let Err(errors) = infcx.drain_fulfillment_cx(&mut fulfill_cx, &()) { - // no dice! - debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \ - {:?}", - source_trait_ref, - target_trait_ref, - errors, - infcx.parameter_environment.caller_bounds); - Err(()) - } else { - debug!("fulfill_implication: an impl for {:?} specializes {:?}", - source_trait_ref, - target_trait_ref); - - // Now resolve the *substitution* we built for the target earlier, replacing - // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_type_vars_if_possible(&target_substs)) - } - }) + if let Err(errors) = infcx.drain_fulfillment_cx(&mut fulfill_cx, &()) { + // no dice! + debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \ + {:?}", + source_trait_ref, + target_trait_ref, + errors, + infcx.parameter_environment.caller_bounds); + Err(()) + } else { + debug!("fulfill_implication: an impl for {:?} specializes {:?}", + source_trait_ref, + target_trait_ref); + + // Now resolve the *substitution* we built for the target earlier, replacing + // the inference variables inside with whatever we got from fulfillment. + Ok(infcx.resolve_type_vars_if_possible(&target_substs)) + } } pub struct SpecializesCache { diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 71e49031347b8..60f2ca6f4d9b6 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -235,8 +235,9 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> { None => { span_bug!( expr_span, - "the {}th autoderef failed: {}", + "the {}th autoderef for {} failed: {}", autoderef, + expr_id, adjusted_ty); } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 4a14185b6e3ad..f76f4c01df344 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -99,6 +99,16 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { TypeFlags::HAS_RE_INFER | TypeFlags::HAS_FREE_REGIONS) } + fn is_normalized_for_trans(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_RE_EARLY_BOUND | + TypeFlags::HAS_RE_INFER | + TypeFlags::HAS_FREE_REGIONS | + TypeFlags::HAS_TY_INFER | + TypeFlags::HAS_PARAMS | + TypeFlags::HAS_PROJECTION | + TypeFlags::HAS_TY_ERR | + TypeFlags::HAS_SELF) + } /// Indicates whether this value references only 'global' /// types/lifetimes that are the same regardless of what fn we are /// in. This is used for caching. Errs on the side of returning diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 5246c6739d960..ee9983038b162 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,12 +14,38 @@ use hir::def_id::{DefId, CRATE_DEF_INDEX}; use ty::{self, Ty, TyCtxt}; use syntax::ast; +use std::cell::Cell; + +thread_local! { + static FORCE_ABSOLUTE: Cell = Cell::new(false) +} + +/// Enforces that item_path_str always returns an absolute path. +/// This is useful when building symbols that contain types, +/// where we want the crate name to be part of the symbol. +pub fn with_forced_absolute_paths R, R>(f: F) -> R { + FORCE_ABSOLUTE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate - /// root. + /// root, unless with_forced_absolute_paths was used. pub fn item_path_str(self, def_id: DefId) -> String { - let mut buffer = LocalPathBuffer::new(RootMode::Local); + let mode = FORCE_ABSOLUTE.with(|force| { + if force.get() { + RootMode::Absolute + } else { + RootMode::Local + } + }); + let mut buffer = LocalPathBuffer::new(mode); self.push_item_path(&mut buffer, def_id); buffer.into_string() } @@ -75,7 +101,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. - buffer.push(&self.crate_name(cnum)); + if cnum == LOCAL_CRATE { + buffer.push(&self.crate_name(cnum)); + } else { + buffer.push(&self.sess.cstore.original_crate_name(cnum)); + } } } } diff --git a/src/librustc_back/dynamic_lib.rs b/src/librustc_back/dynamic_lib.rs index 2f86262afbe22..38e60060925e6 100644 --- a/src/librustc_back/dynamic_lib.rs +++ b/src/librustc_back/dynamic_lib.rs @@ -189,12 +189,16 @@ mod dl { pub fn check_for_errors_in(f: F) -> Result where F: FnOnce() -> T, { - use std::sync::StaticMutex; - static LOCK: StaticMutex = StaticMutex::new(); + use std::sync::{Mutex, Once, ONCE_INIT}; + static INIT: Once = ONCE_INIT; + static mut LOCK: *mut Mutex<()> = 0 as *mut _; unsafe { + INIT.call_once(|| { + LOCK = Box::into_raw(Box::new(Mutex::new(()))); + }); // dlerror isn't thread safe, so we need to lock around this entire // sequence - let _guard = LOCK.lock(); + let _guard = (*LOCK).lock(); let _old_error = libc::dlerror(); let result = f(); diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 67b11a930d6f7..6a7bc51d15a42 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -38,7 +38,6 @@ #![feature(staged_api)] #![feature(step_by)] #![feature(question_mark)] -#![cfg_attr(unix, feature(static_mutex))] #![cfg_attr(test, feature(test, rand))] extern crate syntax; diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 404298d8839ae..97fb39c17ea0e 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -25,11 +25,10 @@ fn write_u32_be(dst: &mut[u8], input: u32) { /// Read the value of a vector of bytes as a u32 value in big-endian format. fn read_u32_be(input: &[u8]) -> u32 { - return - (input[0] as u32) << 24 | + (input[0] as u32) << 24 | (input[1] as u32) << 16 | (input[2] as u32) << 8 | - (input[3] as u32); + (input[3] as u32) } /// Read a vector of bytes into a vector of u32s. The values are read in big-endian format. @@ -50,7 +49,7 @@ trait ToBits: Sized { impl ToBits for u64 { fn to_bits(self) -> (u64, u64) { - return (self >> 61, self << 3); + (self >> 61, self << 3) } } @@ -64,7 +63,7 @@ fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 { } match bits.checked_add(new_low_bits) { - Some(x) => return x, + Some(x) => x, None => panic!("numeric overflow occurred.") } } @@ -113,10 +112,10 @@ struct FixedBuffer64 { impl FixedBuffer64 { /// Create a new FixedBuffer64 fn new() -> FixedBuffer64 { - return FixedBuffer64 { + FixedBuffer64 { buffer: [0; 64], buffer_idx: 0 - }; + } } } @@ -175,13 +174,13 @@ impl FixedBuffer for FixedBuffer64 { fn next<'s>(&'s mut self, len: usize) -> &'s mut [u8] { self.buffer_idx += len; - return &mut self.buffer[self.buffer_idx - len..self.buffer_idx]; + &mut self.buffer[self.buffer_idx - len..self.buffer_idx] } fn full_buffer<'s>(&'s mut self) -> &'s [u8] { assert!(self.buffer_idx == 64); self.buffer_idx = 0; - return &self.buffer[..64]; + &self.buffer[..64] } fn position(&self) -> usize { self.buffer_idx } @@ -278,7 +277,7 @@ struct Engine256State { impl Engine256State { fn new(h: &[u32; 8]) -> Engine256State { - return Engine256State { + Engine256State { h0: h[0], h1: h[1], h2: h[2], @@ -287,7 +286,7 @@ impl Engine256State { h5: h[5], h6: h[6], h7: h[7] - }; + } } fn reset(&mut self, h: &[u32; 8]) { @@ -433,7 +432,7 @@ struct Engine256 { impl Engine256 { fn new(h: &[u32; 8]) -> Engine256 { - return Engine256 { + Engine256 { length_bits: 0, buffer: FixedBuffer64::new(), state: Engine256State::new(h), @@ -457,17 +456,15 @@ impl Engine256 { } fn finish(&mut self) { - if self.finished { - return; + if !self.finished { + let self_state = &mut self.state; + self.buffer.standard_padding(8, |input: &[u8]| { self_state.process_block(input) }); + write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 ); + write_u32_be(self.buffer.next(4), self.length_bits as u32); + self_state.process_block(self.buffer.full_buffer()); + + self.finished = true; } - - let self_state = &mut self.state; - self.buffer.standard_padding(8, |input: &[u8]| { self_state.process_block(input) }); - write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 ); - write_u32_be(self.buffer.next(4), self.length_bits as u32); - self_state.process_block(self.buffer.full_buffer()); - - self.finished = true; } } diff --git a/src/librustc_borrowck/bitslice.rs b/src/librustc_borrowck/bitslice.rs index a4aa7ae15744d..80fa86a007ed3 100644 --- a/src/librustc_borrowck/bitslice.rs +++ b/src/librustc_borrowck/bitslice.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME: move this to `rustc_data_structures` and potentially merge +// with `bitvec` there. + use std::mem; -/// `BitSlice` provides helper methods for treating a `[usize]` +pub type Word = usize; + +/// `BitSlice` provides helper methods for treating a `[Word]` /// as a bitvector. pub trait BitSlice { fn clear_bit(&mut self, idx: usize) -> bool; @@ -18,12 +23,12 @@ pub trait BitSlice { fn get_bit(&self, idx: usize) -> bool; } -impl BitSlice for [usize] { +impl BitSlice for [Word] { /// Clears bit at `idx` to 0; returns true iff this changed `self.` fn clear_bit(&mut self, idx: usize) -> bool { let words = self; debug!("clear_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); + bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); let oldv = words[word]; @@ -36,7 +41,7 @@ impl BitSlice for [usize] { fn set_bit(&mut self, idx: usize) -> bool { let words = self; debug!("set_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); + bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); let oldv = words[word]; @@ -54,52 +59,85 @@ impl BitSlice for [usize] { } struct BitLookup { - /// An index of the word holding the bit in original `[usize]` of query. + /// An index of the word holding the bit in original `[Word]` of query. word: usize, /// Index of the particular bit within the word holding the bit. bit_in_word: usize, /// Word with single 1-bit set corresponding to where the bit is located. - bit_mask: usize, + bit_mask: Word, } #[inline] fn bit_lookup(bit: usize) -> BitLookup { - let usize_bits = mem::size_of::() * 8; - let word = bit / usize_bits; - let bit_in_word = bit % usize_bits; + let word_bits = mem::size_of::() * 8; + let word = bit / word_bits; + let bit_in_word = bit % word_bits; let bit_mask = 1 << bit_in_word; BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask } } -fn bit_str(bit: usize) -> String { - let byte = bit >> 8; - let lobits = 1 << (bit & 0xFF); +fn bit_str(bit: Word) -> String { + let byte = bit >> 3; + let lobits = 1 << (bit & 0b111); format!("[{}:{}-{:02x}]", bit, byte, lobits) } -pub fn bits_to_string(words: &[usize], bytes: usize) -> String { +pub fn bits_to_string(words: &[Word], bits: usize) -> String { let mut result = String::new(); let mut sep = '['; // Note: this is a little endian printout of bytes. + // i tracks how many bits we have printed so far. let mut i = 0; for &word in words.iter() { let mut v = word; - for _ in 0..mem::size_of::() { - let byte = v & 0xFF; - if i >= bytes { - assert!(byte == 0); - } else { - result.push(sep); - result.push_str(&format!("{:02x}", byte)); - } + loop { // for each byte in `v`: + let remain = bits - i; + // If less than a byte remains, then mask just that many bits. + let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; + assert!(mask <= 0xFF); + let byte = v & mask; + + result.push(sep); + result.push_str(&format!("{:02x}", byte)); + + if remain <= 8 { break; } v >>= 8; - i += 1; + i += 8; sep = '-'; } } result.push(']'); return result } + +#[inline] +pub fn bitwise(out_vec: &mut [usize], + in_vec: &[usize], + op: &Op) -> bool { + assert_eq!(out_vec.len(), in_vec.len()); + let mut changed = false; + for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) { + let old_val = *out_elt; + let new_val = op.join(old_val, *in_elt); + *out_elt = new_val; + changed |= old_val != new_val; + } + changed +} + +pub trait BitwiseOperator { + /// Applies some bit-operation pointwise to each of the bits in the two inputs. + fn join(&self, pred1: usize, pred2: usize) -> usize; +} + +pub struct Union; +impl BitwiseOperator for Union { + fn join(&self, a: usize, b: usize) -> usize { a | b } +} +pub struct Subtract; +impl BitwiseOperator for Subtract { + fn join(&self, a: usize, b: usize) -> usize { a & !b } +} diff --git a/src/librustc_borrowck/borrowck/mir/dataflow.rs b/src/librustc_borrowck/borrowck/mir/dataflow.rs deleted file mode 100644 index d6dd176e3ba28..0000000000000 --- a/src/librustc_borrowck/borrowck/mir/dataflow.rs +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::attr::AttrMetaMethods; - -use rustc::ty::TyCtxt; -use rustc::mir::repr::{self, Mir}; - -use std::io; -use std::mem; -use std::usize; - -use super::MirBorrowckCtxt; -use super::gather_moves::{Location, MoveData, MovePathData, MovePathIndex, MoveOutIndex, PathMap}; -use super::graphviz; -use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. - -pub trait Dataflow { - fn dataflow(&mut self); -} - -impl<'b, 'a: 'b, 'tcx: 'a> Dataflow for MirBorrowckCtxt<'b, 'a, 'tcx> { - fn dataflow(&mut self) { - self.build_gen_and_kill_sets(); - self.pre_dataflow_instrumentation().unwrap(); - self.propagate(); - self.post_dataflow_instrumentation().unwrap(); - } -} - -struct PropagationContext<'c, 'b: 'c, 'a: 'b, 'tcx: 'a, OnReturn> - where OnReturn: Fn(&MoveData, &mut [usize], &repr::Lvalue) -{ - mbcx: &'c mut MirBorrowckCtxt<'b, 'a, 'tcx>, - changed: bool, - on_return: OnReturn -} - -impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { - fn propagate(&mut self) { - let mut temp = vec![0; self.flow_state.sets.words_per_block]; - let mut propcx = PropagationContext { - mbcx: &mut *self, - changed: true, - on_return: |move_data, in_out, dest_lval| { - let move_path_index = move_data.rev_lookup.find(dest_lval); - on_all_children_bits(in_out, - &move_data.path_map, - &move_data.move_paths, - move_path_index, - &|in_out, mpi| { - in_out.clear_bit(mpi.idx()); - }); - }, - }; - while propcx.changed { - propcx.changed = false; - propcx.reset(&mut temp); - propcx.walk_cfg(&mut temp); - } - } - - fn build_gen_and_kill_sets(&mut self) { - // First we need to build the gen- and kill-sets. The - // gather_moves information provides a high-level mapping from - // mir-locations to the MoveOuts (and those correspond - // directly to gen-sets here). But we still need to figure out - // the kill-sets. - - let move_data = &self.flow_state.operator; - let move_paths = &move_data.move_paths; - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - let rev_lookup = &move_data.rev_lookup; - - for bb in self.mir.all_basic_blocks() { - let &repr::BasicBlockData { ref statements, - ref terminator, - is_cleanup: _ } = - self.mir.basic_block_data(bb); - - let mut sets = self.flow_state.sets.for_block(bb.index()); - for (j, stmt) in statements.iter().enumerate() { - let loc = Location { block: bb, index: j }; - debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", - stmt, loc, &loc_map[loc]); - for move_index in &loc_map[loc] { - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - zero_to_one(&mut sets.gen_set, *move_index); - } - match stmt.kind { - repr::StatementKind::Assign(ref lvalue, _) => { - // assigning into this `lvalue` kills all - // MoveOuts from it, and *also* all MoveOuts - // for children and associated fragment sets. - let move_path_index = rev_lookup.find(lvalue); - - on_all_children_bits(sets.kill_set, - path_map, - move_paths, - move_path_index, - &|kill_set, mpi| { - kill_set.set_bit(mpi.idx()); - }); - } - } - } - - let loc = Location { block: bb, index: statements.len() }; - debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", - terminator, loc, &loc_map[loc]); - for move_index in &loc_map[loc] { - zero_to_one(&mut sets.gen_set, *move_index); - } - } - - fn zero_to_one(gen_set: &mut [usize], move_index: MoveOutIndex) { - let retval = gen_set.set_bit(move_index.idx()); - assert!(retval); - } - } -} - -fn on_all_children_bits(set: &mut [usize], - path_map: &PathMap, - move_paths: &MovePathData, - move_path_index: MovePathIndex, - each_child: &Each) - where Each: Fn(&mut [usize], MoveOutIndex) -{ - // 1. invoke `each_child` callback for all moves that directly - // influence path for `move_path_index` - for move_index in &path_map[move_path_index] { - each_child(set, *move_index); - } - - // 2. for each child of the path (that is named in this - // function), recur. - // - // (Unnamed children are irrelevant to dataflow; by - // definition they have no associated moves.) - let mut next_child_index = move_paths[move_path_index].first_child; - while let Some(child_index) = next_child_index { - on_all_children_bits(set, path_map, move_paths, child_index, each_child); - next_child_index = move_paths[child_index].next_sibling; - } -} - -impl<'c, 'b: 'c, 'a: 'b, 'tcx: 'a, OnReturn> PropagationContext<'c, 'b, 'a, 'tcx, OnReturn> - where OnReturn: Fn(&MoveData, &mut [usize], &repr::Lvalue) -{ - fn reset(&mut self, bits: &mut [usize]) { - let e = if self.mbcx.flow_state.operator.initial_value() {usize::MAX} else {0}; - for b in bits { - *b = e; - } - } - - fn walk_cfg(&mut self, in_out: &mut [usize]) { - let &mut MirBorrowckCtxt { ref mir, ref mut flow_state, .. } = self.mbcx; - for (idx, bb) in mir.basic_blocks.iter().enumerate() { - { - let sets = flow_state.sets.for_block(idx); - debug_assert!(in_out.len() == sets.on_entry.len()); - in_out.clone_from_slice(sets.on_entry); - bitwise(in_out, sets.gen_set, &Union); - bitwise(in_out, sets.kill_set, &Subtract); - } - flow_state.propagate_bits_into_graph_successors_of(in_out, - &mut self.changed, - bb, - &self.on_return); - } - } -} - -impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { - fn pre_dataflow_instrumentation(&self) -> io::Result<()> { - self.if_attr_meta_name_found( - "borrowck_graphviz_preflow", - |this, path: &str| { - graphviz::print_borrowck_graph_to(this, "preflow", path) - }) - } - - fn post_dataflow_instrumentation(&self) -> io::Result<()> { - self.if_attr_meta_name_found( - "borrowck_graphviz_postflow", - |this, path: &str| { - graphviz::print_borrowck_graph_to(this, "postflow", path) - }) - } - - fn if_attr_meta_name_found(&self, - name: &str, - callback: F) -> io::Result<()> - where F: for <'aa, 'bb> FnOnce(&'aa Self, &'bb str) -> io::Result<()> - { - for attr in self.attributes { - if attr.check_name("rustc_mir") { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - if item.check_name(name) { - if let Some(s) = item.value_str() { - return callback(self, &s); - } else { - self.bcx.tcx.sess.span_err( - item.span, - &format!("{} attribute requires a path", item.name())); - } - } - } - } - } - - Ok(()) - } -} - -/// Maps each block to a set of bits -#[derive(Clone, Debug)] -struct Bits { - bits: Vec, -} - -impl Bits { - fn new(init_word: usize, num_words: usize) -> Self { - Bits { bits: vec![init_word; num_words] } - } -} - -pub struct DataflowState -{ - /// All the sets for the analysis. (Factored into its - /// own structure so that we can borrow it mutably - /// on its own separate from other fields.) - pub sets: AllSets, - - /// operator used to initialize, combine, and interpret bits. - operator: O, -} - -pub struct AllSets { - /// Analysis bitwidth for each block. - bits_per_block: usize, - - /// Number of words associated with each block entry - /// equal to bits_per_block / usize::BITS, rounded up. - words_per_block: usize, - - /// For each block, bits generated by executing the statements in - /// the block. (For comparison, the Terminator for each block is - /// handled in a flow-specific manner during propagation.) - gen_sets: Bits, - - /// For each block, bits killed by executing the statements in the - /// block. (For comparison, the Terminator for each block is - /// handled in a flow-specific manner during propagation.) - kill_sets: Bits, - - /// For each block, bits valid on entry to the block. - on_entry_sets: Bits, -} - -pub struct BlockSets<'a> { - on_entry: &'a mut [usize], - gen_set: &'a mut [usize], - kill_set: &'a mut [usize], -} - -impl AllSets { - pub fn bits_per_block(&self) -> usize { self.bits_per_block } - pub fn bytes_per_block(&self) -> usize { (self.bits_per_block + 7) / 8 } - pub fn for_block(&mut self, block_idx: usize) -> BlockSets { - let offset = self.words_per_block * block_idx; - let range = offset..(offset + self.words_per_block); - BlockSets { - on_entry: &mut self.on_entry_sets.bits[range.clone()], - gen_set: &mut self.gen_sets.bits[range.clone()], - kill_set: &mut self.kill_sets.bits[range], - } - } - - fn lookup_set_for<'a>(&self, sets: &'a Bits, block_idx: usize) -> &'a [usize] { - let offset = self.words_per_block * block_idx; - &sets.bits[offset..(offset + self.words_per_block)] - } - pub fn gen_set_for(&self, block_idx: usize) -> &[usize] { - self.lookup_set_for(&self.gen_sets, block_idx) - } - pub fn kill_set_for(&self, block_idx: usize) -> &[usize] { - self.lookup_set_for(&self.kill_sets, block_idx) - } - pub fn on_entry_set_for(&self, block_idx: usize) -> &[usize] { - self.lookup_set_for(&self.on_entry_sets, block_idx) - } -} - -impl DataflowState { - fn each_bit(&self, words: &[usize], mut f: F) - where F: FnMut(usize) { - //! Helper for iterating over the bits in a bitvector. - - for (word_index, &word) in words.iter().enumerate() { - if word != 0 { - let usize_bits: usize = mem::size_of::(); - let base_index = word_index * usize_bits; - for offset in 0..usize_bits { - let bit = 1 << offset; - if (word & bit) != 0 { - // NB: we round up the total number of bits - // that we store in any given bit set so that - // it is an even multiple of usize::BITS. This - // means that there may be some stray bits at - // the end that do not correspond to any - // actual value; that's why we first check - // that we are in range of bits_per_block. - let bit_index = base_index + offset as usize; - if bit_index >= self.sets.bits_per_block() { - return; - } else { - f(bit_index); - } - } - } - } - } - } - - pub fn interpret_set(&self, words: &[usize]) -> Vec<&O::Bit> { - let mut v = Vec::new(); - self.each_bit(words, |i| { - v.push(self.operator.interpret(i)); - }); - v - } -} - -pub trait BitwiseOperator { - /// Joins two predecessor bits together, typically either `|` or `&` - fn join(&self, pred1: usize, pred2: usize) -> usize; -} - -/// Parameterization for the precise form of data flow that is used. -pub trait DataflowOperator : BitwiseOperator { - /// Specifies the initial value for each bit in the `on_entry` set - fn initial_value(&self) -> bool; -} - -pub trait BitDenotation: DataflowOperator { - /// Specifies what is represented by each bit in the dataflow bitvector. - type Bit; - /// Size of each bivector allocated for each block in the analysis. - fn bits_per_block(&self) -> usize; - /// Provides the meaning of each entry in the dataflow bitvector. - /// (Mostly intended for use for better debug instrumentation.) - fn interpret(&self, idx: usize) -> &Self::Bit; -} - -impl DataflowState { - pub fn new(mir: &Mir, denotation: D) -> Self { - let bits_per_block = denotation.bits_per_block(); - let usize_bits = mem::size_of::() * 8; - let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; - let num_blocks = mir.basic_blocks.len(); - let num_words = num_blocks * words_per_block; - - let entry = if denotation.initial_value() { usize::MAX } else {0}; - - let zeroes = Bits::new(0, num_words); - let on_entry = Bits::new(entry, num_words); - - DataflowState { - sets: AllSets { - bits_per_block: bits_per_block, - words_per_block: words_per_block, - gen_sets: zeroes.clone(), - kill_sets: zeroes, - on_entry_sets: on_entry, - }, - operator: denotation, - } - } -} - -impl DataflowState { - /// Propagates the bits of `in_out` into all the successors of `bb`, - /// using bitwise operator denoted by `self.operator`. - /// - /// For most blocks, this is entirely uniform. However, for blocks - /// that end with a call terminator, the effect of the call on the - /// dataflow state may depend on whether the call returned - /// successfully or unwound. To reflect this, the `on_return` - /// callback mutates `in_out` when propagating `in_out` via a call - /// terminator; such mutation is performed *last*, to ensure its - /// side-effects do not leak elsewhere (e.g. into unwind target). - fn propagate_bits_into_graph_successors_of( - &mut self, - in_out: &mut [usize], - changed: &mut bool, - bb: &repr::BasicBlockData, - on_return: OnReturn) where OnReturn: Fn(&D, &mut [usize], &repr::Lvalue) - { - match bb.terminator().kind { - repr::TerminatorKind::Return | - repr::TerminatorKind::Resume => {} - repr::TerminatorKind::Goto { ref target } | - repr::TerminatorKind::Drop { ref target, value: _, unwind: None } => { - self.propagate_bits_into_entry_set_for(in_out, changed, target); - } - repr::TerminatorKind::Drop { ref target, value: _, unwind: Some(ref unwind) } => { - self.propagate_bits_into_entry_set_for(in_out, changed, target); - self.propagate_bits_into_entry_set_for(in_out, changed, unwind); - } - repr::TerminatorKind::If { ref targets, .. } => { - self.propagate_bits_into_entry_set_for(in_out, changed, &targets.0); - self.propagate_bits_into_entry_set_for(in_out, changed, &targets.1); - } - repr::TerminatorKind::Switch { ref targets, .. } | - repr::TerminatorKind::SwitchInt { ref targets, .. } => { - for target in targets { - self.propagate_bits_into_entry_set_for(in_out, changed, target); - } - } - repr::TerminatorKind::Call { ref cleanup, ref destination, func: _, args: _ } => { - if let Some(ref unwind) = *cleanup { - self.propagate_bits_into_entry_set_for(in_out, changed, unwind); - } - if let Some((ref dest_lval, ref dest_bb)) = *destination { - // N.B.: This must be done *last*, after all other - // propagation, as documented in comment above. - on_return(&self.operator, in_out, dest_lval); - self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb); - } - } - } - } - - fn propagate_bits_into_entry_set_for(&mut self, - in_out: &[usize], - changed: &mut bool, - bb: &repr::BasicBlock) { - let entry_set = self.sets.for_block(bb.index()).on_entry; - let set_changed = bitwise(entry_set, in_out, &self.operator); - if set_changed { - *changed = true; - } - } -} - - -impl<'a, 'tcx> DataflowState> { - pub fn new_move_analysis(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { - let move_data = MoveData::gather_moves(mir, tcx); - DataflowState::new(mir, move_data) - } -} - -impl<'tcx> BitwiseOperator for MoveData<'tcx> { - #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { - pred1 | pred2 // moves from both preds are in scope - } -} - -impl<'tcx> DataflowOperator for MoveData<'tcx> { - #[inline] - fn initial_value(&self) -> bool { - false // no loans in scope by default - } -} - -#[inline] -fn bitwise(out_vec: &mut [usize], - in_vec: &[usize], - op: &Op) -> bool { - assert_eq!(out_vec.len(), in_vec.len()); - let mut changed = false; - for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) { - let old_val = *out_elt; - let new_val = op.join(old_val, *in_elt); - *out_elt = new_val; - changed |= old_val != new_val; - } - changed -} - -struct Union; -impl BitwiseOperator for Union { - fn join(&self, a: usize, b: usize) -> usize { a | b } -} -struct Subtract; -impl BitwiseOperator for Subtract { - fn join(&self, a: usize, b: usize) -> usize { a & !b } -} diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs new file mode 100644 index 0000000000000..63c11fb3545b0 --- /dev/null +++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs @@ -0,0 +1,340 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Hook into libgraphviz for rendering dataflow graphs for MIR. + +use syntax::ast::NodeId; +use rustc::mir::repr::{BasicBlock, Mir}; + +use dot; +use dot::IntoCow; + +use std::fmt::Debug; +use std::fs::File; +use std::io; +use std::io::prelude::*; +use std::marker::PhantomData; +use std::mem; +use std::path::Path; + +use super::super::MoveDataParamEnv; +use super::super::MirBorrowckCtxtPreDataflow; +use bitslice::bits_to_string; +use indexed_set::{Idx, IdxSet}; +use super::{BitDenotation, DataflowState}; + +impl DataflowState { + fn each_bit(&self, ctxt: &O::Ctxt, words: &IdxSet, mut f: F) + where F: FnMut(O::Idx) { + //! Helper for iterating over the bits in a bitvector. + + let bits_per_block = self.operator.bits_per_block(ctxt); + let usize_bits: usize = mem::size_of::() * 8; + + for (word_index, &word) in words.words().iter().enumerate() { + if word != 0 { + let base_index = word_index * usize_bits; + for offset in 0..usize_bits { + let bit = 1 << offset; + if (word & bit) != 0 { + // NB: we round up the total number of bits + // that we store in any given bit set so that + // it is an even multiple of usize::BITS. This + // means that there may be some stray bits at + // the end that do not correspond to any + // actual value; that's why we first check + // that we are in range of bits_per_block. + let bit_index = base_index + offset as usize; + if bit_index >= bits_per_block { + return; + } else { + f(O::Idx::new(bit_index)); + } + } + } + } + } + } + + pub fn interpret_set<'c, P>(&self, + ctxt: &'c O::Ctxt, + words: &IdxSet, + render_idx: &P) + -> Vec<&'c Debug> + where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug + { + let mut v = Vec::new(); + self.each_bit(ctxt, words, |i| { + v.push(render_idx(ctxt, i)); + }); + v + } +} + +pub trait MirWithFlowState<'tcx> { + type BD: BitDenotation>; + fn node_id(&self) -> NodeId; + fn mir(&self) -> &Mir<'tcx>; + fn analysis_ctxt(&self) -> &::Ctxt; + fn flow_state(&self) -> &DataflowState; +} + +impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> + where 'a, 'tcx: 'a, BD: BitDenotation> +{ + type BD = BD; + fn node_id(&self) -> NodeId { self.node_id } + fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() } + fn analysis_ctxt(&self) -> &BD::Ctxt { &self.flow_state.ctxt } + fn flow_state(&self) -> &DataflowState { &self.flow_state.flow_state } +} + +struct Graph<'a, 'tcx, MWF:'a, P> where + MWF: MirWithFlowState<'tcx> +{ + mbcx: &'a MWF, + phantom: PhantomData<&'tcx ()>, + render_idx: P, +} + +pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>( + mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>, + path: &Path, + render_idx: P) + -> io::Result<()> + where BD: BitDenotation>, + P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug +{ + let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx }; + let mut v = Vec::new(); + dot::render(&g, &mut v)?; + debug!("print_borrowck_graph_to path: {} node_id: {}", + path.display(), mbcx.node_id); + File::create(path).and_then(|mut f| f.write_all(&v)) +} + +pub type Node = BasicBlock; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Edge { source: BasicBlock, index: usize } + +fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { + let succ_len = mir.basic_block_data(bb).terminator().successors().len(); + (0..succ_len).map(|index| Edge { source: bb, index: index}).collect() +} + +impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> + where MWF: MirWithFlowState<'tcx>, + P: for <'b> Fn(&'b ::Ctxt, + ::Idx) + -> &'b Debug, +{ + type Node = Node; + type Edge = Edge; + fn graph_id(&self) -> dot::Id { + dot::Id::new(format!("graph_for_node_{}", + self.mbcx.node_id())) + .unwrap() + } + + fn node_id(&self, n: &Node) -> dot::Id { + dot::Id::new(format!("bb_{}", n.index())) + .unwrap() + } + + fn node_label(&self, n: &Node) -> dot::LabelText { + // A standard MIR label, as generated by write_node_label, is + // presented in a single column in a table. + // + // The code below does a bunch of formatting work to format a + // node (i.e. MIR basic-block) label with extra + // dataflow-enriched information. In particular, the goal is + // to add extra columns that present the three dataflow + // bitvectors, and the data those bitvectors represent. + // + // It presents it in the following format (where I am + // presenting the table rendering via ASCII art, one line per + // row of the table, and a chunk size of 3 rather than 5): + // + // ------ ----------------------- ------------ -------------------- + // [e1, e3, e4] + // [e8, e9] "= ENTRY:" + // ------ ----------------------- ------------ -------------------- + // Left + // Most + // Column + // Is + // Just + // Normal + // Series + // Of + // MIR + // Stmts + // ------ ----------------------- ------------ -------------------- + // [g1, g4, g5] "= GEN:" + // ------ ----------------------- ------------ -------------------- + // "KILL:" "=" [k1, k3, k8] + // [k9] + // ------ ----------------------- ------------ -------------------- + // + // (In addition, the added dataflow is rendered with a colored + // background just so it will stand out compared to the + // statements.) + let mut v = Vec::new(); + let i = n.index(); + let chunk_size = 5; + const BG_FLOWCONTENT: &'static str = r#"bgcolor="pink""#; + const ALIGN_RIGHT: &'static str = r#"align="right""#; + const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#; + fn chunked_present_left(w: &mut W, + interpreted: &[&Debug], + chunk_size: usize) + -> io::Result<()> + { + // This function may emit a sequence of 's, but it + // always finishes with an (unfinished) + // + // + // Thus, after being called, one should finish both the + // pending as well as the itself. + let mut seen_one = false; + for c in interpreted.chunks(chunk_size) { + if seen_one { + // if not the first row, finish off the previous row + write!(w, "")?; + } + write!(w, "{objs:?}", + bg = BG_FLOWCONTENT, + align = ALIGN_RIGHT, + objs = c)?; + seen_one = true; + } + if !seen_one { + write!(w, "[]", + bg = BG_FLOWCONTENT, + align = ALIGN_RIGHT)?; + } + Ok(()) + } + ::rustc_mir::graphviz::write_node_label( + *n, self.mbcx.mir(), &mut v, 4, + |w| { + let ctxt = self.mbcx.analysis_ctxt(); + let flow = self.mbcx.flow_state(); + let entry_interp = flow.interpret_set(ctxt, + flow.sets.on_entry_set_for(i), + &self.render_idx); + chunked_present_left(w, &entry_interp[..], chunk_size)?; + let bits_per_block = flow.sets.bits_per_block(); + let entry = flow.sets.on_entry_set_for(i); + debug!("entry set for i={i} bits_per_block: {bpb} entry: {e:?} interp: {ei:?}", + i=i, e=entry, bpb=bits_per_block, ei=entry_interp); + write!(w, "= ENTRY:{entrybits:?}\ + ", + bg = BG_FLOWCONTENT, + face = FACE_MONOSPACE, + entrybits=bits_to_string(entry.words(), bits_per_block)) + }, + |w| { + let ctxt = self.mbcx.analysis_ctxt(); + let flow = self.mbcx.flow_state(); + let gen_interp = + flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx); + let kill_interp = + flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx); + chunked_present_left(w, &gen_interp[..], chunk_size)?; + let bits_per_block = flow.sets.bits_per_block(); + { + let gen = flow.sets.gen_set_for(i); + debug!("gen set for i={i} bits_per_block: {bpb} gen: {g:?} interp: {gi:?}", + i=i, g=gen, bpb=bits_per_block, gi=gen_interp); + write!(w, " = GEN:{genbits:?}\ + ", + bg = BG_FLOWCONTENT, + face = FACE_MONOSPACE, + genbits=bits_to_string(gen.words(), bits_per_block))?; + } + + { + let kill = flow.sets.kill_set_for(i); + debug!("kill set for i={i} bits_per_block: {bpb} kill: {k:?} interp: {ki:?}", + i=i, k=kill, bpb=bits_per_block, ki=kill_interp); + write!(w, "KILL:\ + {killbits:?}", + bg = BG_FLOWCONTENT, + align = ALIGN_RIGHT, + face = FACE_MONOSPACE, + killbits=bits_to_string(kill.words(), bits_per_block))?; + } + + // (chunked_present_right) + let mut seen_one = false; + for k in kill_interp.chunks(chunk_size) { + if !seen_one { + // continuation of row; this is fourth + write!(w, "= {kill:?}", + bg = BG_FLOWCONTENT, + kill=k)?; + } else { + // new row, with indent of three 's + write!(w, "{kill:?}", + bg = BG_FLOWCONTENT, + kill=k)?; + } + seen_one = true; + } + if !seen_one { + write!(w, "= []", + bg = BG_FLOWCONTENT)?; + } + + Ok(()) + }) + .unwrap(); + dot::LabelText::html(String::from_utf8(v).unwrap()) + } + + fn node_shape(&self, _n: &Node) -> Option { + Some(dot::LabelText::label("none")) + } +} + +impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> + where MWF: MirWithFlowState<'tcx> +{ + type Node = Node; + type Edge = Edge; + fn nodes(&self) -> dot::Nodes { + self.mbcx.mir().all_basic_blocks().into_cow() + } + + fn edges(&self) -> dot::Edges { + let mir = self.mbcx.mir(); + let blocks = mir.all_basic_blocks(); + // base initial capacity on assumption every block has at + // least one outgoing edge (Which should be true for all + // blocks but one, the exit-block). + let mut edges = Vec::with_capacity(blocks.len()); + for bb in blocks { + let outgoing = outgoing(mir, bb); + edges.extend(outgoing.into_iter()); + } + edges.into_cow() + } + + fn source(&self, edge: &Edge) -> Node { + edge.source + } + + fn target(&self, edge: &Edge) -> Node { + let mir = self.mbcx.mir(); + mir.basic_block_data(edge.source).terminator().successors()[edge.index] + } +} diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs new file mode 100644 index 0000000000000..e3435ed990506 --- /dev/null +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -0,0 +1,571 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::ty::TyCtxt; +use rustc::mir::repr::{self, Mir}; + +use super::super::gather_moves::{Location}; +use super::super::gather_moves::{MoveOutIndex, MovePathIndex}; +use super::super::MoveDataParamEnv; +use super::super::DropFlagState; +use super::super::drop_flag_effects_for_function_entry; +use super::super::drop_flag_effects_for_location; +use super::super::on_all_children_bits; + +use super::{BitDenotation, BlockSets, DataflowOperator}; + +use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. +use bitslice::{BitwiseOperator}; +use indexed_set::{Idx, IdxSet}; + +// Dataflow analyses are built upon some interpretation of the +// bitvectors attached to each basic block, represented via a +// zero-sized structure. + +/// `MaybeInitializedLvals` tracks all l-values that might be +/// initialized upon reaching a particular point in the control flow +/// for a function. +/// +/// For example, in code like the following, we have corresponding +/// dataflow information shown in the right-hand comments. +/// +/// ```rust +/// struct S; +/// fn foo(pred: bool) { // maybe-init: +/// // {} +/// let a = S; let b = S; let c; let d; // {a, b} +/// +/// if pred { +/// drop(a); // { b} +/// b = S; // { b} +/// +/// } else { +/// drop(b); // {a} +/// d = S; // {a, d} +/// +/// } // {a, b, d} +/// +/// c = S; // {a, b, c, d} +/// } +/// ``` +/// +/// To determine whether an l-value *must* be initialized at a +/// particular control-flow point, one can take the set-difference +/// between this data and the data from `MaybeUninitializedLvals` at the +/// corresponding control-flow point. +/// +/// Similarly, at a given `drop` statement, the set-intersection +/// between this data and `MaybeUninitializedLvals` yields the set of +/// l-values that would require a dynamic drop-flag at that statement. +pub struct MaybeInitializedLvals<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, +} + +impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + MaybeInitializedLvals { tcx: tcx, mir: mir } + } +} + +/// `MaybeUninitializedLvals` tracks all l-values that might be +/// uninitialized upon reaching a particular point in the control flow +/// for a function. +/// +/// For example, in code like the following, we have corresponding +/// dataflow information shown in the right-hand comments. +/// +/// ```rust +/// struct S; +/// fn foo(pred: bool) { // maybe-uninit: +/// // {a, b, c, d} +/// let a = S; let b = S; let c; let d; // { c, d} +/// +/// if pred { +/// drop(a); // {a, c, d} +/// b = S; // {a, c, d} +/// +/// } else { +/// drop(b); // { b, c, d} +/// d = S; // { b, c } +/// +/// } // {a, b, c, d} +/// +/// c = S; // {a, b, d} +/// } +/// ``` +/// +/// To determine whether an l-value *must* be uninitialized at a +/// particular control-flow point, one can take the set-difference +/// between this data and the data from `MaybeInitializedLvals` at the +/// corresponding control-flow point. +/// +/// Similarly, at a given `drop` statement, the set-intersection +/// between this data and `MaybeInitializedLvals` yields the set of +/// l-values that would require a dynamic drop-flag at that statement. +pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, +} + +impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + MaybeUninitializedLvals { tcx: tcx, mir: mir } + } +} + +/// `DefinitelyInitializedLvals` tracks all l-values that are definitely +/// initialized upon reaching a particular point in the control flow +/// for a function. +/// +/// FIXME: Note that once flow-analysis is complete, this should be +/// the set-complement of MaybeUninitializedLvals; thus we can get rid +/// of one or the other of these two. I'm inclined to get rid of +/// MaybeUninitializedLvals, simply because the sets will tend to be +/// smaller in this analysis and thus easier for humans to process +/// when debugging. +/// +/// For example, in code like the following, we have corresponding +/// dataflow information shown in the right-hand comments. +/// +/// ```rust +/// struct S; +/// fn foo(pred: bool) { // definite-init: +/// // { } +/// let a = S; let b = S; let c; let d; // {a, b } +/// +/// if pred { +/// drop(a); // { b, } +/// b = S; // { b, } +/// +/// } else { +/// drop(b); // {a, } +/// d = S; // {a, d} +/// +/// } // { } +/// +/// c = S; // { c } +/// } +/// ``` +/// +/// To determine whether an l-value *may* be uninitialized at a +/// particular control-flow point, one can take the set-complement +/// of this data. +/// +/// Similarly, at a given `drop` statement, the set-difference between +/// this data and `MaybeInitializedLvals` yields the set of l-values +/// that would require a dynamic drop-flag at that statement. +pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, +} + +impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + DefinitelyInitializedLvals { tcx: tcx, mir: mir } + } +} + +/// `MovingOutStatements` tracks the statements that perform moves out +/// of particular l-values. More precisely, it tracks whether the +/// *effect* of such moves (namely, the uninitialization of the +/// l-value in question) can reach some point in the control-flow of +/// the function, or if that effect is "killed" by some intervening +/// operation reinitializing that l-value. +/// +/// The resulting dataflow is a more enriched version of +/// `MaybeUninitializedLvals`. Both structures on their own only tell +/// you if an l-value *might* be uninitialized at a given point in the +/// control flow. But `MovingOutStatements` also includes the added +/// data of *which* particular statement causing the deinitialization +/// that the borrow checker's error meessage may need to report. +#[allow(dead_code)] +pub struct MovingOutStatements<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, +} + +impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> { + fn update_bits(sets: &mut BlockSets, path: MovePathIndex, + state: DropFlagState) + { + match state { + DropFlagState::Absent => sets.kill(&path), + DropFlagState::Present => sets.gen(&path), + } + } +} + +impl<'a, 'tcx> MaybeUninitializedLvals<'a, 'tcx> { + fn update_bits(sets: &mut BlockSets, path: MovePathIndex, + state: DropFlagState) + { + match state { + DropFlagState::Absent => sets.gen(&path), + DropFlagState::Present => sets.kill(&path), + } + } +} + +impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> { + fn update_bits(sets: &mut BlockSets, path: MovePathIndex, + state: DropFlagState) + { + match state { + DropFlagState::Absent => sets.kill(&path), + DropFlagState::Present => sets.gen(&path), + } + } +} + +impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { + type Idx = MovePathIndex; + type Ctxt = MoveDataParamEnv<'tcx>; + fn name() -> &'static str { "maybe_init" } + fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { + ctxt.move_data.move_paths.len() + } + + fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) + { + drop_flag_effects_for_function_entry( + self.tcx, self.mir, ctxt, + |path, s| { + assert!(s == DropFlagState::Present); + sets.on_entry.add(&path); + }); + } + + fn statement_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: idx }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn terminator_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + statements_len: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: statements_len }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn propagate_call_return(&self, + ctxt: &Self::Ctxt, + in_out: &mut IdxSet, + _call_bb: repr::BasicBlock, + _dest_bb: repr::BasicBlock, + dest_lval: &repr::Lvalue) { + // when a call returns successfully, that means we need to set + // the bits for that dest_lval to 1 (initialized). + let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval); + on_all_children_bits(self.tcx, self.mir, &ctxt.move_data, + move_path_index, + |mpi| { in_out.add(&mpi); }); + } +} + +impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { + type Idx = MovePathIndex; + type Ctxt = MoveDataParamEnv<'tcx>; + fn name() -> &'static str { "maybe_uninit" } + fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { + ctxt.move_data.move_paths.len() + } + + // sets on_entry bits for Arg lvalues + fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) { + // set all bits to 1 (uninit) before gathering counterevidence + for e in sets.on_entry.words_mut() { *e = !0; } + + drop_flag_effects_for_function_entry( + self.tcx, self.mir, ctxt, + |path, s| { + assert!(s == DropFlagState::Present); + sets.on_entry.remove(&path); + }); + } + + fn statement_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: idx }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn terminator_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + statements_len: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: statements_len }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn propagate_call_return(&self, + ctxt: &Self::Ctxt, + in_out: &mut IdxSet, + _call_bb: repr::BasicBlock, + _dest_bb: repr::BasicBlock, + dest_lval: &repr::Lvalue) { + // when a call returns successfully, that means we need to set + // the bits for that dest_lval to 1 (initialized). + let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval); + on_all_children_bits(self.tcx, self.mir, &ctxt.move_data, + move_path_index, + |mpi| { in_out.remove(&mpi); }); + } +} + +impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { + type Idx = MovePathIndex; + type Ctxt = MoveDataParamEnv<'tcx>; + fn name() -> &'static str { "definite_init" } + fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { + ctxt.move_data.move_paths.len() + } + + // sets on_entry bits for Arg lvalues + fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets) { + for e in sets.on_entry.words_mut() { *e = 0; } + + drop_flag_effects_for_function_entry( + self.tcx, self.mir, ctxt, + |path, s| { + assert!(s == DropFlagState::Present); + sets.on_entry.add(&path); + }); + } + + fn statement_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: idx }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn terminator_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + statements_len: usize) + { + drop_flag_effects_for_location( + self.tcx, self.mir, ctxt, + Location { block: bb, index: statements_len }, + |path, s| Self::update_bits(sets, path, s) + ) + } + + fn propagate_call_return(&self, + ctxt: &Self::Ctxt, + in_out: &mut IdxSet, + _call_bb: repr::BasicBlock, + _dest_bb: repr::BasicBlock, + dest_lval: &repr::Lvalue) { + // when a call returns successfully, that means we need to set + // the bits for that dest_lval to 1 (initialized). + let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval); + on_all_children_bits(self.tcx, self.mir, &ctxt.move_data, + move_path_index, + |mpi| { in_out.add(&mpi); }); + } +} + +impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { + type Idx = MoveOutIndex; + type Ctxt = MoveDataParamEnv<'tcx>; + fn name() -> &'static str { "moving_out" } + fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize { + ctxt.move_data.moves.len() + } + + fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets) { + // no move-statements have been executed prior to function + // execution, so this method has no effect on `_sets`. + } + fn statement_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx: usize) { + let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data); + let stmt = &mir.basic_block_data(bb).statements[idx]; + let loc_map = &move_data.loc_map; + let path_map = &move_data.path_map; + let rev_lookup = &move_data.rev_lookup; + + let loc = Location { block: bb, index: idx }; + debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", + stmt, loc, &loc_map[loc]); + for move_index in &loc_map[loc] { + // Every path deinitialized by a *particular move* + // has corresponding bit, "gen'ed" (i.e. set) + // here, in dataflow vector + zero_to_one(sets.gen_set.words_mut(), *move_index); + } + let bits_per_block = self.bits_per_block(ctxt); + match stmt.kind { + repr::StatementKind::Assign(ref lvalue, _) => { + // assigning into this `lvalue` kills all + // MoveOuts from it, and *also* all MoveOuts + // for children and associated fragment sets. + let move_path_index = rev_lookup.find(lvalue); + on_all_children_bits(tcx, + mir, + move_data, + move_path_index, + |mpi| for moi in &path_map[mpi] { + assert!(moi.idx() < bits_per_block); + sets.kill_set.add(&moi); + }); + } + } + } + + fn terminator_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + statements_len: usize) + { + let (mir, move_data) = (self.mir, &ctxt.move_data); + let term = mir.basic_block_data(bb).terminator.as_ref().unwrap(); + let loc_map = &move_data.loc_map; + let loc = Location { block: bb, index: statements_len }; + debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", + term, loc, &loc_map[loc]); + let bits_per_block = self.bits_per_block(ctxt); + for move_index in &loc_map[loc] { + assert!(move_index.idx() < bits_per_block); + zero_to_one(sets.gen_set.words_mut(), *move_index); + } + } + + fn propagate_call_return(&self, + ctxt: &Self::Ctxt, + in_out: &mut IdxSet, + _call_bb: repr::BasicBlock, + _dest_bb: repr::BasicBlock, + dest_lval: &repr::Lvalue) { + let move_data = &ctxt.move_data; + let move_path_index = move_data.rev_lookup.find(dest_lval); + let bits_per_block = self.bits_per_block(ctxt); + + let path_map = &move_data.path_map; + on_all_children_bits(self.tcx, + self.mir, + move_data, + move_path_index, + |mpi| for moi in &path_map[mpi] { + assert!(moi.idx() < bits_per_block); + in_out.remove(&moi); + }); + } +} + +fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) { + let retval = bitvec.set_bit(move_index.idx()); + assert!(retval); +} + +impl<'a, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 | pred2 // moves from both preds are in scope + } +} + +impl<'a, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 | pred2 // "maybe" means we union effects of both preds + } +} + +impl<'a, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 | pred2 // "maybe" means we union effects of both preds + } +} + +impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 & pred2 // "definitely" means we intersect effects of both preds + } +} + +// The way that dataflow fixed point iteration works, you want to +// start at bottom and work your way to a fixed point. Control-flow +// merges will apply the `join` operator to each block entry's current +// state (which starts at that bottom value). +// +// This means, for propagation across the graph, that you either want +// to start at all-zeroes and then use Union as your merge when +// propagating, or you start at all-ones and then use Intersect as +// your merge when propagating. + +impl<'a, 'tcx> DataflowOperator for MovingOutStatements<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + false // bottom = no loans in scope by default + } +} + +impl<'a, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + false // bottom = uninitialized + } +} + +impl<'a, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + false // bottom = initialized (start_block_effect counters this at outset) + } +} + +impl<'a, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + true // bottom = initialized (start_block_effect counters this at outset) + } +} diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs new file mode 100644 index 0000000000000..b46b6c368a053 --- /dev/null +++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs @@ -0,0 +1,491 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::ty::TyCtxt; +use rustc::mir::repr::{self, Mir}; + +use std::fmt::Debug; +use std::io; +use std::mem; +use std::path::PathBuf; +use std::usize; + +use super::MirBorrowckCtxtPreDataflow; +use super::MoveDataParamEnv; + +use bitslice::{bitwise, BitwiseOperator}; +use indexed_set::{Idx, IdxSet, IdxSetBuf}; + +pub use self::sanity_check::sanity_check_via_rustc_peek; +pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; +pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; + +mod graphviz; +mod sanity_check; +mod impls; + +pub trait Dataflow { + fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug; +} + +impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> + where BD: BitDenotation> + DataflowOperator +{ + fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug { + self.flow_state.build_sets(); + self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap(); + self.flow_state.propagate(); + self.post_dataflow_instrumentation(|c,i| p(c,i)).unwrap(); + } +} + +struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> + where O: 'b + BitDenotation, O::Ctxt: 'a +{ + builder: &'b mut DataflowAnalysis<'a, 'tcx, O>, + changed: bool, +} + +impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> + where BD: BitDenotation + DataflowOperator +{ + fn propagate(&mut self) { + let mut temp = IdxSetBuf::new_empty(self.flow_state.sets.bits_per_block); + let mut propcx = PropagationContext { + builder: self, + changed: true, + }; + while propcx.changed { + propcx.changed = false; + propcx.reset(&mut temp); + propcx.walk_cfg(&mut temp); + } + } + + fn build_sets(&mut self) { + // First we need to build the entry-, gen- and kill-sets. The + // gather_moves information provides a high-level mapping from + // mir-locations to the MoveOuts (and those correspond + // directly to gen-sets here). But we still need to figure out + // the kill-sets. + + { + let sets = &mut self.flow_state.sets.for_block(repr::START_BLOCK.index()); + self.flow_state.operator.start_block_effect(&self.ctxt, sets); + } + + for bb in self.mir.all_basic_blocks() { + let &repr::BasicBlockData { ref statements, + ref terminator, + is_cleanup: _ } = + self.mir.basic_block_data(bb); + + let sets = &mut self.flow_state.sets.for_block(bb.index()); + for j_stmt in 0..statements.len() { + self.flow_state.operator.statement_effect(&self.ctxt, sets, bb, j_stmt); + } + + if terminator.is_some() { + let stmts_len = statements.len(); + self.flow_state.operator.terminator_effect(&self.ctxt, sets, bb, stmts_len); + } + } + } +} + +impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> + where BD: BitDenotation + DataflowOperator +{ + fn reset(&mut self, bits: &mut IdxSet) { + let e = if BD::bottom_value() {!0} else {0}; + for b in bits.words_mut() { + *b = e; + } + } + + fn walk_cfg(&mut self, in_out: &mut IdxSet) { + let mir = self.builder.mir; + for (bb_idx, bb_data) in mir.basic_blocks.iter().enumerate() { + let builder = &mut self.builder; + { + let sets = builder.flow_state.sets.for_block(bb_idx); + debug_assert!(in_out.words().len() == sets.on_entry.words().len()); + in_out.clone_from(sets.on_entry); + in_out.union(sets.gen_set); + in_out.subtract(sets.kill_set); + } + builder.propagate_bits_into_graph_successors_of( + in_out, &mut self.changed, (repr::BasicBlock::new(bb_idx), bb_data)); + } + } +} + +fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { + format!("{}_{}", context, prepost); + let mut path = PathBuf::from(path); + let new_file_name = { + let orig_file_name = path.file_name().unwrap().to_str().unwrap(); + format!("{}_{}", context, orig_file_name) + }; + path.set_file_name(new_file_name); + path +} + +impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> + where BD: BitDenotation> +{ + fn pre_dataflow_instrumentation

(&self, p: P) -> io::Result<()> + where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug + { + if let Some(ref path_str) = self.print_preflow_to { + let path = dataflow_path(BD::name(), "preflow", path_str); + graphviz::print_borrowck_graph_to(self, &path, p) + } else { + Ok(()) + } + } + + fn post_dataflow_instrumentation

(&self, p: P) -> io::Result<()> + where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug + { + if let Some(ref path_str) = self.print_postflow_to { + let path = dataflow_path(BD::name(), "postflow", path_str); + graphviz::print_borrowck_graph_to(self, &path, p) + } else{ + Ok(()) + } + } +} + +/// Maps each block to a set of bits +#[derive(Debug)] +struct Bits { + bits: IdxSetBuf, +} + +impl Clone for Bits { + fn clone(&self) -> Self { Bits { bits: self.bits.clone() } } +} + +impl Bits { + fn new(bits: IdxSetBuf) -> Self { + Bits { bits: bits } + } +} + +pub struct DataflowAnalysis<'a, 'tcx: 'a, O> + where O: BitDenotation, O::Ctxt: 'a +{ + flow_state: DataflowState, + mir: &'a Mir<'tcx>, + ctxt: &'a O::Ctxt, +} + +impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> + where O: BitDenotation +{ + pub fn results(self) -> DataflowResults { + DataflowResults(self.flow_state) + } + + pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } +} + +pub struct DataflowResults(DataflowState) where O: BitDenotation; + +// FIXME: This type shouldn't be public, but the graphviz::MirWithFlowState trait +// references it in a method signature. Look into using `pub(crate)` to address this. +pub struct DataflowState +{ + /// All the sets for the analysis. (Factored into its + /// own structure so that we can borrow it mutably + /// on its own separate from other fields.) + pub sets: AllSets, + + /// operator used to initialize, combine, and interpret bits. + operator: O, +} + +#[derive(Debug)] +pub struct AllSets { + /// Analysis bitwidth for each block. + bits_per_block: usize, + + /// Number of words associated with each block entry + /// equal to bits_per_block / usize::BITS, rounded up. + words_per_block: usize, + + /// For each block, bits generated by executing the statements in + /// the block. (For comparison, the Terminator for each block is + /// handled in a flow-specific manner during propagation.) + gen_sets: Bits, + + /// For each block, bits killed by executing the statements in the + /// block. (For comparison, the Terminator for each block is + /// handled in a flow-specific manner during propagation.) + kill_sets: Bits, + + /// For each block, bits valid on entry to the block. + on_entry_sets: Bits, +} + +pub struct BlockSets<'a, E: Idx> { + on_entry: &'a mut IdxSet, + gen_set: &'a mut IdxSet, + kill_set: &'a mut IdxSet, +} + +impl<'a, E:Idx> BlockSets<'a, E> { + fn gen(&mut self, e: &E) { + self.gen_set.add(e); + self.kill_set.remove(e); + } + fn kill(&mut self, e: &E) { + self.gen_set.remove(e); + self.kill_set.add(e); + } +} + +impl AllSets { + pub fn bits_per_block(&self) -> usize { self.bits_per_block } + pub fn for_block(&mut self, block_idx: usize) -> BlockSets { + let offset = self.words_per_block * block_idx; + let range = E::new(offset)..E::new(offset + self.words_per_block); + BlockSets { + on_entry: self.on_entry_sets.bits.range_mut(&range), + gen_set: self.gen_sets.bits.range_mut(&range), + kill_set: self.kill_sets.bits.range_mut(&range), + } + } + + fn lookup_set_for<'a>(&self, sets: &'a Bits, block_idx: usize) -> &'a IdxSet { + let offset = self.words_per_block * block_idx; + let range = E::new(offset)..E::new(offset + self.words_per_block); + sets.bits.range(&range) + } + pub fn gen_set_for(&self, block_idx: usize) -> &IdxSet { + self.lookup_set_for(&self.gen_sets, block_idx) + } + pub fn kill_set_for(&self, block_idx: usize) -> &IdxSet { + self.lookup_set_for(&self.kill_sets, block_idx) + } + pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet { + self.lookup_set_for(&self.on_entry_sets, block_idx) + } +} + +/// Parameterization for the precise form of data flow that is used. +pub trait DataflowOperator: BitwiseOperator { + /// Specifies the initial value for each bit in the `on_entry` set + fn bottom_value() -> bool; +} + +pub trait BitDenotation { + /// Specifies what index type is used to access the bitvector. + type Idx: Idx; + + /// Specifies what, if any, separate context needs to be supplied for methods below. + type Ctxt; + + /// A name describing the dataflow analysis that this + /// BitDenotation is supporting. The name should be something + /// suitable for plugging in as part of a filename e.g. avoid + /// space-characters or other things that tend to look bad on a + /// file system, like slashes or periods. It is also better for + /// the name to be reasonably short, again because it will be + /// plugged into a filename. + fn name() -> &'static str; + + /// Size of each bitvector allocated for each block in the analysis. + fn bits_per_block(&self, &Self::Ctxt) -> usize; + + /// Mutates the block-sets (the flow sets for the given + /// basic block) according to the effects that have been + /// established *prior* to entering the start block. + /// + /// (For example, establishing the call arguments.) + /// + /// (Typically this should only modify `sets.on_entry`, since the + /// gen and kill sets should reflect the effects of *executing* + /// the start block itself.) + fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets); + + /// Mutates the block-sets (the flow sets for the given + /// basic block) according to the effects of evaluating statement. + /// + /// This is used, in particular, for building up the + /// "transfer-function" represnting the overall-effect of the + /// block, represented via GEN and KILL sets. + /// + /// The statement is identified as `bb_data[idx_stmt]`, where + /// `bb_data` is the sequence of statements identifed by `bb` in + /// the MIR. + fn statement_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx_stmt: usize); + + /// Mutates the block-sets (the flow sets for the given + /// basic block) according to the effects of evaluating + /// the terminator. + /// + /// This is used, in particular, for building up the + /// "transfer-function" represnting the overall-effect of the + /// block, represented via GEN and KILL sets. + /// + /// The effects applied here cannot depend on which branch the + /// terminator took. + fn terminator_effect(&self, + ctxt: &Self::Ctxt, + sets: &mut BlockSets, + bb: repr::BasicBlock, + idx_term: usize); + + /// Mutates the block-sets according to the (flow-dependent) + /// effect of a successful return from a Call terminator. + /// + /// If basic-block BB_x ends with a call-instruction that, upon + /// successful return, flows to BB_y, then this method will be + /// called on the exit flow-state of BB_x in order to set up the + /// entry flow-state of BB_y. + /// + /// This is used, in particular, as a special case during the + /// "propagate" loop where all of the basic blocks are repeatedly + /// visited. Since the effects of a Call terminator are + /// flow-dependent, the current MIR cannot encode them via just + /// GEN and KILL sets attached to the block, and so instead we add + /// this extra machinery to represent the flow-dependent effect. + /// + /// FIXME: Right now this is a bit of a wart in the API. It might + /// be better to represent this as an additional gen- and + /// kill-sets associated with each edge coming out of the basic + /// block. + fn propagate_call_return(&self, + ctxt: &Self::Ctxt, + in_out: &mut IdxSet, + call_bb: repr::BasicBlock, + dest_bb: repr::BasicBlock, + dest_lval: &repr::Lvalue); +} + +impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> + where D: BitDenotation + DataflowOperator +{ + pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + ctxt: &'a D::Ctxt, + denotation: D) -> Self { + let bits_per_block = denotation.bits_per_block(&ctxt); + let usize_bits = mem::size_of::() * 8; + let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; + + // (now rounded up to multiple of word size) + let bits_per_block = words_per_block * usize_bits; + + let num_blocks = mir.basic_blocks.len(); + let num_overall = num_blocks * bits_per_block; + + let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); + let on_entry = Bits::new(if D::bottom_value() { + IdxSetBuf::new_filled(num_overall) + } else { + IdxSetBuf::new_empty(num_overall) + }); + + DataflowAnalysis { + ctxt: ctxt, + mir: mir, + flow_state: DataflowState { + sets: AllSets { + bits_per_block: bits_per_block, + words_per_block: words_per_block, + gen_sets: zeroes.clone(), + kill_sets: zeroes, + on_entry_sets: on_entry, + }, + operator: denotation, + }, + } + + } +} + +impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> + where D: BitDenotation + DataflowOperator +{ + /// Propagates the bits of `in_out` into all the successors of `bb`, + /// using bitwise operator denoted by `self.operator`. + /// + /// For most blocks, this is entirely uniform. However, for blocks + /// that end with a call terminator, the effect of the call on the + /// dataflow state may depend on whether the call returned + /// successfully or unwound. + /// + /// To reflect this, the `propagate_call_return` method of the + /// `BitDenotation` mutates `in_out` when propagating `in_out` via + /// a call terminator; such mutation is performed *last*, to + /// ensure its side-effects do not leak elsewhere (e.g. into + /// unwind target). + fn propagate_bits_into_graph_successors_of( + &mut self, + in_out: &mut IdxSet, + changed: &mut bool, + (bb, bb_data): (repr::BasicBlock, &repr::BasicBlockData)) + { + match bb_data.terminator().kind { + repr::TerminatorKind::Return | + repr::TerminatorKind::Resume => {} + repr::TerminatorKind::Goto { ref target } | + repr::TerminatorKind::Drop { ref target, value: _, unwind: None } => { + self.propagate_bits_into_entry_set_for(in_out, changed, target); + } + repr::TerminatorKind::Drop { ref target, value: _, unwind: Some(ref unwind) } => { + self.propagate_bits_into_entry_set_for(in_out, changed, target); + self.propagate_bits_into_entry_set_for(in_out, changed, unwind); + } + repr::TerminatorKind::If { ref targets, .. } => { + self.propagate_bits_into_entry_set_for(in_out, changed, &targets.0); + self.propagate_bits_into_entry_set_for(in_out, changed, &targets.1); + } + repr::TerminatorKind::Switch { ref targets, .. } | + repr::TerminatorKind::SwitchInt { ref targets, .. } => { + for target in targets { + self.propagate_bits_into_entry_set_for(in_out, changed, target); + } + } + repr::TerminatorKind::Call { ref cleanup, ref destination, func: _, args: _ } => { + if let Some(ref unwind) = *cleanup { + self.propagate_bits_into_entry_set_for(in_out, changed, unwind); + } + if let Some((ref dest_lval, ref dest_bb)) = *destination { + // N.B.: This must be done *last*, after all other + // propagation, as documented in comment above. + self.flow_state.operator.propagate_call_return( + &self.ctxt, in_out, bb, *dest_bb, dest_lval); + self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb); + } + } + } + } + + fn propagate_bits_into_entry_set_for(&mut self, + in_out: &IdxSet, + changed: &mut bool, + bb: &repr::BasicBlock) { + let entry_set = self.flow_state.sets.for_block(bb.index()).on_entry; + let set_changed = bitwise(entry_set.words_mut(), + in_out.words(), + &self.flow_state.operator); + if set_changed { + *changed = true; + } + } +} diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs new file mode 100644 index 0000000000000..74dc921b0bba5 --- /dev/null +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -0,0 +1,172 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::abi::{Abi}; +use syntax::ast; +use syntax::codemap::Span; + +use rustc::ty::{self, TyCtxt}; +use rustc::mir::repr::{self, Mir}; + +use super::super::gather_moves::{MovePathIndex}; +use super::super::MoveDataParamEnv; +use super::BitDenotation; +use super::DataflowResults; + +/// This function scans `mir` for all calls to the intrinsic +/// `rustc_peek` that have the expression form `rustc_peek(&expr)`. +/// +/// For each such call, determines what the dataflow bit-state is for +/// the L-value corresponding to `expr`; if the bit-state is a 1, then +/// that call to `rustc_peek` is ignored by the sanity check. If the +/// bit-state is a 0, then this pass emits a error message saying +/// "rustc_peek: bit not set". +/// +/// The intention is that one can write unit tests for dataflow by +/// putting code into a compile-fail test and using `rustc_peek` to +/// make observations about the results of dataflow static analyses. +/// +/// (If there are any calls to `rustc_peek` that do not match the +/// expression form above, then that emits an error as well, but those +/// errors are not intended to be used for unit tests.) +pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + id: ast::NodeId, + _attributes: &[ast::Attribute], + flow_ctxt: &O::Ctxt, + results: &DataflowResults) + where O: BitDenotation, Idx=MovePathIndex> +{ + debug!("sanity_check_via_rustc_peek id: {:?}", id); + // FIXME: this is not DRY. Figure out way to abstract this and + // `dataflow::build_sets`. (But note it is doing non-standard + // stuff, so such generalization may not be realistic.) + + let blocks = mir.all_basic_blocks(); + 'next_block: for bb in blocks { + each_block(tcx, mir, flow_ctxt, results, bb); + } +} + +fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + ctxt: &O::Ctxt, + results: &DataflowResults, + bb: repr::BasicBlock) where + O: BitDenotation, Idx=MovePathIndex> +{ + let move_data = &ctxt.move_data; + let bb_data = mir.basic_block_data(bb); + let &repr::BasicBlockData { ref statements, + ref terminator, + is_cleanup: _ } = bb_data; + + let (args, span) = match is_rustc_peek(tcx, terminator) { + Some(args_and_span) => args_and_span, + None => return, + }; + assert!(args.len() == 1); + let peek_arg_lval = match args[0] { + repr::Operand::Consume(ref lval @ repr::Lvalue::Temp(_)) => { + lval + } + repr::Operand::Consume(_) | + repr::Operand::Constant(_) => { + tcx.sess.diagnostic().span_err( + span, "dataflow::sanity_check cannot feed a non-temp to rustc_peek."); + return; + } + }; + + let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned(); + let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned(); + let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned(); + + // Emulate effect of all statements in the block up to (but not + // including) the borrow within `peek_arg_lval`. Do *not* include + // call to `peek_arg_lval` itself (since we are peeking the state + // of the argument at time immediate preceding Call to + // `rustc_peek`). + + let mut sets = super::BlockSets { on_entry: &mut entry, + gen_set: &mut gen, + kill_set: &mut kill }; + + for (j, stmt) in statements.iter().enumerate() { + debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt); + let (lvalue, rvalue) = match stmt.kind { + repr::StatementKind::Assign(ref lvalue, ref rvalue) => { + (lvalue, rvalue) + } + }; + + if lvalue == peek_arg_lval { + if let repr::Rvalue::Ref(_, + repr::BorrowKind::Shared, + ref peeking_at_lval) = *rvalue { + // Okay, our search is over. + let peek_mpi = move_data.rev_lookup.find(peeking_at_lval); + let bit_state = sets.on_entry.contains(&peek_mpi); + debug!("rustc_peek({:?} = &{:?}) bit_state: {}", + lvalue, peeking_at_lval, bit_state); + if !bit_state { + tcx.sess.span_err(span, &format!("rustc_peek: bit not set")); + } + return; + } else { + // Our search should have been over, but the input + // does not match expectations of `rustc_peek` for + // this sanity_check. + let msg = &format!("rustc_peek: argument expression \ + must be immediate borrow of form `&expr`"); + tcx.sess.span_err(span, msg); + } + } + + let lhs_mpi = move_data.rev_lookup.find(lvalue); + + debug!("rustc_peek: computing effect on lvalue: {:?} ({:?}) in stmt: {:?}", + lvalue, lhs_mpi, stmt); + // reset GEN and KILL sets before emulating their effect. + for e in sets.gen_set.words_mut() { *e = 0; } + for e in sets.kill_set.words_mut() { *e = 0; } + results.0.operator.statement_effect(ctxt, &mut sets, bb, j); + sets.on_entry.union(sets.gen_set); + sets.on_entry.subtract(sets.kill_set); + } + + tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \ + anticipated pattern; note that \ + rustc_peek expects input of \ + form `&expr`")); +} + +fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + terminator: &'a Option>) + -> Option<(&'a [repr::Operand<'tcx>], Span)> { + if let Some(repr::Terminator { ref kind, span, .. }) = *terminator { + if let repr::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind + { + if let repr::Operand::Constant(ref func) = *oper + { + if let ty::TyFnDef(def_id, _, &ty::BareFnTy { abi, .. }) = func.ty.sty + { + let name = tcx.item_name(def_id); + if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { + if name.as_str() == "rustc_peek" { + return Some((args, span)); + } + } + } + } + } + } + return None; +} diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index bf3d671bdb5af..48511cd5ebc91 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -9,7 +9,7 @@ // except according to those terms. -use rustc::ty::TyCtxt; +use rustc::ty::{FnOutput, TyCtxt}; use rustc::mir::repr::*; use rustc::util::nodemap::FnvHashMap; @@ -19,8 +19,8 @@ use std::fmt; use std::iter; use std::ops::Index; -use super::dataflow::BitDenotation; use super::abs_domain::{AbstractElem, Lift}; +use indexed_set::{Idx}; // This submodule holds some newtype'd Index wrappers that are using // NonZero to ensure that Option occupies only a single word. @@ -29,17 +29,21 @@ use super::abs_domain::{AbstractElem, Lift}; // (which is likely to yield a subtle off-by-one error). mod indexes { use core::nonzero::NonZero; + use indexed_set::Idx; macro_rules! new_index { ($Index:ident) => { - #[derive(Copy, Clone, PartialEq, Eq, Debug)] + #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct $Index(NonZero); impl $Index { - pub fn new(idx: usize) -> Self { + } + + impl Idx for $Index { + fn new(idx: usize) -> Self { unsafe { $Index(NonZero::new(idx + 1)) } } - pub fn idx(&self) -> usize { + fn idx(&self) -> usize { *self.0 - 1 } } @@ -56,6 +60,12 @@ mod indexes { pub use self::indexes::MovePathIndex; pub use self::indexes::MoveOutIndex; +impl self::indexes::MoveOutIndex { + pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex { + move_data.moves[self.idx()].path + } +} + /// `MovePath` is a canonicalized representation of a path that is /// moved or assigned to. /// @@ -125,6 +135,7 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> { } } +#[derive(Debug)] pub struct MoveData<'tcx> { pub move_paths: MovePathData<'tcx>, pub moves: Vec, @@ -133,6 +144,7 @@ pub struct MoveData<'tcx> { pub rev_lookup: MovePathLookup<'tcx>, } +#[derive(Debug)] pub struct LocMap { /// Location-indexed (BasicBlock for outer index, index within BB /// for inner index) map to list of MoveOutIndex's. @@ -153,6 +165,7 @@ impl Index for LocMap { } } +#[derive(Debug)] pub struct PathMap { /// Path-indexed map to list of MoveOutIndex's. /// @@ -187,7 +200,7 @@ impl fmt::Debug for MoveOut { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Location { /// block where action is located pub block: BasicBlock, @@ -202,10 +215,15 @@ impl fmt::Debug for Location { } } +#[derive(Debug)] pub struct MovePathData<'tcx> { move_paths: Vec>, } +impl<'tcx> MovePathData<'tcx> { + pub fn len(&self) -> usize { self.move_paths.len() } +} + impl<'tcx> Index for MovePathData<'tcx> { type Output = MovePath<'tcx>; fn index(&self, i: MovePathIndex) -> &MovePath<'tcx> { @@ -224,6 +242,7 @@ struct MovePathDataBuilder<'a, 'tcx: 'a> { } /// Tables mapping from an l-value to its MovePathIndex. +#[derive(Debug)] pub struct MovePathLookup<'tcx> { vars: MovePathInverseMap, temps: MovePathInverseMap, @@ -272,6 +291,7 @@ impl FillTo for Vec { #[derive(Clone, Debug)] enum LookupKind { Generate, Reuse } +#[derive(Clone, Debug)] struct Lookup(LookupKind, T); impl Lookup { @@ -419,7 +439,14 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> { self.rev_lookup.lookup_proj(proj, base_index) } + fn create_move_path(&mut self, lval: &Lvalue<'tcx>) { + // Create MovePath for `lval`, discarding returned index. + self.move_path_for(lval); + } + fn move_path_for(&mut self, lval: &Lvalue<'tcx>) -> MovePathIndex { + debug!("move_path_for({:?})", lval); + let lookup: Lookup = self.lookup(lval); // `lookup` is either the previously assigned index or a @@ -491,7 +518,7 @@ impl<'a, 'tcx> MoveData<'tcx> { #[derive(Debug)] enum StmtKind { Use, Repeat, Cast, BinaryOp, UnaryOp, Box, - Aggregate, Drop, CallFn, CallArg, Return, + Aggregate, Drop, CallFn, CallArg, Return, If, } fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveData<'tcx> { @@ -511,6 +538,27 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD rev_lookup: MovePathLookup::new(), }; + // Before we analyze the program text, we create the MovePath's + // for all of the vars, args, and temps. (This enforces a basic + // property that even if the MIR body doesn't contain any + // references to a var/arg/temp, it will still be a valid + // operation to lookup the MovePath associated with it.) + assert!(mir.var_decls.len() <= ::std::u32::MAX as usize); + assert!(mir.arg_decls.len() <= ::std::u32::MAX as usize); + assert!(mir.temp_decls.len() <= ::std::u32::MAX as usize); + for var_idx in 0..mir.var_decls.len() { + let path_idx = builder.move_path_for(&Lvalue::Var(var_idx as u32)); + path_map.fill_to(path_idx.idx()); + } + for arg_idx in 0..mir.arg_decls.len() { + let path_idx = builder.move_path_for(&Lvalue::Arg(arg_idx as u32)); + path_map.fill_to(path_idx.idx()); + } + for temp_idx in 0..mir.temp_decls.len() { + let path_idx = builder.move_path_for(&Lvalue::Temp(temp_idx as u32)); + path_map.fill_to(path_idx.idx()); + } + for bb in bbs { let loc_map_bb = &mut loc_map[bb.index()]; let bb_data = mir.basic_block_data(bb); @@ -521,7 +569,7 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD debug_assert!(loc_map_bb.len() == len + 1); let mut bb_ctxt = BlockContext { - tcx: tcx, + _tcx: tcx, moves: &mut moves, builder: builder, path_map: &mut path_map, @@ -532,8 +580,12 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD let source = Location { block: bb, index: i }; match stmt.kind { StatementKind::Assign(ref lval, ref rval) => { - // ensure MovePath created for `lval`. - bb_ctxt.builder.move_path_for(lval); + bb_ctxt.builder.create_move_path(lval); + + // Ensure that the path_map contains entries even + // if the lvalue is assigned and never read. + let assigned_path = bb_ctxt.builder.move_path_for(lval); + bb_ctxt.path_map.fill_to(assigned_path.idx()); match *rval { Rvalue::Use(ref operand) => { @@ -569,27 +621,45 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD Rvalue::InlineAsm { .. } => {} Rvalue::Slice {..} => { - bug!("cannot move out of slice"); + // A slice pattern `x..` binds `x` to a + // reference; thus no move occurs. + // + // FIXME: I recall arielb1 questioning + // whether this is even a legal thing to + // have as an R-value. The particular + // example where I am seeing this arise is + // `TargetDataLayout::parse(&Session)` in + // `rustc::ty::layout`. + // + // this should be removed soon. + debug!("encountered Rvalue::Slice as RHS of Assign, source: {:?}", + source); } } } } } + debug!("gather_moves({:?})", bb_data.terminator()); match bb_data.terminator().kind { TerminatorKind::Goto { target: _ } | TerminatorKind::Resume => { } TerminatorKind::Return => { let source = Location { block: bb, index: bb_data.statements.len() }; - let lval = &Lvalue::ReturnPointer.deref(); - bb_ctxt.on_move_out_lval(SK::Return, lval, source); + if let FnOutput::FnConverging(_) = bb_ctxt.builder.mir.return_ty { + debug!("gather_moves Return on_move_out_lval return {:?}", source); + bb_ctxt.on_move_out_lval(SK::Return, &Lvalue::ReturnPointer, source); + } else { + debug!("gather_moves Return on_move_out_lval \ + assuming unreachable return {:?}", source); + } } TerminatorKind::If { ref cond, targets: _ } => { - // The `cond` is always of (copyable) type `bool`, - // so there will never be anything to move. - let _ = cond; + let source = Location { block: bb, + index: bb_data.statements.len() }; + bb_ctxt.on_operand(SK::If, cond, source); } TerminatorKind::SwitchInt { switch_ty: _, values: _, targets: _, ref discr } | @@ -606,18 +676,23 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD index: bb_data.statements.len() }; bb_ctxt.on_move_out_lval(SK::Drop, lval, source); } - TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { let source = Location { block: bb, index: bb_data.statements.len() }; bb_ctxt.on_operand(SK::CallFn, func, source); for arg in args { + debug!("gather_moves Call on_operand {:?} {:?}", arg, source); bb_ctxt.on_operand(SK::CallArg, arg, source); } if let Some((ref destination, _bb)) = *destination { - // Create MovePath for `destination`, then - // discard returned index. - bb_ctxt.builder.move_path_for(destination); + debug!("gather_moves Call create_move_path {:?} {:?}", destination, source); + + // Ensure that the path_map contains entries even + // if the lvalue is assigned and never read. + let assigned_path = bb_ctxt.builder.move_path_for(destination); + bb_ctxt.path_map.fill_to(assigned_path.idx()); + + bb_ctxt.builder.create_move_path(destination); } } } @@ -635,7 +710,6 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD // // well you know, lets actually try just asserting that the path map *is* complete. assert_eq!(path_map.len(), builder.pre_move_paths.len()); - path_map.fill_to(builder.pre_move_paths.len() - 1); let pre_move_paths = builder.pre_move_paths; let move_paths: Vec<_> = pre_move_paths.into_iter() @@ -667,7 +741,7 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD } struct BlockContext<'b, 'a: 'b, 'tcx: 'a> { - tcx: TyCtxt<'b, 'tcx, 'tcx>, + _tcx: TyCtxt<'b, 'tcx, 'tcx>, moves: &'b mut Vec, builder: MovePathDataBuilder<'a, 'tcx>, path_map: &'b mut Vec>, @@ -679,25 +753,6 @@ impl<'b, 'a: 'b, 'tcx: 'a> BlockContext<'b, 'a, 'tcx> { stmt_kind: StmtKind, lval: &Lvalue<'tcx>, source: Location) { - let tcx = self.tcx; - let lval_ty = self.builder.mir.lvalue_ty(tcx, lval); - - // FIXME: does lvalue_ty ever return TyError, or is it - // guaranteed to always return non-Infer/non-Error values? - - // This code is just trying to avoid creating a MoveOut - // entry for values that do not need move semantics. - // - // type_contents is imprecise (may claim needs drop for - // types that in fact have no destructor). But that is - // still usable for our purposes here. - let consumed = lval_ty.to_ty(tcx).type_contents(tcx).needs_drop(tcx); - - if !consumed { - debug!("ctxt: {:?} no consume of lval: {:?} of type {:?}", - stmt_kind, lval, lval_ty); - return; - } let i = source.index; let index = MoveOutIndex::new(self.moves.len()); @@ -732,13 +787,3 @@ impl<'b, 'a: 'b, 'tcx: 'a> BlockContext<'b, 'a, 'tcx> { } } } - -impl<'tcx> BitDenotation for MoveData<'tcx>{ - type Bit = MoveOut; - fn bits_per_block(&self) -> usize { - self.moves.len() - } - fn interpret(&self, idx: usize) -> &Self::Bit { - &self.moves[idx] - } -} diff --git a/src/librustc_borrowck/borrowck/mir/graphviz.rs b/src/librustc_borrowck/borrowck/mir/graphviz.rs deleted file mode 100644 index 460c71dee3d72..0000000000000 --- a/src/librustc_borrowck/borrowck/mir/graphviz.rs +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Hook into libgraphviz for rendering dataflow graphs for MIR. - -use rustc::mir::repr::{BasicBlock, Mir}; - -use dot; -use dot::IntoCow; - -use std::fs::File; -use std::io; -use std::io::prelude::*; - -use super::MirBorrowckCtxt; -use bitslice::bits_to_string; -use super::gather_moves::MoveOut; - -struct Graph<'c, 'b:'c, 'a:'b, 'tcx:'a> { mbcx: &'c MirBorrowckCtxt<'b, 'a, 'tcx>, - context: &'b str } - -pub fn print_borrowck_graph_to(mbcx: &MirBorrowckCtxt, - context: &str, - path: &str) -> io::Result<()> { - let g = Graph { mbcx: mbcx, context: context }; - let mut v = Vec::new(); - dot::render(&g, &mut v)?; - println!("print_borrowck_graph_to path: {} context: {} node_id: {}", - path, context, mbcx.node_id); - File::create(path).and_then(|mut f| f.write_all(&v)) -} - -pub type Node = BasicBlock; - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Edge { source: BasicBlock, index: usize } - -fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { - let succ_len = mir.basic_block_data(bb).terminator().successors().len(); - (0..succ_len).map(|index| Edge { source: bb, index: index}).collect() -} - -impl<'c, 'b:'c, 'a:'b, 'tcx:'a> dot::Labeller<'c> for Graph<'c,'b,'a,'tcx> { - type Node = Node; - type Edge = Edge; - fn graph_id(&self) -> dot::Id { - dot::Id::new(format!("graph_for_node_{}_{}", - self.mbcx.node_id, - self.context)) - .unwrap() - } - - fn node_id(&self, n: &Node) -> dot::Id { - dot::Id::new(format!("bb_{}", n.index())) - .unwrap() - } - - fn node_label(&self, n: &Node) -> dot::LabelText { - // A standard MIR label, as generated by write_node_label, is - // presented in a single column in a table. - // - // The code below does a bunch of formatting work to format a - // node (i.e. MIR basic-block) label with extra - // dataflow-enriched information. In particular, the goal is - // to add extra columns that present the three dataflow - // bitvectors, and the data those bitvectors represent. - // - // It presents it in the following format (where I am - // presenting the table rendering via ASCII art, one line per - // row of the table, and a chunk size of 3 rather than 5): - // - // ------ ----------------------- ------------ -------------------- - // [e1, e3, e4] - // [e8, e9] "= ENTRY:" - // ------ ----------------------- ------------ -------------------- - // Left - // Most - // Column - // Is - // Just - // Normal - // Series - // Of - // MIR - // Stmts - // ------ ----------------------- ------------ -------------------- - // [g1, g4, g5] "= GEN:" - // ------ ----------------------- ------------ -------------------- - // "KILL:" "=" [k1, k3, k8] - // [k9] - // ------ ----------------------- ------------ -------------------- - // - // (In addition, the added dataflow is rendered with a colored - // background just so it will stand out compared to the - // statements.) - let mut v = Vec::new(); - let i = n.index(); - let chunk_size = 5; - const BG_FLOWCONTENT: &'static str = r#"bgcolor="pink""#; - const ALIGN_RIGHT: &'static str = r#"align="right""#; - const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#; - fn chunked_present_left(w: &mut W, - interpreted: &[&MoveOut], - chunk_size: usize) - -> io::Result<()> - { - // This function may emit a sequence of 's, but it - // always finishes with an (unfinished) - // - // - // Thus, after being called, one should finish both the - // pending as well as the itself. - let mut seen_one = false; - for c in interpreted.chunks(chunk_size) { - if seen_one { - // if not the first row, finish off the previous row - write!(w, "")?; - } - write!(w, "{objs:?}", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT, - objs = c)?; - seen_one = true; - } - if !seen_one { - write!(w, "[]", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT)?; - } - Ok(()) - } - ::rustc_mir::graphviz::write_node_label( - *n, self.mbcx.mir, &mut v, 4, - |w| { - let flow = &self.mbcx.flow_state; - let entry = flow.interpret_set(flow.sets.on_entry_set_for(i)); - chunked_present_left(w, &entry[..], chunk_size)?; - write!(w, "= ENTRY:{entrybits:?}\ - ", - bg = BG_FLOWCONTENT, - face = FACE_MONOSPACE, - entrybits=bits_to_string(flow.sets.on_entry_set_for(i), - flow.sets.bytes_per_block())) - }, - |w| { - let flow = &self.mbcx.flow_state; - let gen = flow.interpret_set( flow.sets.gen_set_for(i)); - let kill = flow.interpret_set(flow.sets.kill_set_for(i)); - chunked_present_left(w, &gen[..], chunk_size)?; - write!(w, " = GEN:{genbits:?}\ - ", - bg = BG_FLOWCONTENT, - face = FACE_MONOSPACE, - genbits=bits_to_string( flow.sets.gen_set_for(i), - flow.sets.bytes_per_block()))?; - write!(w, "KILL:\ - {killbits:?}", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT, - face = FACE_MONOSPACE, - killbits=bits_to_string(flow.sets.kill_set_for(i), - flow.sets.bytes_per_block()))?; - - // (chunked_present_right) - let mut seen_one = false; - for k in kill.chunks(chunk_size) { - if !seen_one { - // continuation of row; this is fourth - write!(w, "= {kill:?}", - bg = BG_FLOWCONTENT, - kill=k)?; - } else { - // new row, with indent of three 's - write!(w, "{kill:?}", - bg = BG_FLOWCONTENT, - kill=k)?; - } - seen_one = true; - } - if !seen_one { - write!(w, "= []", - bg = BG_FLOWCONTENT)?; - } - - Ok(()) - }) - .unwrap(); - dot::LabelText::html(String::from_utf8(v).unwrap()) - } - - fn node_shape(&self, _n: &Node) -> Option { - Some(dot::LabelText::label("none")) - } -} - -impl<'c, 'b:'c, 'a:'b, 'tcx:'a> dot::GraphWalk<'c> for Graph<'c,'b,'a,'tcx> { - type Node = Node; - type Edge = Edge; - fn nodes(&self) -> dot::Nodes { - self.mbcx.mir.all_basic_blocks().into_cow() - } - - fn edges(&self) -> dot::Edges { - let mir = self.mbcx.mir; - let blocks = self.mbcx.mir.all_basic_blocks(); - // base initial capacity on assumption every block has at - // least one outgoing edge (Which should be true for all - // blocks but one, the exit-block). - let mut edges = Vec::with_capacity(blocks.len()); - for bb in blocks { - let outgoing = outgoing(mir, bb); - edges.extend(outgoing.into_iter()); - } - edges.into_cow() - } - - fn source(&self, edge: &Edge) -> Node { - edge.source - } - - fn target(&self, edge: &Edge) -> Node { - let mir = self.mbcx.mir; - mir.basic_block_data(edge.source).terminator().successors()[edge.index] - } -} diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index bec5ae03d3d4d..1b9d08bade7c4 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -10,24 +10,53 @@ use borrowck::BorrowckCtxt; -use syntax::ast; -use syntax::codemap::Span; +use syntax::ast::{self, MetaItem}; +use syntax::attr::AttrMetaMethods; +use syntax::codemap::{Span, DUMMY_SP}; +use syntax::ptr::P; use rustc::hir; use rustc::hir::intravisit::{FnKind}; +use rustc::mir::repr; use rustc::mir::repr::{BasicBlock, BasicBlockData, Mir, Statement, Terminator}; +use rustc::session::Session; +use rustc::ty::{self, TyCtxt}; mod abs_domain; mod dataflow; mod gather_moves; -mod graphviz; +// mod graphviz; -use self::dataflow::{Dataflow, DataflowState}; -use self::gather_moves::{MoveData}; +use self::dataflow::{BitDenotation}; +use self::dataflow::{DataflowOperator}; +use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults}; +use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use self::dataflow::{DefinitelyInitializedLvals}; +use self::gather_moves::{MoveData, MovePathIndex, Location}; +use self::gather_moves::{MovePathContent}; -pub fn borrowck_mir<'b, 'a: 'b, 'tcx: 'a>( - bcx: &'b mut BorrowckCtxt<'a, 'tcx>, +fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option> { + for attr in attrs { + if attr.check_name("rustc_mir") { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + if item.check_name(name) { + return Some(item.clone()) + } + } + } + } + return None; +} + +pub struct MoveDataParamEnv<'tcx> { + move_data: MoveData<'tcx>, + param_env: ty::ParameterEnvironment<'tcx>, +} + +pub fn borrowck_mir<'a, 'tcx: 'a>( + bcx: &mut BorrowckCtxt<'a, 'tcx>, fk: FnKind, _decl: &hir::FnDecl, mir: &'a Mir<'tcx>, @@ -45,29 +74,106 @@ pub fn borrowck_mir<'b, 'a: 'b, 'tcx: 'a>( } } + let tcx = bcx.tcx; + + let move_data = MoveData::gather_moves(mir, tcx); + let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let flow_inits = + do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir)); + let flow_uninits = + do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir)); + let flow_def_inits = + do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir)); + + if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() { + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_inits); + } + if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() { + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_uninits); + } + if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() { + dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_def_inits); + } + + if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() { + bcx.tcx.sess.fatal("stop_after_dataflow ended compilation"); + } + let mut mbcx = MirBorrowckCtxt { - flow_state: DataflowState::new_move_analysis(mir, bcx.tcx), bcx: bcx, mir: mir, node_id: id, - attributes: attributes, + move_data: mdpe.move_data, + flow_inits: flow_inits, + flow_uninits: flow_uninits, }; for bb in mir.all_basic_blocks() { mbcx.process_basic_block(bb); } - mbcx.dataflow(); - debug!("borrowck_mir done"); } +fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + node_id: ast::NodeId, + attributes: &[ast::Attribute], + ctxt: &BD::Ctxt, + bd: BD) -> DataflowResults + where BD: BitDenotation> + DataflowOperator +{ + use syntax::attr::AttrMetaMethods; + + let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option { + if let Some(item) = has_rustc_mir_with(attrs, name) { + if let Some(s) = item.value_str() { + return Some(s.to_string()) + } else { + sess.span_err( + item.span, + &format!("{} attribute requires a path", item.name())); + return None; + } + } + return None; + }; + + let print_preflow_to = + name_found(tcx.sess, attributes, "borrowck_graphviz_preflow"); + let print_postflow_to = + name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); + + let mut mbcx = MirBorrowckCtxtPreDataflow { + node_id: node_id, + print_preflow_to: print_preflow_to, + print_postflow_to: print_postflow_to, + flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd), + }; + + mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]); + mbcx.flow_state.results() +} + + +pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> + where BD: BitDenotation, BD::Ctxt: 'a +{ + node_id: ast::NodeId, + flow_state: DataflowAnalysis<'a, 'tcx, BD>, + print_preflow_to: Option, + print_postflow_to: Option, +} + +#[allow(dead_code)] pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { bcx: &'b mut BorrowckCtxt<'a, 'tcx>, mir: &'b Mir<'tcx>, node_id: ast::NodeId, - attributes: &'b [ast::Attribute], - flow_state: DataflowState>, + move_data: MoveData<'tcx>, + flow_inits: DataflowResults>, + flow_uninits: DataflowResults> } impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { @@ -89,3 +195,129 @@ impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term); } } + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +enum DropFlagState { + Present, // i.e. initialized + Absent, // i.e. deinitialized or "moved" +} + +fn on_all_children_bits<'a, 'tcx, F>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + move_data: &MoveData<'tcx>, + move_path_index: MovePathIndex, + mut each_child: F) + where F: FnMut(MovePathIndex) +{ + fn is_terminal_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + move_data: &MoveData<'tcx>, + path: MovePathIndex) -> bool + { + match move_data.move_paths[path].content { + MovePathContent::Lvalue(ref lvalue) => { + match mir.lvalue_ty(tcx, lvalue).to_ty(tcx).sty { + // don't trace paths past arrays, slices, and + // pointers. They can only be accessed while + // their parents are initialized. + // + // FIXME: we have to do something for moving + // slice patterns. + ty::TyArray(..) | ty::TySlice(..) | + ty::TyRef(..) | ty::TyRawPtr(..) => true, + _ => false + } + } + _ => true + } + } + + fn on_all_children_bits<'a, 'tcx, F>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + move_data: &MoveData<'tcx>, + move_path_index: MovePathIndex, + each_child: &mut F) + where F: FnMut(MovePathIndex) + { + each_child(move_path_index); + + if is_terminal_path(tcx, mir, move_data, move_path_index) { + return + } + + let mut next_child_index = move_data.move_paths[move_path_index].first_child; + while let Some(child_index) = next_child_index { + on_all_children_bits(tcx, mir, move_data, child_index, each_child); + next_child_index = move_data.move_paths[child_index].next_sibling; + } + } + on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child); +} + +fn drop_flag_effects_for_function_entry<'a, 'tcx, F>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + ctxt: &MoveDataParamEnv<'tcx>, + mut callback: F) + where F: FnMut(MovePathIndex, DropFlagState) +{ + let move_data = &ctxt.move_data; + for i in 0..(mir.arg_decls.len() as u32) { + let lvalue = repr::Lvalue::Arg(i); + let move_path_index = move_data.rev_lookup.find(&lvalue); + on_all_children_bits(tcx, mir, move_data, + move_path_index, + |moi| callback(moi, DropFlagState::Present)); + } +} + +fn drop_flag_effects_for_location<'a, 'tcx, F>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + ctxt: &MoveDataParamEnv<'tcx>, + loc: Location, + mut callback: F) + where F: FnMut(MovePathIndex, DropFlagState) +{ + let move_data = &ctxt.move_data; + let param_env = &ctxt.param_env; + debug!("drop_flag_effects_for_location({:?})", loc); + + // first, move out of the RHS + for mi in &move_data.loc_map[loc] { + let path = mi.move_path_index(move_data); + debug!("moving out of path {:?}", move_data.move_paths[path]); + + // don't move out of non-Copy things + if let MovePathContent::Lvalue(ref lvalue) = move_data.move_paths[path].content { + let ty = mir.lvalue_ty(tcx, lvalue).to_ty(tcx); + if !ty.moves_by_default(tcx, param_env, DUMMY_SP) { + continue; + } + } + + on_all_children_bits(tcx, mir, move_data, + path, + |moi| callback(moi, DropFlagState::Absent)) + } + + let bb = mir.basic_block_data(loc.block); + match bb.statements.get(loc.index) { + Some(stmt) => match stmt.kind { + repr::StatementKind::Assign(ref lvalue, _) => { + debug!("drop_flag_effects: assignment {:?}", stmt); + on_all_children_bits(tcx, mir, move_data, + move_data.rev_lookup.find(lvalue), + |moi| callback(moi, DropFlagState::Present)) + } + }, + None => { + // terminator - no move-ins except for function return edge + let term = bb.terminator(); + debug!("drop_flag_effects: terminator {:?}", term); + } + } +} diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 36222e172b8d6..819717628d62d 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -977,7 +977,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Categorization::Local(local_id) = err.cmt.cat { let span = self.tcx.map.span(local_id); if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { - if snippet != "self" { + if snippet.starts_with("ref ") { + db.span_label(span, + &format!("use `{}` here to make mutable", + snippet.replace("ref ", "ref mut "))); + } else if snippet != "self" { db.span_label(span, &format!("use `mut {}` here to make mutable", snippet)); } diff --git a/src/librustc_borrowck/indexed_set.rs b/src/librustc_borrowck/indexed_set.rs new file mode 100644 index 0000000000000..3fee1dbc05660 --- /dev/null +++ b/src/librustc_borrowck/indexed_set.rs @@ -0,0 +1,165 @@ +// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME: move this to `rustc_data_structures` + +use std::fmt; +use std::marker::PhantomData; +use std::mem; +use std::ops::{Deref, DerefMut, Range}; +use bitslice::{BitSlice, Word}; +use bitslice::{bitwise, Union, Subtract}; + +/// Represents some newtyped `usize` wrapper. +/// +/// (purpose: avoid mixing indexes for different bitvector domains.) +pub trait Idx: 'static { + fn new(usize) -> Self; + fn idx(&self) -> usize; +} + +/// Represents a set (or packed family of sets), of some element type +/// E, where each E is identified by some unique index type `T`. +/// +/// In other words, `T` is the type used to index into the bitvector +/// this type uses to represent the set of object it holds. +pub struct IdxSetBuf { + _pd: PhantomData, + bits: Vec, +} + +impl Clone for IdxSetBuf { + fn clone(&self) -> Self { + IdxSetBuf { _pd: PhantomData, bits: self.bits.clone() } + } +} + +// pnkfelix wants to have this be `IdxSet([Word]) and then pass +// around `&mut IdxSet` or `&IdxSet`. +// +// WARNING: Mapping a `&IdxSetBuf` to `&IdxSet` (at least today) +// requires a transmute relying on representation guarantees that may +// not hold in the future. + +/// Represents a set (or packed family of sets), of some element type +/// E, where each E is identified by some unique index type `T`. +/// +/// In other words, `T` is the type used to index into the bitslice +/// this type uses to represent the set of object it holds. +pub struct IdxSet { + _pd: PhantomData, + bits: [Word], +} + +impl fmt::Debug for IdxSetBuf { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) } +} + +impl fmt::Debug for IdxSet { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) } +} + +impl IdxSetBuf { + fn new(init: Word, universe_size: usize) -> Self { + let bits_per_word = mem::size_of::() * 8; + let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word; + IdxSetBuf { + _pd: Default::default(), + bits: vec![init; num_words], + } + } + + /// Creates set holding every element whose index falls in range 0..universe_size. + pub fn new_filled(universe_size: usize) -> Self { + Self::new(!0, universe_size) + } + + /// Creates set holding no elements. + pub fn new_empty(universe_size: usize) -> Self { + Self::new(0, universe_size) + } +} + +impl IdxSet { + unsafe fn from_slice(s: &[Word]) -> &Self { + mem::transmute(s) // (see above WARNING) + } + + unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self { + mem::transmute(s) // (see above WARNING) + } +} + +impl Deref for IdxSetBuf { + type Target = IdxSet; + fn deref(&self) -> &IdxSet { + unsafe { IdxSet::from_slice(&self.bits[..]) } + } +} + +impl DerefMut for IdxSetBuf { + fn deref_mut(&mut self) -> &mut IdxSet { + unsafe { IdxSet::from_slice_mut(&mut self.bits[..]) } + } +} + +impl IdxSet { + pub fn to_owned(&self) -> IdxSetBuf { + IdxSetBuf { + _pd: Default::default(), + bits: self.bits.to_owned(), + } + } + + /// Removes `elem` from the set `self`; returns true iff this changed `self`. + pub fn remove(&mut self, elem: &T) -> bool { + self.bits.clear_bit(elem.idx()) + } + + /// Adds `elem` to the set `self`; returns true iff this changed `self`. + pub fn add(&mut self, elem: &T) -> bool { + self.bits.set_bit(elem.idx()) + } + + pub fn range(&self, elems: &Range) -> &Self { + let elems = elems.start.idx()..elems.end.idx(); + unsafe { Self::from_slice(&self.bits[elems]) } + } + + pub fn range_mut(&mut self, elems: &Range) -> &mut Self { + let elems = elems.start.idx()..elems.end.idx(); + unsafe { Self::from_slice_mut(&mut self.bits[elems]) } + } + + /// Returns true iff set `self` contains `elem`. + pub fn contains(&self, elem: &T) -> bool { + self.bits.get_bit(elem.idx()) + } + + pub fn words(&self) -> &[Word] { + &self.bits[..] + } + + pub fn words_mut(&mut self) -> &mut [Word] { + &mut self.bits[..] + } + + pub fn clone_from(&mut self, other: &IdxSet) { + self.words_mut().clone_from_slice(other.words()); + } + + pub fn union(&mut self, other: &IdxSet) -> bool { + bitwise(self.words_mut(), other.words(), &Union) + } + + pub fn subtract(&mut self, other: &IdxSet) -> bool { + bitwise(self.words_mut(), other.words(), &Subtract) + } +} diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index e38677de6625f..9d7e05ed9fa86 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -47,6 +47,7 @@ pub mod diagnostics; mod borrowck; mod bitslice; +mod indexed_set; pub mod graphviz; diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 2fb5d796589b2..16b61534ee9ab 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -374,7 +374,7 @@ fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool { PatKind::Ident(_, _, None) => pat_is_binding(dm, p), PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s), PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s), - PatKind::Tup(ref v) => v.iter().all(|p| pat_is_catchall(dm, &p)), + PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(dm, &p)), _ => false } } @@ -398,7 +398,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir: hir::MatchSource::ForLoopDesugar => { // `witnesses[0]` has the form `Some()`, peel off the `Some` let witness = match witnesses[0].node { - PatKind::TupleStruct(_, Some(ref pats)) => match &pats[..] { + PatKind::TupleStruct(_, ref pats, _) => match &pats[..] { [ref pat] => &**pat, _ => bug!(), }, @@ -559,7 +559,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, let pats_len = pats.len(); let mut pats = pats.into_iter().map(|p| P((*p).clone())); let pat = match left_ty.sty { - ty::TyTuple(_) => PatKind::Tup(pats.collect()), + ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None), ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => { let v = ctor.variant_for_adt(adt); @@ -580,7 +580,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor, PatKind::Struct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields) } VariantKind::Tuple => { - PatKind::TupleStruct(def_to_path(cx.tcx, v.did), Some(pats.collect())) + PatKind::TupleStruct(def_to_path(cx.tcx, v.did), pats.collect(), None) } VariantKind::Unit => { PatKind::Path(def_to_path(cx.tcx, v.did)) @@ -832,7 +832,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, vec!(Slice(before.len() + after.len())) } }, - PatKind::Box(_) | PatKind::Tup(_) | PatKind::Ref(..) => + PatKind::Box(..) | PatKind::Tuple(..) | PatKind::Ref(..) => vec!(Single), PatKind::Wild => vec!(), @@ -914,7 +914,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } } - PatKind::TupleStruct(_, ref args) => { + PatKind::TupleStruct(_, ref args, ddpos) => { let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); match def { Def::Const(..) | Def::AssociatedConst(..) => @@ -922,10 +922,15 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], been rewritten"), Def::Variant(_, id) if *constructor != Variant(id) => None, Def::Variant(..) | Def::Struct(..) => { - Some(match args { - &Some(ref args) => args.iter().map(|p| &**p).collect(), - &None => vec![DUMMY_WILD_PAT; arity], - }) + match ddpos { + Some(ddpos) => { + let mut pats: Vec<_> = args[..ddpos].iter().map(|p| &**p).collect(); + pats.extend(repeat(DUMMY_WILD_PAT).take(arity - args.len())); + pats.extend(args[ddpos..].iter().map(|p| &**p)); + Some(pats) + } + None => Some(args.iter().map(|p| &**p).collect()) + } } _ => None } @@ -952,7 +957,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } } - PatKind::Tup(ref args) => + PatKind::Tuple(ref args, Some(ddpos)) => { + let mut pats: Vec<_> = args[..ddpos].iter().map(|p| &**p).collect(); + pats.extend(repeat(DUMMY_WILD_PAT).take(arity - args.len())); + pats.extend(args[ddpos..].iter().map(|p| &**p)); + Some(pats) + } + PatKind::Tuple(ref args, None) => Some(args.iter().map(|p| &**p).collect()), PatKind::Box(ref inner) | PatKind::Ref(ref inner, _) => diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 9db24fa4770fe..b727b778fcd79 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -271,10 +271,9 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let pat = match expr.node { hir::ExprTup(ref exprs) => - PatKind::Tup(try!(exprs.iter() - .map(|expr| const_expr_to_pat(tcx, &expr, - pat_id, span)) - .collect())), + PatKind::Tuple(try!(exprs.iter() + .map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span)) + .collect()), None), hir::ExprCall(ref callee, ref args) => { let def = *tcx.def_map.borrow().get(&callee.id).unwrap(); @@ -295,7 +294,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .map(|expr| const_expr_to_pat(tcx, &**expr, pat_id, span)) .collect()); - PatKind::TupleStruct(path, Some(pats)) + PatKind::TupleStruct(path, pats, None) } hir::ExprStruct(ref path, ref fields, None) => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1f3df1ff6f2d8..a8ddc7e7bdab0 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -720,16 +720,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, ret }); - // JBC: make CFG processing part of expansion to avoid this problem: - - // strip again, in case expansion added anything with a #[cfg]. krate = sess.track_errors(|| { - let krate = time(time_passes, "configuration 2", || { - syntax::config::strip_unconfigured_items(sess.diagnostic(), - krate, - &mut feature_gated_cfgs) - }); - time(time_passes, "gated configuration checking", || { let features = sess.features.borrow(); feature_gated_cfgs.sort(); @@ -743,7 +734,10 @@ pub fn phase_2_configure_and_expand(sess: &Session, })?; krate = time(time_passes, "maybe building test harness", || { - syntax::test::modify_for_testing(&sess.parse_sess, &sess.opts.cfg, krate, sess.diagnostic()) + syntax::test::modify_for_testing(&sess.parse_sess, + sess.opts.test, + krate, + sess.diagnostic()) }); krate = time(time_passes, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 06133c508d9f0..bd6b0599e7832 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -511,10 +511,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_write_deps.stop = Compilation::Stop; } - if sess.opts.no_trans { - control.after_analysis.stop = Compilation::Stop; - } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) { control.after_llvm.stop = Compilation::Stop; } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 8c84e561e317a..0a093887c5094 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -757,6 +757,7 @@ fn get_source(input: &Input, sess: &Session) -> (Vec, String) { let src_name = driver::source_name(input); let src = sess.codemap() .get_filemap(&src_name) + .unwrap() .src .as_ref() .unwrap() diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs index 24ecce1148745..a039467c8afc0 100644 --- a/src/librustc_incremental/calculate_svh.rs +++ b/src/librustc_incremental/calculate_svh.rs @@ -251,7 +251,7 @@ mod svh_visitor { ExprType(..) => SawExprType, ExprIf(..) => SawExprIf, ExprWhile(..) => SawExprWhile, - ExprLoop(_, id) => SawExprLoop(id.map(|id| id.as_str())), + ExprLoop(_, id) => SawExprLoop(id.map(|id| id.node.as_str())), ExprMatch(..) => SawExprMatch, ExprClosure(..) => SawExprClosure, ExprBlock(..) => SawExprBlock, @@ -401,10 +401,6 @@ mod svh_visitor { SawPath.hash(self.st); visit::walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &'a Path, item: &'a PathListItem) { - SawPath.hash(self.st); visit::walk_path_list_item(self, prefix, item) - } - fn visit_block(&mut self, b: &'a Block) { SawBlock.hash(self.st); visit::walk_block(self, b) } diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 2b972af07ff91..74f97de265898 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -33,7 +33,7 @@ pub const tag_items_data_item_family: usize = 0x24; pub const tag_items_data_item_type: usize = 0x25; -pub const tag_items_data_item_symbol: usize = 0x26; +// GAP 0x26 pub const tag_items_data_item_variant: usize = 0x27; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index ad6bb2dbac221..2025045cc8f56 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,6 +17,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use decoder; use loader::{self, CratePaths}; +use rustc::hir::def_id::DefIndex; use rustc::hir::svh::Svh; use rustc::dep_graph::{DepGraph, DepNode}; use rustc::session::{config, Session}; @@ -610,9 +611,10 @@ impl<'a> CrateReader<'a> { macros } - /// Look for a plugin registrar. Returns library path and symbol name. + /// Look for a plugin registrar. Returns library path, crate + /// SVH and DefIndex of the registrar function. pub fn find_plugin_registrar(&mut self, span: Span, name: &str) - -> Option<(PathBuf, String)> { + -> Option<(PathBuf, Svh, DefIndex)> { let ekrate = self.read_extension_crate(span, &CrateInfo { name: name.to_string(), ident: name.to_string(), @@ -630,12 +632,14 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } + let svh = decoder::get_crate_hash(ekrate.metadata.as_slice()); let registrar = - decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()) - .map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id)); + decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice()); match (ekrate.dylib.as_ref(), registrar) { - (Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)), + (Some(dylib), Some(reg)) => { + Some((dylib.to_path_buf(), svh, reg)) + } (None, Some(_)) => { span_err!(self.sess, span, E0457, "plugin `{}` only found in rlib format, but must be available \ diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index b87b5492f0440..5d42f8c1d6f6a 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -25,7 +25,7 @@ use rustc::hir::map as hir_map; use rustc::hir::map::DefKey; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap}; +use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap}; use rustc::session::config::PanicStrategy; use std::cell::RefCell; @@ -115,13 +115,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_item_attrs(&cdata, def_id.index) } - fn item_symbol(&self, def: DefId) -> String - { - self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_symbol(&cdata, def.index) - } - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); @@ -284,6 +277,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::is_extern_item(&cdata, did.index, tcx) } + fn is_foreign_item(&self, did: DefId) -> bool { + let cdata = self.get_crate_data(did.krate); + decoder::is_foreign_item(&cdata, did.index) + } + fn is_static_method(&self, def: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(def)); @@ -564,7 +562,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, - item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, mir_map: &MirMap<'tcx>, @@ -574,7 +571,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { diag: tcx.sess.diagnostic(), tcx: tcx, reexports: reexports, - item_symbols: item_symbols, link_meta: link_meta, cstore: self, reachable: reachable, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b6f35074b7dc7..d1153fe2d0603 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -213,10 +213,6 @@ fn item_sort(item: rbml::Doc) -> Option { }) } -fn item_symbol(item: rbml::Doc) -> String { - reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string() -} - fn untranslated_def_id(d: rbml::Doc) -> DefId { let id = reader::doc_as_u64(d); let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); @@ -640,18 +636,6 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, } } -pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { - return item_symbol(cdata.lookup_item(id)); -} - -/// If you have a crate_metadata, call get_symbol instead -pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String { - let index = load_index(data); - let pos = index.lookup_item(data, id).unwrap(); - let doc = reader::doc_at(data, pos as usize).unwrap().doc; - item_symbol(doc) -} - /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where F: FnMut(DefIndex, usize) -> bool, @@ -1642,6 +1626,16 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, } } +pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { + let item_doc = cdata.lookup_item(id); + let parent_item_id = match item_parent_item(cdata, item_doc) { + None => return false, + Some(item_id) => item_id, + }; + let parent_item_doc = cdata.lookup_item(parent_item_id.index); + item_family(parent_item_doc) == ForeignMod +} + pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { let item_doc = cdata.lookup_item(id); match item_family(item_doc) { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 928601095b078..2bc953039adb2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -34,7 +34,7 @@ use rustc::ty::util::IntTypeExt; use rustc::hir::svh::Svh; use rustc::mir::mir_map::MirMap; use rustc::session::config::{self, PanicStrategy}; -use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; +use rustc::util::nodemap::{FnvHashMap, NodeSet}; use rustc_serialize::Encodable; use std::cell::RefCell; @@ -59,7 +59,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub diag: &'a Handler, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub reexports: &'a def::ExportMap, - pub item_symbols: &'a RefCell>, pub link_meta: &'a LinkMeta, pub cstore: &'a cstore::CStore, pub type_abbrevs: tyencode::abbrev_map<'tcx>, @@ -213,20 +212,6 @@ fn encode_region(ecx: &EncodeContext, rbml_w.end_tag(); } -fn encode_symbol(ecx: &EncodeContext, - rbml_w: &mut Encoder, - id: NodeId) { - match ecx.item_symbols.borrow().get(&id) { - Some(x) => { - debug!("encode_symbol(id={}, str={})", id, *x); - rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); - } - None => { - bug!("encode_symbol: id not found {}", id); - } - } -} - fn encode_disr_val(_: &EncodeContext, rbml_w: &mut Encoder, disr_val: ty::Disr) { @@ -518,10 +503,6 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_name(rbml_w, name); encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id)); - if ecx.item_symbols.borrow().contains_key(&ctor_id) { - encode_symbol(ecx, rbml_w, ctor_id); - } - let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(ctor_id)); let depr= ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(ctor_id)); encode_stability(rbml_w, stab); @@ -710,10 +691,6 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } encode_constness(rbml_w, sig.constness); encode_defaultness(rbml_w, impl_item.defaultness); - if !any_types { - let m_id = ecx.local_id(m.def_id); - encode_symbol(ecx, rbml_w, m_id); - } encode_method_argument_names(rbml_w, &sig.decl); } } @@ -894,7 +871,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_family(rbml_w, 'c'); } encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id); - encode_symbol(ecx, rbml_w, item.id); encode_name(rbml_w, item.name); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -931,9 +907,6 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item)); encode_mir(ecx, rbml_w, item.id); } - if tps_len == 0 { - encode_symbol(ecx, rbml_w, item.id); - } encode_constness(rbml_w, constness); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -1354,6 +1327,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, let _task = index.record(def_id, rbml_w); rbml_w.start_tag(tag_items_data_item); encode_def_id_and_key(ecx, rbml_w, def_id); + let parent_id = ecx.tcx.map.get_parent(nitem.id); + encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id)); encode_visibility(rbml_w, &nitem.vis); match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { @@ -1363,8 +1338,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem)); encode_mir(ecx, rbml_w, nitem.id); - } else { - encode_symbol(ecx, rbml_w, nitem.id); } encode_attributes(rbml_w, &nitem.attrs); let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id)); @@ -1385,7 +1358,6 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id)); encode_stability(rbml_w, stab); encode_deprecation(rbml_w, depr); - encode_symbol(ecx, rbml_w, nitem.id); encode_name(rbml_w, nitem.name); } } diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 0118b97dd7f3e..b9ba860e8d0aa 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -13,7 +13,7 @@ use hair::cx::Cx; use rustc_data_structures::fnv::FnvHashMap; use rustc_const_eval as const_eval; use rustc::hir::def::Def; -use rustc::hir::pat_util::{pat_is_resolved_const, pat_is_binding}; +use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const, pat_is_binding}; use rustc::ty::{self, Ty}; use rustc::mir::repr::*; use rustc::hir::{self, PatKind}; @@ -148,17 +148,23 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { } } - PatKind::Tup(ref subpatterns) => { - let subpatterns = - subpatterns.iter() - .enumerate() - .map(|(i, subpattern)| FieldPattern { - field: Field::new(i), - pattern: self.to_pattern(subpattern), - }) - .collect(); + PatKind::Tuple(ref subpatterns, ddpos) => { + match self.cx.tcx.node_id_to_type(pat.id).sty { + ty::TyTuple(ref tys) => { + let subpatterns = + subpatterns.iter() + .enumerate_and_adjust(tys.len(), ddpos) + .map(|(i, subpattern)| FieldPattern { + field: Field::new(i), + pattern: self.to_pattern(subpattern), + }) + .collect(); + + PatternKind::Leaf { subpatterns: subpatterns } + } - PatternKind::Leaf { subpatterns: subpatterns } + ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty), + } } PatKind::Ident(bm, ref ident, ref sub) @@ -208,11 +214,18 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { self.variant_or_leaf(pat, vec![]) } - PatKind::TupleStruct(_, ref opt_subpatterns) => { + PatKind::TupleStruct(_, ref subpatterns, ddpos) => { + let pat_ty = self.cx.tcx.node_id_to_type(pat.id); + let adt_def = match pat_ty.sty { + ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def, + _ => span_bug!(pat.span, "tuple struct pattern not applied to struct or enum"), + }; + let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); + let variant_def = adt_def.variant_of_def(def); + let subpatterns = - opt_subpatterns.iter() - .flat_map(|v| v.iter()) - .enumerate() + subpatterns.iter() + .enumerate_and_adjust(variant_def.fields.len(), ddpos) .map(|(i, field)| FieldPattern { field: Field::new(i), pattern: self.to_pattern(field), diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index fb29cbd5fa8a2..a6bbd55ffa7a4 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -106,12 +106,9 @@ enum Annotation { ExitScope(ScopeId), } -pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, - w: &mut Write, - auxiliary: Option<&ScopeAuxiliaryVec>) - -> io::Result<()> { +fn scope_entry_exit_annotations(auxiliary: Option<&ScopeAuxiliaryVec>) + -> FnvHashMap> +{ // compute scope/entry exit annotations let mut annotations = FnvHashMap(); if let Some(auxiliary) = auxiliary { @@ -129,7 +126,16 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } } + return annotations; +} +pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &Mir<'tcx>, + w: &mut Write, + auxiliary: Option<&ScopeAuxiliaryVec>) + -> io::Result<()> { + let annotations = scope_entry_exit_annotations(auxiliary); write_mir_intro(tcx, src, mir, w)?; for block in mir.all_basic_blocks() { write_basic_block(tcx, block, mir, w, &annotations)?; @@ -270,6 +276,14 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir, w: &mut Write) -> io::Result<()> { + write_mir_sig(tcx, src, mir, w)?; + writeln!(w, " {{")?; + write_mir_decls(tcx, mir, w) +} + +fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) + -> io::Result<()> +{ match src { MirSource::Fn(_) => write!(w, "fn")?, MirSource::Const(_) => write!(w, "const")?, @@ -295,16 +309,18 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // fn return type. match mir.return_ty { - ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty)?, - ty::FnOutput::FnDiverging => write!(w, "!")?, + ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty), + ty::FnOutput::FnDiverging => write!(w, "!"), } } else { assert!(mir.arg_decls.is_empty()); - write!(w, ": {} =", mir.return_ty.unwrap())?; + write!(w, ": {} =", mir.return_ty.unwrap()) } +} - writeln!(w, " {{")?; - +fn write_mir_decls(tcx: TyCtxt, mir: &Mir, w: &mut Write) + -> io::Result<()> +{ // User variable types (including the user's name in a comment). for (i, var) in mir.var_decls.iter().enumerate() { let mut_str = if var.mutability == Mutability::Mut { diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 036e46c380398..11e1841f7493e 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -101,7 +101,8 @@ impl<'a> PluginLoader<'a> { fn load_plugin(&mut self, span: Span, name: &str, args: Vec>) { let registrar = self.reader.find_plugin_registrar(span, name); - if let Some((lib, symbol)) = registrar { + if let Some((lib, svh, index)) = registrar { + let symbol = self.sess.generate_plugin_registrar_symbol(&svh, index); let fun = self.dylink_registrar(span, lib, symbol); self.plugins.push(PluginRegistrar { fun: fun, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f1e744098b960..c90d152e3c314 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -31,7 +31,7 @@ use std::mem::replace; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::{self, Visitor}; - +use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::dep_graph::DepNode; use rustc::lint; use rustc::hir::def::{self, Def}; @@ -488,13 +488,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { self.check_field(pattern.span, adt, variant.field_named(field.node.name)); } } - - // Patterns which bind no fields are allowable (the path is check - // elsewhere). - PatKind::TupleStruct(_, Some(ref fields)) => { + PatKind::TupleStruct(_, ref fields, ddpos) => { match self.tcx.pat_ty(pattern).sty { ty::TyStruct(def, _) => { - for (i, field) in fields.iter().enumerate() { + let expected_len = def.struct_variant().fields.len(); + for (i, field) in fields.iter().enumerate_and_adjust(expected_len, ddpos) { if let PatKind::Wild = field.node { continue } @@ -506,7 +504,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } _ => {} } - } _ => {} } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f56b22f924891..e0243bf4fa690 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -35,7 +35,7 @@ use syntax::codemap::{Span, DUMMY_SP}; use syntax::ast::{Block, Crate, DeclKind}; use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, PathListItemKind}; -use syntax::ast::{SelfKind, Stmt, StmtKind, TraitItemKind}; +use syntax::ast::{Stmt, StmtKind, TraitItemKind}; use syntax::ast::{Variant, ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::visit::{self, Visitor}; @@ -335,7 +335,7 @@ impl<'b> Resolver<'b> { let (def, ns) = match item.node { TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS), TraitItemKind::Method(ref sig, _) => { - is_static_method = sig.explicit_self.node == SelfKind::Static; + is_static_method = !sig.decl.has_self(); (Def::Method(item_def_id), ValueNS) } TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 61ed88ec173d4..2444f6acced24 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -148,7 +148,13 @@ enum ResolutionError<'a> { /// error E0424: `self` is not available in a static method SelfNotAvailableInStaticMethod, /// error E0425: unresolved name - UnresolvedName(&'a str, &'a str, UnresolvedNameContext<'a>), + UnresolvedName { + path: &'a str, + message: &'a str, + context: UnresolvedNameContext<'a>, + is_static_method: bool, + is_field: bool + }, /// error E0426: use of undeclared label UndeclaredLabel(&'a str), /// error E0427: cannot use `ref` binding mode with ... @@ -406,16 +412,21 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, "`self` is not available in a static method. Maybe a `self` \ argument is missing?") } - ResolutionError::UnresolvedName(path, msg, context) => { + ResolutionError::UnresolvedName { path, message: msg, context, is_static_method, + is_field } => { let mut err = struct_span_err!(resolver.session, span, E0425, "unresolved name `{}`{}", path, msg); - match context { - UnresolvedNameContext::Other => { } // no help available + UnresolvedNameContext::Other => { + if msg.is_empty() && is_static_method && is_field { + err.help("this is an associated function, you don't have access to \ + this type's fields or methods"); + } + } UnresolvedNameContext::PathIsMod(parent) => { err.help(&match parent.map(|parent| &parent.node) { Some(&ExprKind::Field(_, ident)) => { @@ -596,7 +607,7 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> { } FnKind::Method(_, sig, _) => { self.visit_generics(&sig.generics); - MethodRibKind + MethodRibKind(!sig.decl.has_self()) } FnKind::Closure => ClosureRibKind(node_id), }; @@ -666,7 +677,9 @@ enum RibKind<'a> { // methods. Allow references to ty params that impl or trait // binds. Disallow any other upvars (including other ty params that are // upvars). - MethodRibKind, + // + // The boolean value represents the fact that this method is static or not. + MethodRibKind(bool), // We passed through an item scope. Disallow upvars. ItemRibKind, @@ -1095,7 +1108,13 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { Err(false) => { let path_name = &format!("{}", path); let error = - ResolutionError::UnresolvedName(path_name, "", UnresolvedNameContext::Other); + ResolutionError::UnresolvedName { + path: path_name, + message: "", + context: UnresolvedNameContext::Other, + is_static_method: false, + is_field: false + }; resolve_error(self, path.span, error); Def::Err } @@ -1657,7 +1676,7 @@ impl<'a> Resolver<'a> { let type_parameters = HasTypeParameters(&sig.generics, FnSpace, - MethodRibKind); + MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) }); @@ -1776,7 +1795,10 @@ impl<'a> Resolver<'a> { self.value_ribs.pop(); } - fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, block: &Block) { + fn resolve_function(&mut self, + rib_kind: RibKind<'a>, + declaration: &FnDecl, + block: &Block) { // Create a value rib for the function. self.value_ribs.push(Rib::new(rib_kind)); @@ -1983,7 +2005,7 @@ impl<'a> Resolver<'a> { let type_parameters = HasTypeParameters(&sig.generics, FnSpace, - MethodRibKind); + MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_impl_item(this, impl_item); }); @@ -2334,7 +2356,7 @@ impl<'a> Resolver<'a> { } } - PatKind::TupleStruct(ref path, _) | PatKind::Path(ref path) => { + PatKind::TupleStruct(ref path, _, _) | PatKind::Path(ref path) => { // This must be an enum variant, struct or const. let resolution = match self.resolve_possibly_assoc_item(pat_id, None, @@ -2677,7 +2699,7 @@ impl<'a> Resolver<'a> { def = Def::Upvar(node_def_id, node_id, depth, function_id); seen.insert(node_id, depth); } - ItemRibKind | MethodRibKind => { + ItemRibKind | MethodRibKind(_) => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -2699,7 +2721,7 @@ impl<'a> Resolver<'a> { Def::TyParam(..) | Def::SelfTy(..) => { for rib in ribs { match rib.kind { - NormalRibKind | MethodRibKind | ClosureRibKind(..) | + NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) | ModuleRibKind(..) => { // Nothing to do. Continue. } @@ -2992,9 +3014,13 @@ impl<'a> Resolver<'a> { // `resolve_path` already reported the error } else { let mut method_scope = false; + let mut is_static = false; self.value_ribs.iter().rev().all(|rib| { method_scope = match rib.kind { - MethodRibKind => true, + MethodRibKind(is_static_) => { + is_static = is_static_; + true + } ItemRibKind | ConstantItemRibKind => false, _ => return true, // Keep advancing }; @@ -3008,22 +3034,29 @@ impl<'a> Resolver<'a> { ResolutionError::SelfNotAvailableInStaticMethod); } else { let last_name = path.segments.last().unwrap().identifier.name; - let mut msg = match self.find_fallback_in_self_type(last_name) { + let (mut msg, is_field) = + match self.find_fallback_in_self_type(last_name) { NoSuggestion => { // limit search to 5 to reduce the number // of stupid suggestions - match self.find_best_match(&path_name) { + (match self.find_best_match(&path_name) { SuggestionType::Macro(s) => { format!("the macro `{}`", s) } SuggestionType::Function(s) => format!("`{}`", s), SuggestionType::NotFound => "".to_string(), - } + }, false) + } + Field => { + (if is_static && method_scope { + "".to_string() + } else { + format!("`self.{}`", path_name) + }, true) } - Field => format!("`self.{}`", path_name), - TraitItem => format!("to call `self.{}`", path_name), + TraitItem => (format!("to call `self.{}`", path_name), false), TraitMethod(path_str) => - format!("to call `{}::{}`", path_str, path_name), + (format!("to call `{}::{}`", path_str, path_name), false), }; let mut context = UnresolvedNameContext::Other; @@ -3048,8 +3081,13 @@ impl<'a> Resolver<'a> { resolve_error(self, expr.span, - ResolutionError::UnresolvedName( - &path_name, &msg, context)); + ResolutionError::UnresolvedName { + path: &path_name, + message: &msg, + context: context, + is_static_method: method_scope && is_static, + is_field: is_field, + }); } } } @@ -3086,7 +3124,7 @@ impl<'a> Resolver<'a> { { let rib = this.label_ribs.last_mut().unwrap(); - rib.bindings.insert(mtwt::resolve(label), def); + rib.bindings.insert(mtwt::resolve(label.node), def); } visit::walk_expr(this, expr); @@ -3131,7 +3169,7 @@ impl<'a> Resolver<'a> { self.value_ribs.push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new()); - self.resolve_labeled_block(label, expr.id, block); + self.resolve_labeled_block(label.map(|l| l.node), expr.id, block); self.value_ribs.pop(); } @@ -3141,7 +3179,7 @@ impl<'a> Resolver<'a> { self.value_ribs.push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new()); - self.resolve_labeled_block(label, expr.id, block); + self.resolve_labeled_block(label.map(|l| l.node), expr.id, block); self.value_ribs.pop(); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8c00a56999398..05de5d2770d27 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -123,15 +123,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_item_data(&self, item: &ast::Item) -> Option { match item.node { ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => { - let name = self.tcx.node_path_str(item.id); - let qualname = format!("::{}", name); + let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); Some(Data::FunctionData(FunctionData { id: item.id, - name: name, + name: item.ident.to_string(), qualname: qualname, declaration: None, span: sub_span.unwrap(), @@ -696,7 +695,7 @@ impl<'v> Visitor<'v> for PathCollector { self.collected_paths.push((p.id, path.clone(), ast::Mutability::Mutable, recorder::TypeRef)); } - PatKind::TupleStruct(ref path, _) | + PatKind::TupleStruct(ref path, _, _) | PatKind::Path(ref path) | PatKind::QPath(_, ref path) => { self.collected_paths.push((p.id, path.clone(), diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index dbc277f243267..4b22e410f4c22 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -792,7 +792,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool { m.iter().any(|br| { let pat = br.pats[col]; match pat.node { - PatKind::Tup(_) => true, + PatKind::Tuple(..) => true, PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::Ident(_, _, None) => { match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() { @@ -1833,7 +1833,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx = bind_irrefutable_pat(bcx, &inner_pat, val, cleanup_scope); } } - PatKind::TupleStruct(_, ref sub_pats) => { + PatKind::TupleStruct(_, ref sub_pats, ddpos) => { let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); match opt_def { Some(Def::Variant(enum_id, var_id)) => { @@ -1843,35 +1843,34 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &repr, Disr::from(vinfo.disr_val), val); - if let Some(ref sub_pat) = *sub_pats { - for (i, &argval) in args.vals.iter().enumerate() { - bcx = bind_irrefutable_pat( - bcx, - &sub_pat[i], - MatchInput::from_val(argval), - cleanup_scope); - } + for (i, subpat) in sub_pats.iter() + .enumerate_and_adjust(vinfo.fields.len(), ddpos) { + bcx = bind_irrefutable_pat( + bcx, + subpat, + MatchInput::from_val(args.vals[i]), + cleanup_scope); } } Some(Def::Struct(..)) => { - match *sub_pats { - None => { - // This is a unit-like struct. Nothing to do here. + let expected_len = match *ccx.tcx().pat_ty(&pat) { + ty::TyS{sty: ty::TyStruct(adt_def, _), ..} => { + adt_def.struct_variant().fields.len() } - Some(ref elems) => { - // This is the tuple struct case. - let repr = adt::represent_node(bcx, pat.id); - let val = adt::MaybeSizedValue::sized(val.val); - for (i, elem) in elems.iter().enumerate() { - let fldptr = adt::trans_field_ptr(bcx, &repr, - val, Disr(0), i); - bcx = bind_irrefutable_pat( - bcx, - &elem, - MatchInput::from_val(fldptr), - cleanup_scope); - } + ref ty => { + span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); } + }; + + let repr = adt::represent_node(bcx, pat.id); + let val = adt::MaybeSizedValue::sized(val.val); + for (i, elem) in sub_pats.iter().enumerate_and_adjust(expected_len, ddpos) { + let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i); + bcx = bind_irrefutable_pat( + bcx, + &elem, + MatchInput::from_val(fldptr), + cleanup_scope); } } _ => { @@ -1919,16 +1918,21 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, cleanup_scope); } } - PatKind::Tup(ref elems) => { - let repr = adt::represent_node(bcx, pat.id); - let val = adt::MaybeSizedValue::sized(val.val); - for (i, elem) in elems.iter().enumerate() { - let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i); - bcx = bind_irrefutable_pat( - bcx, - &elem, - MatchInput::from_val(fldptr), - cleanup_scope); + PatKind::Tuple(ref elems, ddpos) => { + match tcx.node_id_to_type(pat.id).sty { + ty::TyTuple(ref tys) => { + let repr = adt::represent_node(bcx, pat.id); + let val = adt::MaybeSizedValue::sized(val.val); + for (i, elem) in elems.iter().enumerate_and_adjust(tys.len(), ddpos) { + let fldptr = adt::trans_field_ptr(bcx, &repr, val, Disr(0), i); + bcx = bind_irrefutable_pat( + bcx, + &elem, + MatchInput::from_val(fldptr), + cleanup_scope); + } + } + ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty), } } PatKind::Box(ref inner) => { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 53cc03198292e..4640377cf8600 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::archive::{ArchiveBuilder, ArchiveConfig}; -use super::linker::{Linker, GnuLinker, MsvcLinker}; +use super::linker::Linker; use super::rpath::RPathConfig; use super::rpath; use super::msvc; @@ -188,6 +188,11 @@ pub fn link_binary(sess: &Session, let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { + // Ignore executable crates if we have -Z no-trans, as they will error. + if sess.opts.no_trans && crate_type == config::CrateTypeExecutable { + continue; + } + if invalid_output_for_target(sess, crate_type) { bug!("invalid output type `{:?}` for target os `{}`", crate_type, sess.opts.target_triple); @@ -637,13 +642,9 @@ fn link_natively(sess: &Session, } { - let mut linker = if sess.target.target.options.is_like_msvc { - Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box - } else { - Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box - }; + let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, trans, outputs); + objects, out_filename, outputs); if !sess.target.target.options.no_compiler_rt { linker.link_staticlib("compiler-rt"); } @@ -712,7 +713,6 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - trans: &CrateTranslation, outputs: &OutputFilenames) { // The default library location, we need this to find the runtime. @@ -731,7 +731,7 @@ fn link_args(cmd: &mut Linker, // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { - cmd.export_symbols(sess, trans, tmpdir, crate_type); + cmd.export_symbols(tmpdir, crate_type); } // When linking a dynamic library, we put the metadata into a section of the diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 50f6366e85c86..cb990ead8e81e 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -15,13 +15,50 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; +use context::SharedCrateContext; +use monomorphize::Instance; + use back::archive; use middle::dependency_format::Linkage; use session::Session; use session::config::CrateType; use session::config; use syntax::ast; -use CrateTranslation; + +/// For all the linkers we support, and information they might +/// need out of the shared crate context before we get rid of it. +pub struct LinkerInfo { + dylib_exports: Vec, + cdylib_exports: Vec +} + +impl<'a, 'tcx> LinkerInfo { + pub fn new(scx: &SharedCrateContext<'a, 'tcx>, + reachable: &[String]) -> LinkerInfo { + LinkerInfo { + dylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeDylib), + cdylib_exports: exported_symbols(scx, reachable, CrateType::CrateTypeCdylib) + } + } + + pub fn to_linker(&'a self, + cmd: &'a mut Command, + sess: &'a Session) -> Box { + if sess.target.target.options.is_like_msvc { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } else { + Box::new(GnuLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box + } + } +} /// Linker abstraction used by back::link to build up the command to invoke a /// linker. @@ -53,16 +90,13 @@ pub trait Linker { fn hint_dynamic(&mut self); fn whole_archives(&mut self); fn no_whole_archives(&mut self); - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType); + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); } pub struct GnuLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> GnuLinker<'a> { @@ -201,11 +235,7 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg("-Wl,-Bdynamic"); } - fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, - tmpdir: &Path, - crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. // @@ -225,13 +255,13 @@ impl<'a> Linker for GnuLinker<'a> { }; let res = (|| -> io::Result<()> { let mut f = BufWriter::new(File::create(&path)?); - for sym in exported_symbols(sess, trans, crate_type) { + for sym in &self.info.cdylib_exports { writeln!(f, "{}{}", prefix, sym)?; } Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::new(); if self.sess.target.target.options.is_like_osx { @@ -245,8 +275,9 @@ impl<'a> Linker for GnuLinker<'a> { } pub struct MsvcLinker<'a> { - pub cmd: &'a mut Command, - pub sess: &'a Session, + cmd: &'a mut Command, + sess: &'a Session, + info: &'a LinkerInfo } impl<'a> Linker for MsvcLinker<'a> { @@ -366,8 +397,6 @@ impl<'a> Linker for MsvcLinker<'a> { // in which case they may continue to transitively be used and hence need // their symbols exported. fn export_symbols(&mut self, - sess: &Session, - trans: &CrateTranslation, tmpdir: &Path, crate_type: CrateType) { let path = tmpdir.join("lib.def"); @@ -378,15 +407,18 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - - for sym in exported_symbols(sess, trans, crate_type) { - writeln!(f, " {}", sym)?; + let symbols = if crate_type == CrateType::CrateTypeCdylib { + &self.info.cdylib_exports + } else { + &self.info.dylib_exports + }; + for symbol in symbols { + writeln!(f, " {}", symbol)?; } - Ok(()) })(); if let Err(e) = res { - sess.fatal(&format!("failed to write lib.def file: {}", e)); + self.sess.fatal(&format!("failed to write lib.def file: {}", e)); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -394,10 +426,23 @@ impl<'a> Linker for MsvcLinker<'a> { } } -fn exported_symbols(sess: &Session, - trans: &CrateTranslation, - crate_type: CrateType) -> Vec { - let mut symbols = trans.reachable.iter().cloned().collect::>(); +fn exported_symbols(scx: &SharedCrateContext, + reachable: &[String], + crate_type: CrateType) + -> Vec { + if !scx.sess().crate_types.borrow().contains(&crate_type) { + return vec![]; + } + + // See explanation in GnuLinker::export_symbols, for + // why we don't ever need dylib symbols on non-MSVC. + if crate_type == CrateType::CrateTypeDylib { + if !scx.sess().target.target.options.is_like_msvc { + return vec![]; + } + } + + let mut symbols = reachable.to_vec(); // If we're producing anything other than a dylib then the `reachable` array // above is the exhaustive set of symbols we should be exporting. @@ -409,10 +454,10 @@ fn exported_symbols(sess: &Session, return symbols } - let cstore = &sess.cstore; - let formats = sess.dependency_formats.borrow(); - let upstream_symbols = formats[&crate_type].iter(); - symbols.extend(upstream_symbols.enumerate().filter_map(|(i, f)| { + let cstore = &scx.sess().cstore; + let formats = scx.sess().dependency_formats.borrow(); + let deps = formats[&crate_type].iter(); + symbols.extend(deps.enumerate().filter_map(|(i, f)| { if *f == Linkage::Static { Some((i + 1) as ast::CrateNum) } else { @@ -420,9 +465,8 @@ fn exported_symbols(sess: &Session, } }).flat_map(|cnum| { cstore.reachable_ids(cnum) - }).map(|did| { - cstore.item_symbol(did) + }).map(|did| -> String { + Instance::mono(scx, did).symbol_name(scx) })); - - return symbols + symbols } diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0cf82d66b2b68..170c8f75b5056 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -97,17 +97,19 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use common::{CrateContext, gensym_name}; +use common::{CrateContext, SharedCrateContext, gensym_name}; use monomorphize::Instance; use util::sha2::{Digest, Sha256}; -use rustc::middle::cstore; +use rustc::middle::{cstore, weak_lang_items}; use rustc::hir::def_id::DefId; +use rustc::hir::map as hir_map; use rustc::ty::{self, TyCtxt, TypeFoldable}; -use rustc::ty::item_path::{ItemPathBuffer, RootMode}; +use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; use rustc::hir::map::definitions::{DefPath, DefPathData}; use std::fmt::Write; +use syntax::attr; use syntax::parse::token::{self, InternedString}; use serialize::hex::ToHex; @@ -116,10 +118,14 @@ pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> def_path_to_string(tcx, &def_path) } -pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { +fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String { let mut s = String::with_capacity(def_path.data.len() * 16); - s.push_str(&tcx.crate_name(def_path.krate)); + if def_path.krate == cstore::LOCAL_CRATE { + s.push_str(&tcx.crate_name(def_path.krate)); + } else { + s.push_str(&tcx.sess.cstore.original_crate_name(def_path.krate)); + } s.push_str("/"); s.push_str(&tcx.crate_disambiguator(def_path.krate)); @@ -134,7 +140,7 @@ pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefP s } -fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, +fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // path to the item this name is for def_path: &DefPath, @@ -152,9 +158,9 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("get_symbol_hash(def_path={:?}, parameters={:?})", def_path, parameters); - let tcx = ccx.tcx(); + let tcx = scx.tcx(); - let mut hash_state = ccx.symbol_hasher().borrow_mut(); + let mut hash_state = scx.symbol_hasher().borrow_mut(); hash_state.reset(); @@ -187,66 +193,100 @@ fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: Option<&str>) - -> String { - let &Instance { def: mut def_id, ref substs } = instance; +impl<'a, 'tcx> Instance<'tcx> { + pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String { + let Instance { def: def_id, ref substs } = self; + + debug!("symbol_name(def_id={:?}, substs={:?})", + def_id, substs); - debug!("exported_name_with_opt_suffix(def_id={:?}, substs={:?}, suffix={:?})", - def_id, substs, suffix); + let node_id = scx.tcx().map.as_local_node_id(def_id); - if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) { - if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) { - def_id = src_def_id; + if let Some(id) = node_id { + if scx.sess().plugin_registrar_fn.get() == Some(id) { + let svh = &scx.link_meta().crate_hash; + let idx = def_id.index; + return scx.sess().generate_plugin_registrar_symbol(svh, idx); + } } - } - let def_path = ccx.tcx().def_path(def_id); - assert_eq!(def_path.krate, def_id.krate); - - // We want to compute the "type" of this item. Unfortunately, some - // kinds of items (e.g., closures) don't have an entry in the - // item-type array. So walk back up the find the closest parent - // that DOES have an entry. - let mut ty_def_id = def_id; - let instance_ty; - loop { - let key = ccx.tcx().def_key(ty_def_id); - match key.disambiguated_data.data { - DefPathData::TypeNs(_) | - DefPathData::ValueNs(_) => { - instance_ty = ccx.tcx().lookup_item_type(ty_def_id); - break; + // FIXME(eddyb) Precompute a custom symbol name based on attributes. + let attrs = scx.tcx().get_attrs(def_id); + let is_foreign = if let Some(id) = node_id { + match scx.tcx().map.get(id) { + hir_map::NodeForeignItem(_) => true, + _ => false } - _ => { - // if we're making a symbol for something, there ought - // to be a value or type-def or something in there - // *somewhere* - ty_def_id.index = key.parent.unwrap_or_else(|| { - bug!("finding type for {:?}, encountered def-id {:?} with no \ - parent", def_id, ty_def_id); - }); + } else { + scx.sess().cstore.is_foreign_item(def_id) + }; + + if let Some(name) = weak_lang_items::link_name(&attrs) { + return name.to_string(); + } + + if is_foreign { + if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") { + return name.to_string(); } + // Don't mangle foreign items. + return scx.tcx().item_name(def_id).as_str().to_string(); } - } - // Erase regions because they may not be deterministic when hashed - // and should not matter anyhow. - let instance_ty = ccx.tcx().erase_regions(&instance_ty.ty); + if let Some(name) = attr::find_export_name_attr(scx.sess().diagnostic(), &attrs) { + // Use provided name + return name.to_string(); + } - let hash = get_symbol_hash(ccx, &def_path, instance_ty, substs.types.as_slice()); + if attr::contains_name(&attrs, "no_mangle") { + // Don't mangle + return scx.tcx().item_name(def_id).as_str().to_string(); + } - let mut buffer = SymbolPathBuffer { - names: Vec::with_capacity(def_path.data.len()) - }; - ccx.tcx().push_item_path(&mut buffer, def_id); + let def_path = scx.tcx().def_path(def_id); + + // We want to compute the "type" of this item. Unfortunately, some + // kinds of items (e.g., closures) don't have an entry in the + // item-type array. So walk back up the find the closest parent + // that DOES have an entry. + let mut ty_def_id = def_id; + let instance_ty; + loop { + let key = scx.tcx().def_key(ty_def_id); + match key.disambiguated_data.data { + DefPathData::TypeNs(_) | + DefPathData::ValueNs(_) => { + instance_ty = scx.tcx().lookup_item_type(ty_def_id); + break; + } + _ => { + // if we're making a symbol for something, there ought + // to be a value or type-def or something in there + // *somewhere* + ty_def_id.index = key.parent.unwrap_or_else(|| { + bug!("finding type for {:?}, encountered def-id {:?} with no \ + parent", def_id, ty_def_id); + }); + } + } + } - if let Some(suffix) = suffix { - buffer.push(suffix); - } + // Erase regions because they may not be deterministic when hashed + // and should not matter anyhow. + let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); + + let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); + + let mut buffer = SymbolPathBuffer { + names: Vec::with_capacity(def_path.data.len()) + }; - mangle(buffer.names.into_iter(), Some(&hash[..])) + item_path::with_forced_absolute_paths(|| { + scx.tcx().push_item_path(&mut buffer, def_id); + }); + + mangle(buffer.names.into_iter(), Some(&hash[..])) + } } struct SymbolPathBuffer { @@ -264,19 +304,6 @@ impl ItemPathBuffer for SymbolPathBuffer { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>) - -> String { - exported_name_with_opt_suffix(ccx, instance, None) -} - -pub fn exported_name_with_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: &Instance<'tcx>, - suffix: &str) - -> String { - exported_name_with_opt_suffix(ccx, instance, Some(suffix)) -} - /// Only symbols that are invisible outside their compilation unit should use a /// name generated by this function. pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -289,7 +316,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx> data: vec![], krate: cstore::LOCAL_CRATE, }; - let hash = get_symbol_hash(ccx, &def_path, t, &[]); + let hash = get_symbol_hash(ccx.shared(), &def_path, t, &[]); mangle(path.iter().cloned(), Some(&hash[..])) } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 992e07fa7449d..712805061ea8c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -30,14 +30,14 @@ pub use self::ValueOrigin::*; use super::CrateTranslation; use super::ModuleTranslation; -use back::{link, symbol_names}; +use back::link; +use back::linker::LinkerInfo; use lint; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; use rustc::cfg; use rustc::hir::def_id::DefId; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; -use middle::weak_lang_items; use rustc::hir::pat_util::simple_name; use rustc::ty::subst::{self, Substs}; use rustc::traits; @@ -1660,24 +1660,32 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { self.schedule_drop_mem(arg_scope_id, llarg, arg_ty, None); datum::Datum::new(llarg, - arg_ty, - datum::Lvalue::new("FunctionContext::bind_args")) + arg_ty, + datum::Lvalue::new("FunctionContext::bind_args")) } else { - unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "", - uninit_reason, - arg_scope_id, |bcx, dst| { - debug!("FunctionContext::bind_args: {:?}: {:?}", hir_arg, arg_ty); + let lltmp = if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { + let lltemp = alloc_ty(bcx, arg_ty, ""); let b = &bcx.build(); - if common::type_is_fat_ptr(bcx.tcx(), arg_ty) { - let meta = &self.fn_ty.args[idx]; - idx += 1; - arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, dst)); - meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, dst)); - } else { - arg.store_fn_arg(b, &mut llarg_idx, dst); - } - bcx - })) + // we pass fat pointers as two words, but we want to + // represent them internally as a pointer to two words, + // so make an alloca to store them in. + let meta = &self.fn_ty.args[idx]; + idx += 1; + arg.store_fn_arg(b, &mut llarg_idx, expr::get_dataptr(bcx, lltemp)); + meta.store_fn_arg(b, &mut llarg_idx, expr::get_meta(bcx, lltemp)); + lltemp + } else { + // otherwise, arg is passed by value, so store it into a temporary. + let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx())); + let lltemp = alloca(bcx, llarg_ty, ""); + let b = &bcx.build(); + arg.store_fn_arg(b, &mut llarg_idx, lltemp); + // And coerce the temporary into the type we expect. + b.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to()) + }; + bcx.fcx.schedule_drop_mem(arg_scope_id, lltmp, arg_ty, None); + datum::Datum::new(lltmp, arg_ty, + datum::Lvalue::new("bind_args")) } } else { // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for. @@ -1712,16 +1720,19 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { }; let pat = &hir_arg.pat; - bcx = if let Some(name) = simple_name(pat) { - // Generate nicer LLVM for the common case of fn a pattern - // like `x: T` - set_value_name(arg_datum.val, &bcx.name(name)); - self.lllocals.borrow_mut().insert(pat.id, arg_datum); - bcx - } else { - // General path. Copy out the values that are used in the - // pattern. - _match::bind_irrefutable_pat(bcx, pat, arg_datum.match_input(), arg_scope_id) + bcx = match simple_name(pat) { + // The check for alloca is necessary because above for the immediate argument case + // we had to cast. At this point arg_datum is not an alloca anymore and thus + // breaks debuginfo if we allow this optimisation. + Some(name) + if unsafe { llvm::LLVMIsAAllocaInst(arg_datum.val) != ::std::ptr::null_mut() } => { + // Generate nicer LLVM for the common case of fn a pattern + // like `x: T` + set_value_name(arg_datum.val, &bcx.name(name)); + self.lllocals.borrow_mut().insert(pat.id, arg_datum); + bcx + }, + _ => _match::bind_irrefutable_pat(bcx, pat, arg_datum.match_input(), arg_scope_id) }; debuginfo::create_argument_metadata(bcx, hir_arg); } @@ -2344,15 +2355,6 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) { set_global_section(ccx, g, item); update_linkage(ccx, g, Some(item.id), OriginalTranslation); } - hir::ItemForeignMod(ref m) => { - if m.abi == Abi::RustIntrinsic || m.abi == Abi::PlatformIntrinsic { - return; - } - for fi in &m.items { - let lname = imported_name(fi.name, &fi.attrs).to_string(); - ccx.item_symbols().borrow_mut().insert(fi.id, lname); - } - } _ => {} } } @@ -2437,60 +2439,12 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) { } } -pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - instance: Instance<'tcx>, - attrs: &[ast::Attribute]) - -> String { - let id = ccx.tcx().map.as_local_node_id(instance.def).unwrap(); - - match ccx.external_srcs().borrow().get(&id) { - Some(&did) => { - let sym = ccx.sess().cstore.item_symbol(did); - debug!("found item {} in other crate...", sym); - return sym; - } - None => {} - } - - match attr::find_export_name_attr(ccx.sess().diagnostic(), attrs) { - // Use provided name - Some(name) => name.to_string(), - _ => { - if attr::contains_name(attrs, "no_mangle") { - // Don't mangle - ccx.tcx().map.name(id).as_str().to_string() - } else { - match weak_lang_items::link_name(attrs) { - Some(name) => name.to_string(), - None => { - // Usual name mangling - symbol_names::exported_name(ccx, &instance) - } - } - } - } - } -} - -pub fn imported_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString { - match attr::first_attr_value_str_by_name(attrs, "link_name") { - Some(ln) => ln.clone(), - None => match weak_lang_items::link_name(attrs) { - Some(name) => name, - None => name.as_str(), - } - } -} - fn contains_null(s: &str) -> bool { s.bytes().any(|b| b == 0) } -pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, - krate: &hir::Crate, - reachable: &NodeSet, - mir_map: &MirMap<'tcx>) - -> Vec { +fn write_metadata(cx: &SharedCrateContext, + reachable_ids: &NodeSet) -> Vec { use flate; let any_library = cx.sess() @@ -2505,11 +2459,10 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, let cstore = &cx.tcx().sess.cstore; let metadata = cstore.encode_metadata(cx.tcx(), cx.export_map(), - cx.item_symbols(), cx.link_meta(), - reachable, - mir_map, - krate); + reachable_ids, + cx.mir_map(), + cx.tcx().map.krate()); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); @@ -2670,10 +2623,7 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter { /// This list is later used by linkers to determine the set of symbols needed to /// be exposed from a dynamic library and it's also encoded into the metadata. pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet { - scx.reachable().iter().map(|x| *x).filter(|id| { - // First, only worry about nodes which have a symbol name - scx.item_symbols().borrow().contains_key(id) - }).filter(|&id| { + scx.reachable().iter().map(|x| *x).filter(|&id| { // Next, we want to ignore some FFI functions that are not exposed from // this crate. Reachable FFI functions can be lumped into two // categories: @@ -2691,7 +2641,20 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet { hir_map::NodeForeignItem(..) => { scx.sess().cstore.is_statically_included_foreign_item(id) } - _ => true, + + // Only consider nodes that actually have exported symbols. + hir_map::NodeItem(&hir::Item { + node: hir::ItemStatic(..), .. }) | + hir_map::NodeItem(&hir::Item { + node: hir::ItemFn(..), .. }) | + hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(..), .. }) => { + let def_id = scx.tcx().map.local_def_id(id); + let scheme = scx.tcx().lookup_item_type(def_id); + scheme.generics.types.is_empty() + } + + _ => false } }).collect() } @@ -2733,6 +2696,19 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_overflow, check_dropflag); + let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); + + // Translate the metadata. + let metadata = time(tcx.sess.time_passes(), "write metadata", || { + write_metadata(&shared_ccx, &reachable_symbol_ids) + }); + + let metadata_module = ModuleTranslation { + llcx: shared_ccx.metadata_llcx(), + llmod: shared_ccx.metadata_llmod(), + }; + let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); + let codegen_units = collect_and_partition_translation_items(&shared_ccx); let codegen_unit_count = codegen_units.len(); assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count || @@ -2740,6 +2716,24 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units); + let modules = crate_context_list.iter() + .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) + .collect(); + + // Skip crate items and just output metadata in -Z no-trans mode. + if tcx.sess.opts.no_trans { + let linker_info = LinkerInfo::new(&shared_ccx, &[]); + return CrateTranslation { + modules: modules, + metadata_module: metadata_module, + link: link_meta, + metadata: metadata, + reachable: vec![], + no_builtins: no_builtins, + linker_info: linker_info + }; + } + { let ccx = crate_context_list.get_ccx(0); @@ -2769,13 +2763,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); - - // Translate the metadata. - let metadata = time(tcx.sess.time_passes(), "write metadata", || { - write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map) - }); - if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); println!("--- trans stats ---"); @@ -2805,13 +2792,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let modules = crate_context_list.iter() - .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) - .collect(); - let sess = shared_ccx.sess(); - let mut reachable_symbols = reachable_symbol_ids.iter().map(|id| { - shared_ccx.item_symbols().borrow()[id].to_string() + let mut reachable_symbols = reachable_symbol_ids.iter().map(|&id| { + let def_id = shared_ccx.tcx().map.local_def_id(id); + Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx) }).collect::>(); if sess.entry_fn.borrow().is_some() { reachable_symbols.push("main".to_string()); @@ -2834,7 +2818,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable_symbols.extend(syms.into_iter().filter(|did| { sess.cstore.is_extern_item(shared_ccx.tcx(), *did) }).map(|did| { - sess.cstore.item_symbol(did) + Instance::mono(&shared_ccx, did).symbol_name(&shared_ccx) })); } @@ -2848,12 +2832,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, create_imps(&crate_context_list); } - let metadata_module = ModuleTranslation { - llcx: shared_ccx.metadata_llcx(), - llmod: shared_ccx.metadata_llmod(), - }; - let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); - + let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -2861,6 +2840,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, + linker_info: linker_info } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index c0c5ea818b2d7..d7f565a9cd449 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -499,43 +499,20 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return immediate_rvalue(llfn, fn_ptr_ty); } - let attrs; let local_id = ccx.tcx().map.as_local_node_id(def_id); - let maybe_node = local_id.and_then(|id| tcx.map.find(id)); - let (sym, attrs, local_item) = match maybe_node { + let local_item = match local_id.and_then(|id| tcx.map.find(id)) { Some(hir_map::NodeItem(&hir::Item { - ref attrs, id, span, node: hir::ItemFn(..), .. + span, node: hir::ItemFn(..), .. })) | Some(hir_map::NodeTraitItem(&hir::TraitItem { - ref attrs, id, span, node: hir::MethodTraitItem(_, Some(_)), .. + span, node: hir::MethodTraitItem(_, Some(_)), .. })) | Some(hir_map::NodeImplItem(&hir::ImplItem { - ref attrs, id, span, node: hir::ImplItemKind::Method(..), .. + span, node: hir::ImplItemKind::Method(..), .. })) => { - let sym = exported_name(ccx, instance, attrs); - - if declare::get_defined_value(ccx, &sym).is_some() { - ccx.sess().span_fatal(span, - &format!("symbol `{}` is already defined", sym)); - } - - (sym, &attrs[..], Some(id)) - } - - Some(hir_map::NodeForeignItem(&hir::ForeignItem { - ref attrs, name, node: hir::ForeignItemFn(..), .. - })) => { - (imported_name(name, attrs).to_string(), &attrs[..], None) - } - - None => { - attrs = ccx.sess().cstore.item_attrs(def_id); - (ccx.sess().cstore.item_symbol(def_id), &attrs[..], None) - } - - ref variant => { - bug!("get_fn: unexpected variant: {:?}", variant) + Some(span) } + _ => None }; // This is subtle and surprising, but sometimes we have to bitcast @@ -562,8 +539,16 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // reference. It also occurs when testing libcore and in some // other weird situations. Annoying. + let sym = instance.symbol_name(ccx.shared()); let llptrty = type_of::type_of(ccx, fn_ptr_ty); let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) { + if let Some(span) = local_item { + if declare::get_defined_value(ccx, &sym).is_some() { + ccx.sess().span_fatal(span, + &format!("symbol `{}` is already defined", sym)); + } + } + if common::val_ty(llfn) != llptrty { if local_item.is_some() { bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}", @@ -580,7 +565,8 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, assert_eq!(common::val_ty(llfn), llptrty); debug!("get_fn: not casting pointer!"); - attributes::from_fn_attrs(ccx, attrs, llfn); + let attrs = ccx.tcx().get_attrs(def_id); + attributes::from_fn_attrs(ccx, &attrs, llfn); if local_item.is_some() { // FIXME(eddyb) Doubt all extern fn should allow unwinding. attributes::unwind(llfn, true); @@ -589,11 +575,6 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn }; - // Always insert into item_symbols, in case this item is exported. - if let Some(id) = local_item { - ccx.item_symbols().borrow_mut().insert(id, sym); - } - ccx.instances().borrow_mut().insert(instance, llfn); immediate_rvalue(llfn, fn_ptr_ty) diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 1c393f8091eee..5e0d34c2a674d 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -150,7 +150,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, return llfn; } - let symbol = symbol_names::exported_name(ccx, &instance); + let symbol = instance.symbol_name(ccx.shared()); // Compute the rust-call form of the closure call method. let sig = &tcx.closure_type(closure_id, substs).sig; diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d278c3c8320fd..bbc01f0935f2b 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -523,7 +523,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let ty = monomorphize::apply_param_substs(self.scx.tcx(), self.param_substs, &ty); - let ty = self.scx.tcx().erase_regions(&ty); + assert!(ty.is_normalized_for_trans()); let ty = glue::get_drop_glue_type(self.scx.tcx(), ty); self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty))); } @@ -859,6 +859,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, &callee_substs); let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id)); + let trait_ref = tcx.normalize_associated_type(&trait_ref); let vtbl = fulfill_obligation(scx, DUMMY_SP, trait_ref); // Now that we know which impl is being used, we can dispatch to @@ -992,11 +993,8 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let concrete_substs = monomorphize::apply_param_substs(tcx, param_substs, &fn_substs); - let concrete_substs = tcx.erase_regions(&concrete_substs); - - let trans_item = - TransItem::Fn(Instance::new(def_id, concrete_substs)); - return trans_item; + assert!(concrete_substs.is_normalized_for_trans()); + TransItem::Fn(Instance::new(def_id, concrete_substs)) } /// Creates a `TransItem` for each method that is referenced by the vtable for @@ -1034,10 +1032,14 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, } else { None } - }) - .collect::>(); + }); + + output.extend(items); - output.extend(items.into_iter()); + // Also add the destructor + let dg_type = glue::get_drop_glue_type(scx.tcx(), + trait_ref.self_ty()); + output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type))); } _ => { /* */ } } @@ -1234,7 +1236,7 @@ pub enum TransItemState { } pub fn collecting_debug_information(scx: &SharedCrateContext) -> bool { - return scx.sess().opts.cg.debug_assertions == Some(true) && + return cfg!(debug_assertions) && scx.sess().opts.debugging_opts.print_trans_items.is_some(); } diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 3e876eb3d7de0..bd36c18a47ee2 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -19,7 +19,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use {abi, adt, closure, debuginfo, expr, machine}; -use base::{self, exported_name, imported_name, push_ctxt}; +use base::{self, push_ctxt}; use callee::Callee; use collector; use trans_item::TransItem; @@ -1017,34 +1017,31 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) return Datum::new(g, ty, Lvalue::new("static")); } + let sym = instance.symbol_name(ccx.shared()); + let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) { let llty = type_of::type_of(ccx, ty); match ccx.tcx().map.get(id) { hir_map::NodeItem(&hir::Item { - ref attrs, span, node: hir::ItemStatic(..), .. + span, node: hir::ItemStatic(..), .. }) => { // If this static came from an external crate, then // we need to get the symbol from metadata instead of // using the current crate's name/version // information in the hash of the symbol - let sym = exported_name(ccx, instance, attrs); debug!("making {}", sym); // Create the global before evaluating the initializer; // this is necessary to allow recursive statics. - let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { + declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { ccx.sess().span_fatal(span, &format!("symbol `{}` is already defined", sym)) - }); - - ccx.item_symbols().borrow_mut().insert(id, sym); - g + }) } hir_map::NodeForeignItem(&hir::ForeignItem { - ref attrs, name, span, node: hir::ForeignItemStatic(..), .. + ref attrs, span, node: hir::ForeignItemStatic(..), .. }) => { - let ident = imported_name(name, attrs); let g = if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "linkage") { // If this is a static with a linkage specified, then we need to handle @@ -1066,7 +1063,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = declare::declare_global(ccx, &ident, llty2); + let g1 = declare::declare_global(ccx, &sym, llty2); llvm::SetLinkage(g1, linkage); // Declare an internal global `extern_with_linkage_foo` which @@ -1076,10 +1073,10 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) // `extern_with_linkage_foo` will instead be initialized to // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&ident); + real_name.push_str(&sym); let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{ ccx.sess().span_fatal(span, - &format!("symbol `{}` is already defined", ident)) + &format!("symbol `{}` is already defined", sym)) }); llvm::SetLinkage(g2, llvm::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); @@ -1087,7 +1084,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } } else { // Generate an external declaration. - declare::declare_global(ccx, &ident, llty) + declare::declare_global(ccx, &sym, llty) }; for attr in attrs { @@ -1104,8 +1101,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } else { // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? // FIXME(nagisa): investigate whether it can be changed into define_global - let name = ccx.sess().cstore.item_symbol(def_id); - let g = declare::declare_global(ccx, &name, type_of::type_of(ccx, ty)); + let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty)); // Thread-local statics in some other crate need to *always* be linked // against in a thread-local fashion, so we need to be sure to apply the // thread-local attribute locally if it was present remotely. If we diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 4d6c4cdcc6b07..1ddcbc79aed5f 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -71,7 +71,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { export_map: ExportMap, reachable: NodeSet, - item_symbols: RefCell>, link_meta: LinkMeta, symbol_hasher: RefCell, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -395,7 +394,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { metadata_llcx: metadata_llcx, export_map: export_map, reachable: reachable, - item_symbols: RefCell::new(NodeMap()), link_meta: link_meta, symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, @@ -439,10 +437,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { &self.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.item_symbols - } - pub fn trait_cache(&self) -> &RefCell>> { &self.trait_cache } @@ -504,6 +498,14 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { scheme.generics.regions.map(|_| ty::ReStatic))) } + pub fn symbol_hasher(&self) -> &RefCell { + &self.symbol_hasher + } + + pub fn mir_map(&self) -> &MirMap<'tcx> { + &self.mir_map + } + pub fn metadata_symbol_name(&self) -> String { format!("rust_metadata_{}_{}", self.link_meta().crate_name, @@ -716,10 +718,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.shared.reachable } - pub fn item_symbols<'a>(&'a self) -> &'a RefCell> { - &self.shared.item_symbols - } - pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { &self.shared.link_meta } diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index ba592382d1a79..aec43e69e5182 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -318,13 +318,11 @@ fn walk_pattern(cx: &CrateContext, scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata); } - PatKind::TupleStruct(_, ref sub_pats_opt) => { + PatKind::TupleStruct(_, ref sub_pats, _) => { scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata); - if let Some(ref sub_pats) = *sub_pats_opt { - for p in sub_pats { - walk_pattern(cx, &p, scope_stack, scope_map); - } + for p in sub_pats { + walk_pattern(cx, &p, scope_stack, scope_map); } } @@ -343,7 +341,7 @@ fn walk_pattern(cx: &CrateContext, } } - PatKind::Tup(ref sub_pats) => { + PatKind::Tuple(ref sub_pats, _) => { scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata); for sub_pat in sub_pats { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 10e33195305f6..64e178bf91962 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -20,7 +20,7 @@ use llvm::{ValueRef, get_param}; use middle::lang_items::ExchangeFreeFnLangItem; use rustc::ty::subst::{Substs}; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use abi::{Abi, FnType}; use adt; use adt::GetDtorType; // for tcx.dtor_type() @@ -96,10 +96,12 @@ pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { + assert!(t.is_normalized_for_trans()); + // Even if there is no dtor for t, there might be one deeper down and we // might need to pass in the vtable ptr. if !type_is_sized(tcx, t) { - return tcx.erase_regions(&t); + return t; } // FIXME (#22815): note that type_needs_drop conservatively @@ -123,11 +125,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `Box` does not allocate. tcx.types.i8 } else { - tcx.erase_regions(&t) + t } }) } - _ => tcx.erase_regions(&t) + _ => t } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index bccb5aa050b51..0188a6d54de2d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -145,6 +145,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub linker_info: back::linker::LinkerInfo } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index b98e04e51c007..ffc14b4468b5b 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -327,10 +327,10 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, llarg_idx += 1; llarg } else { - let lltemp = bcx.with_block(|bcx| { - base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) - }); if common::type_is_fat_ptr(tcx, arg_ty) { + let lltemp = bcx.with_block(|bcx| { + base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) + }); // we pass fat pointers as two words, but we want to // represent them internally as a pointer to two words, // so make an alloca to store them in. @@ -338,12 +338,17 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, idx += 1; arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp)); meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp)); + lltemp } else { - // otherwise, arg is passed by value, so make a - // temporary and store it there + // otherwise, arg is passed by value, so store it into a temporary. + let llarg_ty = arg.cast.unwrap_or(arg.memory_ty(bcx.ccx())); + let lltemp = bcx.with_block(|bcx| { + base::alloca(bcx, llarg_ty, &format!("arg{}", arg_index)) + }); arg.store_fn_arg(bcx, &mut llarg_idx, lltemp); + // And coerce the temporary into the type we expect. + bcx.pointercast(lltemp, arg.memory_ty(bcx.ccx()).ptr_to()) } - lltemp }; bcx.with_block(|bcx| arg_scope.map(|scope| { // Is this a regular argument? diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index dfaf84ecef023..b0f8edac0a623 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use back::symbol_names; use llvm::ValueRef; use llvm; use rustc::hir::def_id::DefId; @@ -88,7 +87,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, monomorphizing.insert(fn_id, depth + 1); } - let symbol = symbol_names::exported_name(ccx, &instance); + let symbol = instance.symbol_name(ccx.shared()); debug!("monomorphize_fn mangled to {}", symbol); assert!(declare::get_defined_value(ccx, &symbol).is_none()); diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 098ba759247be..2ded643ef4fdd 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -228,6 +228,17 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } + // always ensure we have at least one CGU; otherwise, if we have a + // crate with just types (for example), we could wind up with no CGU + if codegen_units.is_empty() { + let codegen_unit_name = InternedString::new(FALLBACK_CODEGEN_UNIT); + codegen_units.entry(codegen_unit_name.clone()) + .or_insert_with(|| CodegenUnit { + name: codegen_unit_name.clone(), + items: FnvHashMap(), + }); + } + PreInliningPartitioning { codegen_units: codegen_units.into_iter() .map(|(_, codegen_unit)| codegen_unit) diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs index 284a227276dd0..11e9e9f3204a2 100644 --- a/src/librustc_trans/symbol_names_test.rs +++ b/src/librustc_trans/symbol_names_test.rs @@ -14,7 +14,6 @@ //! item-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. -use back::symbol_names; use rustc::hir; use rustc::hir::intravisit::{self, Visitor}; use syntax::ast; @@ -53,7 +52,7 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { if attr.check_name(SYMBOL_NAME) { // for now, can only use on monomorphic names let instance = Instance::mono(self.ccx.shared(), def_id); - let name = symbol_names::exported_name(self.ccx, &instance); + let name = instance.symbol_name(self.ccx.shared()); tcx.sess.span_err(attr.span, &format!("symbol-name({})", name)); } else if attr.check_name(ITEM_PATH) { let path = tcx.item_path_str(def_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1df12b63e0a50..fc1abb56d5abc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1833,8 +1833,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // lifetime elision, we can determine it in two ways. First (determined // here), if self is by-reference, then the implied output region is the // region of the self parameter. - let explicit_self = decl.inputs.get(0).and_then(hir::Arg::to_self); - let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, explicit_self) { + let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) { (Some(untransformed_self_ty), Some(explicit_self)) => { let self_type = self.determine_self_type(&rb, untransformed_self_ty, &explicit_self); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 10c8ea84bfd64..9030a6f222b85 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -11,7 +11,7 @@ use hir::def::{self, Def}; use rustc::infer::{self, InferOk, TypeOrigin}; use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding}; -use hir::pat_util::pat_is_resolved_const; +use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; use check::{FnCtxt, Expectation}; @@ -213,13 +213,13 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { } PatKind::Ident(_, ref path, _) => { let path = hir::Path::from_name(path.span, path.node); - self.check_pat_enum(pat, &path, Some(&[]), expected, false); + self.check_pat_enum(pat, &path, &[], None, expected, false); } - PatKind::TupleStruct(ref path, ref subpats) => { - self.check_pat_enum(pat, path, subpats.as_ref().map(|v| &v[..]), expected, true); + PatKind::TupleStruct(ref path, ref subpats, ddpos) => { + self.check_pat_enum(pat, path, &subpats, ddpos, expected, true); } PatKind::Path(ref path) => { - self.check_pat_enum(pat, path, Some(&[]), expected, false); + self.check_pat_enum(pat, path, &[], None, expected, false); } PatKind::QPath(ref qself, ref path) => { let self_ty = self.to_ty(&qself.ty); @@ -260,14 +260,23 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { PatKind::Struct(ref path, ref fields, etc) => { self.check_pat_struct(pat, path, fields, etc, expected); } - PatKind::Tup(ref elements) => { - let element_tys: Vec<_> = - (0..elements.len()).map(|_| self.next_ty_var()).collect(); + PatKind::Tuple(ref elements, ddpos) => { + let mut expected_len = elements.len(); + if ddpos.is_some() { + // Require known type only when `..` is present + if let ty::TyTuple(ref tys) = + self.structurally_resolved_type(pat.span, expected).sty { + expected_len = tys.len(); + } + } + let max_len = cmp::max(expected_len, elements.len()); + + let element_tys: Vec<_> = (0 .. max_len).map(|_| self.next_ty_var()).collect(); let pat_ty = tcx.mk_tup(element_tys.clone()); self.write_ty(pat.id, pat_ty); self.demand_eqtype(pat.span, expected, pat_ty); - for (element_pat, element_ty) in elements.iter().zip(element_tys) { - self.check_pat(&element_pat, element_ty); + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat(elem, &element_tys[i]); } } PatKind::Box(ref inner) => { @@ -615,7 +624,8 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { fn check_pat_enum(&self, pat: &hir::Pat, path: &hir::Path, - subpats: Option<&'gcx [P]>, + subpats: &'gcx [P], + ddpos: Option, expected: Ty<'tcx>, is_tuple_struct_pat: bool) { @@ -628,12 +638,9 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); self.write_error(pat.id); - if let Some(subpats) = subpats { - for pat in subpats { - self.check_pat(&pat, tcx.types.err); - } + for pat in subpats { + self.check_pat(&pat, tcx.types.err); } - return; } }; @@ -670,15 +677,12 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { }; self.instantiate_path(segments, path_scheme, &ctor_predicates, opt_ty, def, pat.span, pat.id); - let report_bad_struct_kind = |is_warning| { bad_struct_kind_err(tcx.sess, pat, path, is_warning); if is_warning { return; } self.write_error(pat.id); - if let Some(subpats) = subpats { - for pat in subpats { - self.check_pat(&pat, tcx.types.err); - } + for pat in subpats { + self.check_pat(&pat, tcx.types.err); } }; @@ -715,11 +719,13 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { }; match (is_tuple_struct_pat, variant.kind()) { - (true, ty::VariantKind::Unit) => { + (true, ty::VariantKind::Unit) if subpats.is_empty() && ddpos.is_some() => { // Matching unit structs with tuple variant patterns (`UnitVariant(..)`) // is allowed for backward compatibility. report_bad_struct_kind(true); } + (true, ty::VariantKind::Unit) | + (false, ty::VariantKind::Tuple) | (_, ty::VariantKind::Struct) => { report_bad_struct_kind(false); return @@ -727,30 +733,21 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { _ => {} } - if let Some(subpats) = subpats { - if subpats.len() == variant.fields.len() { - for (subpat, field) in subpats.iter().zip(&variant.fields) { - let field_ty = self.field_ty(subpat.span, field, expected_substs); - self.check_pat(&subpat, field_ty); - } - } else if variant.fields.is_empty() { - span_err!(tcx.sess, pat.span, E0024, - "this pattern has {} field{}, but the corresponding {} has no fields", - subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name); - - for pat in subpats { - self.check_pat(&pat, tcx.types.err); - } - } else { - span_err!(tcx.sess, pat.span, E0023, - "this pattern has {} field{}, but the corresponding {} has {} field{}", - subpats.len(), if subpats.len() == 1 {""} else {"s"}, - kind_name, - variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"}); - - for pat in subpats { - self.check_pat(&pat, tcx.types.err); - } + if subpats.len() == variant.fields.len() || + subpats.len() < variant.fields.len() && ddpos.is_some() { + for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { + let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs); + self.check_pat(&subpat, field_ty); + } + } else { + span_err!(tcx.sess, pat.span, E0023, + "this pattern has {} field{}, but the corresponding {} has {} field{}", + subpats.len(), if subpats.len() == 1 {""} else {"s"}, + kind_name, + variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"}); + + for pat in subpats { + self.check_pat(&pat, tcx.types.err); } } } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs new file mode 100644 index 0000000000000..9e2b7cd034652 --- /dev/null +++ b/src/librustc_typeck/check/autoderef.rs @@ -0,0 +1,210 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use astconv::AstConv; + +use super::FnCtxt; + +use rustc::traits; +use rustc::ty::{self, Ty, TraitRef}; +use rustc::ty::{ToPredicate, TypeFoldable}; +use rustc::ty::{MethodCall, MethodCallee}; +use rustc::ty::subst::Substs; +use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; +use rustc::hir; + +use syntax::codemap::Span; +use syntax::parse::token; + +#[derive(Copy, Clone, Debug)] +enum AutoderefKind { + Builtin, + Overloaded +} + +pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> { + fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + steps: Vec<(Ty<'tcx>, AutoderefKind)>, + cur_ty: Ty<'tcx>, + obligations: Vec>, + at_start: bool, + span: Span +} + +impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { + type Item = (Ty<'tcx>, usize); + + fn next(&mut self) -> Option { + let tcx = self.fcx.tcx; + + debug!("autoderef: steps={:?}, cur_ty={:?}", + self.steps, self.cur_ty); + if self.at_start { + self.at_start = false; + debug!("autoderef stage #0 is {:?}", self.cur_ty); + return Some((self.cur_ty, 0)); + } + + if self.steps.len() == tcx.sess.recursion_limit.get() { + // We've reached the recursion limit, error gracefully. + span_err!(tcx.sess, self.span, E0055, + "reached the recursion limit while auto-dereferencing {:?}", + self.cur_ty); + return None; + } + + if self.cur_ty.is_ty_var() { + return None; + } + + // Otherwise, deref if type is derefable: + let (kind, new_ty) = if let Some(mt) = self.cur_ty.builtin_deref(false, NoPreference) { + (AutoderefKind::Builtin, mt.ty) + } else { + match self.overloaded_deref_ty(self.cur_ty) { + Some(ty) => (AutoderefKind::Overloaded, ty), + _ => return None + } + }; + + if new_ty.references_error() { + return None; + } + + self.steps.push((self.cur_ty, kind)); + debug!("autoderef stage #{:?} is {:?} from {:?}", self.steps.len(), + new_ty, (self.cur_ty, kind)); + self.cur_ty = new_ty; + + Some((self.cur_ty, self.steps.len())) + } +} + +impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { + fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { + debug!("overloaded_deref_ty({:?})", ty); + + let tcx = self.fcx.tcx(); + + // + let trait_ref = TraitRef { + def_id: match tcx.lang_items.deref_trait() { + Some(f) => f, + None => return None + }, + substs: tcx.mk_substs(Substs::new_trait(vec![], vec![], self.cur_ty)) + }; + + let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); + + let mut selcx = traits::SelectionContext::new(self.fcx); + let obligation = traits::Obligation::new(cause.clone(), trait_ref.to_predicate()); + if !selcx.evaluate_obligation(&obligation) { + debug!("overloaded_deref_ty: cannot match obligation"); + return None; + } + + let normalized = traits::normalize_projection_type( + &mut selcx, + ty::ProjectionTy { + trait_ref: trait_ref, + item_name: token::intern("Target") + }, + cause, + 0 + ); + + debug!("overloaded_deref_ty({:?}) = {:?}", ty, normalized); + self.obligations.extend(normalized.obligations); + + Some(self.fcx.resolve_type_vars_if_possible(&normalized.value)) + } + + pub fn unambiguous_final_ty(&self) -> Ty<'tcx> { + self.fcx.structurally_resolved_type(self.span, self.cur_ty) + } + + pub fn finalize<'b, I>(self, pref: LvaluePreference, exprs: I) + where I: IntoIterator + { + let methods : Vec<_> = self.steps.iter().map(|&(ty, kind)| { + if let AutoderefKind::Overloaded = kind { + self.fcx.try_overloaded_deref(self.span, None, ty, pref) + } else { + None + } + }).collect(); + + debug!("finalize({:?}) - {:?},{:?}", pref, methods, self.obligations); + + for expr in exprs { + debug!("finalize - finalizing #{} - {:?}", expr.id, expr); + for (n, method) in methods.iter().enumerate() { + if let &Some(method) = method { + let method_call = MethodCall::autoderef(expr.id, n as u32); + self.fcx.tables.borrow_mut().method_map.insert(method_call, method); + } + } + } + + for obligation in self.obligations { + self.fcx.register_predicate(obligation); + } + } +} + +impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { + pub fn autoderef(&'a self, + span: Span, + base_ty: Ty<'tcx>) + -> Autoderef<'a, 'gcx, 'tcx> + { + Autoderef { + fcx: self, + steps: vec![], + cur_ty: self.resolve_type_vars_if_possible(&base_ty), + obligations: vec![], + at_start: true, + span: span + } + } + + pub fn try_overloaded_deref(&self, + span: Span, + base_expr: Option<&hir::Expr>, + base_ty: Ty<'tcx>, + lvalue_pref: LvaluePreference) + -> Option> + { + debug!("try_overloaded_deref({:?},{:?},{:?},{:?})", + span, base_expr, base_ty, lvalue_pref); + // Try DerefMut first, if preferred. + let method = match (lvalue_pref, self.tcx.lang_items.deref_mut_trait()) { + (PreferMutLvalue, Some(trait_did)) => { + self.lookup_method_in_trait(span, base_expr, + token::intern("deref_mut"), trait_did, + base_ty, None) + } + _ => None + }; + + // Otherwise, fall back to Deref. + let method = match (method, self.tcx.lang_items.deref_trait()) { + (None, Some(trait_did)) => { + self.lookup_method_in_trait(span, base_expr, + token::intern("deref"), trait_did, + base_ty, None) + } + (method, _) => method + }; + + method + } +} diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7493ca70f5567..417b2fafecfd3 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::{DeferredCallResolution, Expectation, FnCtxt, - TupleArgumentsFlag, UnresolvedTypeAction}; + TupleArgumentsFlag}; use CrateCtxt; use middle::cstore::LOCAL_CRATE; @@ -72,15 +72,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { self.check_expr(callee_expr); let original_callee_ty = self.expr_ty(callee_expr); - let (callee_ty, _, result) = - self.autoderef(callee_expr.span, - original_callee_ty, - || Some(callee_expr), - UnresolvedTypeAction::Error, - LvaluePreference::NoPreference, - |adj_ty, idx| { - self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx) - }); + + let mut autoderef = self.autoderef(callee_expr.span, original_callee_ty); + let result = autoderef.by_ref().flat_map(|(adj_ty, idx)| { + self.try_overloaded_call_step(call_expr, callee_expr, adj_ty, idx) + }).next(); + let callee_ty = autoderef.unambiguous_final_ty(); + autoderef.finalize(LvaluePreference::NoPreference, Some(callee_expr)); match result { None => { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 4861ab15e2c01..9dd737f3a6168 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -60,7 +60,7 @@ //! sort of a minor point so I've opted to leave it for later---after all //! we may want to adjust precisely when coercions occur. -use check::{FnCtxt, UnresolvedTypeAction}; +use check::{FnCtxt}; use rustc::hir; use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace}; @@ -220,7 +220,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { -> CoerceResult<'tcx> // FIXME(eddyb) use copyable iterators when that becomes ergonomic. where E: Fn() -> I, - I: IntoIterator { + I: IntoIterator + { debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b); @@ -240,18 +241,16 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let span = self.origin.span(); - let lvalue_pref = LvaluePreference::from_mutbl(mt_b.mutbl); let mut first_error = None; let mut r_borrow_var = None; - let (_, autoderefs, success) = self.autoderef(span, a, exprs, - UnresolvedTypeAction::Ignore, - lvalue_pref, - |referent_ty, autoderef| - { - if autoderef == 0 { + let mut autoderef = self.autoderef(span, a); + let mut success = None; + + for (referent_ty, autoderefs) in autoderef.by_ref() { + if autoderefs == 0 { // Don't let this pass, otherwise it would cause // &T to autoref to &&T. - return None; + continue } // At this point, we have deref'd `a` to `referent_ty`. So @@ -326,7 +325,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // and let regionck figure it out. let r = if !self.use_lub { r_b // [2] above - } else if autoderef == 1 { + } else if autoderefs == 1 { r_a // [3] above } else { if r_borrow_var.is_none() { // create var lazilly, at most once @@ -341,23 +340,22 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { mutbl: mt_b.mutbl // [1] above }); match self.unify(derefd_ty_a, b) { - Ok(ty) => Some(ty), + Ok(ty) => { success = Some((ty, autoderefs)); break }, Err(err) => { if first_error.is_none() { first_error = Some(err); } - None } } - }); + } // Extract type or return an error. We return the first error // we got, which should be from relating the "base" type // (e.g., in example above, the failure from relating `Vec` // to the target type), since that should be the least // confusing. - let ty = match success { - Some(ty) => ty, + let (ty, autoderefs) = match success { + Some(d) => d, None => { let err = first_error.expect("coerce_borrowed_pointer had no error"); debug!("coerce_borrowed_pointer: failed with err = {:?}", err); @@ -365,6 +363,10 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } }; + // This commits the obligations to the fulfillcx. After this succeeds, + // this snapshot can't be rolled back. + autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs()); + // Now apply the autoref. We have to extract the region out of // the final ref type we got. if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index a1a6a83d34ff2..20f82271b9cd6 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -279,78 +279,63 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // type. // Compute skolemized form of impl and trait method tys. - let impl_fty = tcx.mk_fn_ptr(impl_m.fty); - let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs); - let trait_fty = tcx.mk_fn_ptr(trait_m.fty); - let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); - - let err = infcx.commit_if_ok(|snapshot| { - let tcx = infcx.tcx; - let origin = TypeOrigin::MethodCompatCheck(impl_m_span); - - let (impl_sig, _) = - infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, - infer::HigherRankedType, - &impl_m.fty.sig); - let impl_sig = - impl_sig.subst(tcx, impl_to_skol_substs); - let impl_sig = - assoc::normalize_associated_types_in(&infcx, - &mut fulfillment_cx, - impl_m_span, - impl_m_body_id, - &impl_sig); - let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: impl_m.fty.unsafety, - abi: impl_m.fty.abi, - sig: ty::Binder(impl_sig) - })); - debug!("compare_impl_method: impl_fty={:?}", - impl_fty); - - let (trait_sig, skol_map) = - infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot); - let trait_sig = - trait_sig.subst(tcx, &trait_to_skol_substs); - let trait_sig = - assoc::normalize_associated_types_in(&infcx, - &mut fulfillment_cx, - impl_m_span, - impl_m_body_id, - &trait_sig); - let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: trait_m.fty.unsafety, - abi: trait_m.fty.abi, - sig: ty::Binder(trait_sig) - })); - - debug!("compare_impl_method: trait_fty={:?}", + let tcx = infcx.tcx; + let origin = TypeOrigin::MethodCompatCheck(impl_m_span); + + let (impl_sig, _) = + infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, + infer::HigherRankedType, + &impl_m.fty.sig); + let impl_sig = + impl_sig.subst(tcx, impl_to_skol_substs); + let impl_sig = + assoc::normalize_associated_types_in(&infcx, + &mut fulfillment_cx, + impl_m_span, + impl_m_body_id, + &impl_sig); + let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { + unsafety: impl_m.fty.unsafety, + abi: impl_m.fty.abi, + sig: ty::Binder(impl_sig) + })); + debug!("compare_impl_method: impl_fty={:?}", impl_fty); + + let trait_sig = tcx.liberate_late_bound_regions( + infcx.parameter_environment.free_id_outlive, + &trait_m.fty.sig); + let trait_sig = + trait_sig.subst(tcx, &trait_to_skol_substs); + let trait_sig = + assoc::normalize_associated_types_in(&infcx, + &mut fulfillment_cx, + impl_m_span, + impl_m_body_id, + &trait_sig); + let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { + unsafety: trait_m.fty.unsafety, + abi: trait_m.fty.abi, + sig: ty::Binder(trait_sig) + })); + + debug!("compare_impl_method: trait_fty={:?}", trait_fty); + + if let Err(terr) = infcx.sub_types(false, origin, impl_fty, trait_fty) { + debug!("sub_types failed: impl ty {:?}, trait ty {:?}", + impl_fty, trait_fty); - - infcx.sub_types(false, origin, impl_fty, trait_fty)?; - - infcx.leak_check(false, &skol_map, snapshot) - }); - - match err { - Ok(()) => { } - Err(terr) => { - debug!("checking trait method for compatibility: impl ty {:?}, trait ty {:?}", - impl_fty, - trait_fty); - span_err!(tcx.sess, impl_m_span, E0053, - "method `{}` has an incompatible type for trait: {}", - trait_m.name, - terr); - return; - } + span_err!(tcx.sess, impl_m_span, E0053, + "method `{}` has an incompatible type for trait: {}", + trait_m.name, + terr); + return } // Check that all obligations are satisfied by the implementation's // version. - match fulfillment_cx.select_all_or_error(&infcx) { - Err(ref errors) => { infcx.report_fulfillment_errors(errors) } - Ok(_) => {} + if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(errors); + return } // Finally, resolve all regions. This catches wily misuses of diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index c02139140aed5..f120e38630b8a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -117,6 +117,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { param(ccx, 0)) ], ccx.tcx.types.usize) } + "rustc_peek" => (1, vec![param(ccx, 0)], param(ccx, 0)), "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)), "uninit" => (1, Vec::new(), param(ccx, 0)), "forget" => (1, vec!( param(ccx, 0) ), tcx.mk_nil()), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 6faf6f415c266..683a67ff07cf9 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,11 +11,10 @@ use super::probe; use check::{FnCtxt, callee}; -use check::UnresolvedTypeAction; use hir::def_id::DefId; use rustc::ty::subst::{self}; use rustc::traits; -use rustc::ty::{self, NoPreference, PreferMutLvalue, Ty}; +use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk, TypeOrigin}; @@ -133,10 +132,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { ty: fty, substs: all_substs }; - // If this is an `&mut self` method, bias the receiver - // expression towards mutability (this will switch - // e.g. `Deref` to `DerefMut` in overloaded derefs and so on). - self.fixup_derefs_on_method_receiver_if_necessary(&callee); + + if let Some(hir::MutMutable) = pick.autoref { + self.convert_lvalue_derefs_to_mutable(); + } callee } @@ -164,22 +163,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { (None, None) }; - // Commit the autoderefs by calling `autoderef again, but this + // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. - let (autoderefd_ty, n, result) = self.autoderef(self.span, - unadjusted_self_ty, - || Some(self.self_expr), - UnresolvedTypeAction::Error, - NoPreference, - |_, n| { - if n == pick.autoderefs { - Some(()) - } else { - None - } - }); + let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); + let (autoderefd_ty, n) = autoderef.nth(pick.autoderefs).unwrap(); assert_eq!(n, pick.autoderefs); - assert_eq!(result, Some(())); + + autoderef.unambiguous_final_ty(); + autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr)); // Write out the final adjustment. self.write_adjustment(self.self_expr.id, AdjustDerefRef(AutoDerefRef { @@ -293,27 +284,21 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // yield an object-type (e.g., `&Object` or `Box` // etc). - let (_, _, result) = self.fcx.autoderef(self.span, - self_ty, - || None, - UnresolvedTypeAction::Error, - NoPreference, - |ty, _| { - match ty.sty { - ty::TyTrait(ref data) => Some(closure(self, ty, &data)), - _ => None, - } - }); - - match result { - Some(r) => r, - None => { + // FIXME: this feels, like, super dubious + self.fcx.autoderef(self.span, self_ty) + .filter_map(|(ty, _)| { + match ty.sty { + ty::TyTrait(ref data) => Some(closure(self, ty, &data)), + _ => None, + } + }) + .next() + .unwrap_or_else(|| { span_bug!( self.span, "self-type `{}` for ObjectPick never dereferenced to an object", self_ty) - } - } + }) } fn instantiate_method_substs(&mut self, @@ -463,24 +448,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { /////////////////////////////////////////////////////////////////////////// // RECONCILIATION - /// When we select a method with an `&mut self` receiver, we have to go convert any + /// When we select a method with a mutable autoref, we have to go convert any /// auto-derefs, indices, etc from `Deref` and `Index` into `DerefMut` and `IndexMut` /// respectively. - fn fixup_derefs_on_method_receiver_if_necessary(&self, - method_callee: &ty::MethodCallee) { - let sig = match method_callee.ty.sty { - ty::TyFnDef(_, _, ref f) => f.sig.clone(), - _ => return, - }; - - match sig.0.inputs[0].sty { - ty::TyRef(_, ty::TypeAndMut { - ty: _, - mutbl: hir::MutMutable, - }) => {} - _ => return, - } - + fn convert_lvalue_derefs_to_mutable(&self) { // Gather up expressions we want to munge. let mut exprs = Vec::new(); exprs.push(self.self_expr); @@ -495,8 +466,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } } - debug!("fixup_derefs_on_method_receiver_if_necessary: exprs={:?}", - exprs); + debug!("convert_lvalue_derefs_to_mutable: exprs={:?}", exprs); // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { @@ -509,23 +479,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { Some(_) | None => 0, }; - debug!("fixup_derefs_on_method_receiver_if_necessary: i={} expr={:?} \ - autoderef_count={}", + debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \ + autoderef_count={}", i, expr, autoderef_count); if autoderef_count > 0 { - self.autoderef(expr.span, - self.expr_ty(expr), - || Some(expr), - UnresolvedTypeAction::Error, - PreferMutLvalue, - |_, autoderefs| { - if autoderefs == autoderef_count + 1 { - Some(()) - } else { - None - } + let mut autoderef = self.autoderef(expr.span, self.expr_ty(expr)); + autoderef.nth(autoderef_count).unwrap_or_else(|| { + span_bug!(expr.span, "expr was deref-able {} times but now isn't?", + autoderef_count); }); + autoderef.finalize(PreferMutLvalue, Some(expr)); } // Don't retry the first one or we might infinite loop! diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 08c041225171a..0bb078dfbcba2 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -13,13 +13,13 @@ use super::NoMatchData; use super::{CandidateSource, ImplSource, TraitSource}; use super::suggest; -use check::{FnCtxt, UnresolvedTypeAction}; +use check::{FnCtxt}; use hir::def_id::DefId; use hir::def::Def; use rustc::ty::subst; use rustc::ty::subst::Subst; use rustc::traits; -use rustc::ty::{self, NoPreference, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; +use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::infer::{InferOk, TypeOrigin}; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; @@ -208,25 +208,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn create_steps(&self, span: Span, self_ty: Ty<'tcx>) - -> Option>> { - let mut steps = Vec::new(); - - let (final_ty, dereferences, _) = self.autoderef(span, - self_ty, - || None, - UnresolvedTypeAction::Error, - NoPreference, - |t, d| { - steps.push(CandidateStep { - self_ty: t, - autoderefs: d, - unsize: false - }); - None::<()> // keep iterating until we can't anymore - }); + -> Option>> + { + // FIXME: we don't need to create the entire steps in one pass + let mut autoderef = self.autoderef(span, self_ty); + let mut steps: Vec<_> = autoderef.by_ref().map(|(ty, d)| CandidateStep { + self_ty: ty, + autoderefs: d, + unsize: false + }).collect(); + + let final_ty = autoderef.unambiguous_final_ty(); match final_ty.sty { ty::TyArray(elem_ty, _) => { + let dereferences = steps.len() - 1; + steps.push(CandidateStep { self_ty: self.tcx.mk_slice(elem_ty), autoderefs: dereferences, @@ -237,6 +234,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => (), } + debug!("create_steps: steps={:?}", steps); + Some(steps) } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2cd60d20251f3..6f0d2bc0ca5e6 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -13,7 +13,7 @@ use CrateCtxt; -use check::{self, FnCtxt, UnresolvedTypeAction}; +use check::{FnCtxt}; use rustc::hir::map as hir_map; use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable}; use middle::cstore; @@ -21,7 +21,6 @@ use hir::def::Def; use hir::def_id::DefId; use middle::lang_items::FnOnceTraitLangItem; use rustc::ty::subst::Substs; -use rustc::ty::LvaluePreference; use rustc::traits::{Obligation, SelectionContext}; use util::nodemap::{FnvHashSet}; @@ -48,42 +47,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyClosure(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) => true, // If it's not a simple function, look for things which implement FnOnce _ => { - if let Ok(fn_once_trait_did) = - tcx.lang_items.require(FnOnceTraitLangItem) { - let (_, _, opt_is_fn) = self.autoderef(span, - ty, - || None, - UnresolvedTypeAction::Ignore, - LvaluePreference::NoPreference, - |ty, _| { - self.probe(|_| { - let fn_once_substs = - Substs::new_trait(vec![self.next_ty_var()], vec![], ty); - let trait_ref = - ty::TraitRef::new(fn_once_trait_did, - tcx.mk_substs(fn_once_substs)); - let poly_trait_ref = trait_ref.to_poly_trait_ref(); - let obligation = Obligation::misc(span, - self.body_id, - poly_trait_ref - .to_predicate()); - let mut selcx = SelectionContext::new(self); - - if selcx.evaluate_obligation(&obligation) { - Some(()) - } else { - None - } - }) - }); + let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) { + Ok(fn_once) => fn_once, + Err(..) => return false + }; - opt_is_fn.is_some() - } else { - false - } + self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| { + let fn_once_substs = + Substs::new_trait(vec![self.next_ty_var()], vec![], ty); + let trait_ref = + ty::TraitRef::new(fn_once, + tcx.mk_substs(fn_once_substs)); + let poly_trait_ref = trait_ref.to_poly_trait_ref(); + let obligation = Obligation::misc(span, + self.body_id, + poly_trait_ref + .to_predicate()); + SelectionContext::new(self).evaluate_obligation(&obligation) + })) } } } + pub fn report_method_error(&self, span: Span, rcvr_ty: Ty<'tcx>, @@ -384,15 +369,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return is_local(self.resolve_type_vars_with_obligations(rcvr_ty)); } - self.autoderef(span, rcvr_ty, || None, - check::UnresolvedTypeAction::Ignore, ty::NoPreference, - |ty, _| { - if is_local(ty) { - Some(()) - } else { - None - } - }).2.is_some() + self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty)) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 264003bb62b81..5dd00cf3666ad 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -129,6 +129,7 @@ use rustc_back::slice; use rustc_const_eval::eval_repeat_count; mod assoc; +mod autoderef; pub mod dropck; pub mod _match; pub mod writeback; @@ -1412,17 +1413,6 @@ impl<'a, 'gcx, 'tcx> RegionScope for FnCtxt<'a, 'gcx, 'tcx> { } } -/// Whether `autoderef` requires types to resolve. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum UnresolvedTypeAction { - /// Produce an error and return `TyError` whenever a type cannot - /// be resolved (i.e. it is `TyInfer`). - Error, - /// Go on without emitting any errors, and return the unresolved - /// type. Useful for probing, e.g. in coercions. - Ignore -} - /// Controls whether the arguments are tupled. This is used for the call /// operator. /// @@ -2228,120 +2218,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` - /// to decide whether to terminate the loop. Returns the final type and number of - /// derefs that it performed. - /// - /// Note: this method does not modify the adjustments table. The caller is responsible for - /// inserting an AutoAdjustment record into the `self` using one of the suitable methods. - pub fn autoderef<'b, E, I, T, F>(&self, - sp: Span, - base_ty: Ty<'tcx>, - maybe_exprs: E, - unresolved_type_action: UnresolvedTypeAction, - mut lvalue_pref: LvaluePreference, - mut should_stop: F) - -> (Ty<'tcx>, usize, Option) - // FIXME(eddyb) use copyable iterators when that becomes ergonomic. - where E: Fn() -> I, - I: IntoIterator, - F: FnMut(Ty<'tcx>, usize) -> Option, - { - debug!("autoderef(base_ty={:?}, lvalue_pref={:?})", - base_ty, lvalue_pref); - - let mut t = base_ty; - for autoderefs in 0..self.tcx.sess.recursion_limit.get() { - let resolved_t = match unresolved_type_action { - UnresolvedTypeAction::Error => { - self.structurally_resolved_type(sp, t) - } - UnresolvedTypeAction::Ignore => { - // We can continue even when the type cannot be resolved - // (i.e. it is an inference variable) because `Ty::builtin_deref` - // and `try_overloaded_deref` both simply return `None` - // in such a case without producing spurious errors. - self.resolve_type_vars_if_possible(&t) - } - }; - if resolved_t.references_error() { - return (resolved_t, autoderefs, None); - } - - match should_stop(resolved_t, autoderefs) { - Some(x) => return (resolved_t, autoderefs, Some(x)), - None => {} - } - - // Otherwise, deref if type is derefable: - - // Super subtle: it might seem as though we should - // pass `opt_expr` to `try_overloaded_deref`, so that - // the (implicit) autoref of using an overloaded deref - // would get added to the adjustment table. However we - // do not do that, because it's kind of a - // "meta-adjustment" -- instead, we just leave it - // unrecorded and know that there "will be" an - // autoref. regionck and other bits of the code base, - // when they encounter an overloaded autoderef, have - // to do some reconstructive surgery. This is a pretty - // complex mess that is begging for a proper MIR. - let mt = if let Some(mt) = resolved_t.builtin_deref(false, lvalue_pref) { - mt - } else if let Some(method) = self.try_overloaded_deref(sp, None, - resolved_t, lvalue_pref) { - for expr in maybe_exprs() { - let method_call = MethodCall::autoderef(expr.id, autoderefs as u32); - self.tables.borrow_mut().method_map.insert(method_call, method); - } - self.make_overloaded_lvalue_return_type(method) - } else { - return (resolved_t, autoderefs, None); - }; - - t = mt.ty; - if mt.mutbl == hir::MutImmutable { - lvalue_pref = NoPreference; - } - } - - // We've reached the recursion limit, error gracefully. - span_err!(self.tcx.sess, sp, E0055, - "reached the recursion limit while auto-dereferencing {:?}", - base_ty); - (self.tcx.types.err, 0, None) - } - - fn try_overloaded_deref(&self, - span: Span, - base_expr: Option<&hir::Expr>, - base_ty: Ty<'tcx>, - lvalue_pref: LvaluePreference) - -> Option> - { - // Try DerefMut first, if preferred. - let method = match (lvalue_pref, self.tcx.lang_items.deref_mut_trait()) { - (PreferMutLvalue, Some(trait_did)) => { - self.lookup_method_in_trait(span, base_expr, - token::intern("deref_mut"), trait_did, - base_ty, None) - } - _ => None - }; - - // Otherwise, fall back to Deref. - let method = match (method, self.tcx.lang_items.deref_trait()) { - (None, Some(trait_did)) => { - self.lookup_method_in_trait(span, base_expr, - token::intern("deref"), trait_did, - base_ty, None) - } - (method, _) => method - }; - - method - } - /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait /// returns a type of `&T`, but the actual type we assign to the /// *expression* is `T`. So this function just peels off the return @@ -2371,29 +2247,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // autoderef that normal method probing does. They could likely be // consolidated. - let (ty, autoderefs, final_mt) = self.autoderef(base_expr.span, - base_ty, - || Some(base_expr), - UnresolvedTypeAction::Error, - lvalue_pref, - |adj_ty, idx| { - self.try_index_step(MethodCall::expr(expr.id), expr, base_expr, - adj_ty, idx, false, lvalue_pref, idx_ty) - }); + let mut autoderef = self.autoderef(base_expr.span, base_ty); - if final_mt.is_some() { - return final_mt; - } + while let Some((adj_ty, autoderefs)) = autoderef.next() { + if let Some(final_mt) = self.try_index_step( + MethodCall::expr(expr.id), + expr, base_expr, adj_ty, autoderefs, + false, lvalue_pref, idx_ty) + { + autoderef.finalize(lvalue_pref, Some(base_expr)); + return Some(final_mt); + } - // After we have fully autoderef'd, if the resulting type is [T; n], then - // do a final unsized coercion to yield [T]. - if let ty::TyArray(element_ty, _) = ty.sty { - let adjusted_ty = self.tcx.mk_slice(element_ty); - self.try_index_step(MethodCall::expr(expr.id), expr, base_expr, - adjusted_ty, autoderefs, true, lvalue_pref, idx_ty) - } else { - None + if let ty::TyArray(element_ty, _) = adj_ty.sty { + autoderef.finalize(lvalue_pref, Some(base_expr)); + let adjusted_ty = self.tcx.mk_slice(element_ty); + return self.try_index_step( + MethodCall::expr(expr.id), expr, base_expr, + adjusted_ty, autoderefs, true, lvalue_pref, idx_ty); + } } + autoderef.unambiguous_final_ty(); + None } /// To type-check `base_expr[index_expr]`, we progressively autoderef @@ -3034,32 +2909,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_t = self.structurally_resolved_type(expr.span, self.expr_ty(base)); let mut private_candidate = None; - let (_, autoderefs, field_ty) = self.autoderef(expr.span, - expr_t, - || Some(base), - UnresolvedTypeAction::Error, - lvalue_pref, - |base_t, _| { - if let ty::TyStruct(base_def, substs) = base_t.sty { - debug!("struct named {:?}", base_t); - if let Some(field) = base_def.struct_variant().find_field_named(field.node) { - let field_ty = self.field_ty(expr.span, field, substs); - if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { - return Some(field_ty); - } - private_candidate = Some((base_def.did, field_ty)); + let mut autoderef = self.autoderef(expr.span, expr_t); + while let Some((base_t, autoderefs)) = autoderef.next() { + if let ty::TyStruct(base_def, substs) = base_t.sty { + debug!("struct named {:?}", base_t); + if let Some(field) = base_def.struct_variant().find_field_named(field.node) { + let field_ty = self.field_ty(expr.span, field, substs); + if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { + autoderef.finalize(lvalue_pref, Some(base)); + self.write_ty(expr.id, field_ty); + self.write_autoderef_adjustment(base.id, autoderefs); + return; } + private_candidate = Some((base_def.did, field_ty)); } - None - }); - match field_ty { - Some(field_ty) => { - self.write_ty(expr.id, field_ty); - self.write_autoderef_adjustment(base.id, autoderefs); - return; } - None => {} } + autoderef.unambiguous_final_ty(); if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); @@ -3132,42 +2998,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.expr_ty(base)); let mut private_candidate = None; let mut tuple_like = false; - let (_, autoderefs, field_ty) = self.autoderef(expr.span, - expr_t, - || Some(base), - UnresolvedTypeAction::Error, - lvalue_pref, - |base_t, _| { - let (base_def, substs) = match base_t.sty { - ty::TyStruct(base_def, substs) => (base_def, substs), - ty::TyTuple(ref v) => { - tuple_like = true; - return if idx.node < v.len() { Some(v[idx.node]) } else { None } - } - _ => return None, - }; - - tuple_like = base_def.struct_variant().is_tuple_struct(); - if !tuple_like { return None } - - debug!("tuple struct named {:?}", base_t); - if let Some(field) = base_def.struct_variant().fields.get(idx.node) { - let field_ty = self.field_ty(expr.span, field, substs); - if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { - return Some(field_ty); - } - private_candidate = Some((base_def.did, field_ty)); + let mut autoderef = self.autoderef(expr.span, expr_t); + while let Some((base_t, autoderefs)) = autoderef.next() { + let field = match base_t.sty { + ty::TyStruct(base_def, substs) => { + tuple_like = base_def.struct_variant().is_tuple_struct(); + if !tuple_like { continue } + + debug!("tuple struct named {:?}", base_t); + base_def.struct_variant().fields.get(idx.node).and_then(|field| { + let field_ty = self.field_ty(expr.span, field, substs); + private_candidate = Some((base_def.did, field_ty)); + if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { + Some(field_ty) + } else { + None + } + }) } - None - }); - match field_ty { - Some(field_ty) => { + ty::TyTuple(ref v) => { + tuple_like = true; + v.get(idx.node).cloned() + } + _ => continue + }; + + if let Some(field_ty) = field { + autoderef.finalize(lvalue_pref, Some(base)); self.write_ty(expr.id, field_ty); self.write_autoderef_adjustment(base.id, autoderefs); return; } - None => {} } + autoderef.unambiguous_final_ty(); if let Some((did, field_ty)) = private_candidate { let struct_path = self.tcx().item_path_str(did); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 45aec9558feaf..7598751c8fe18 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -62,31 +62,6 @@ Check how many fields the enum was declared with and ensure that your pattern uses the same number. "##, -E0024: r##" -This error indicates that a pattern attempted to extract the fields of an enum -variant with no fields. Here's a tiny example of this error: - -```compile_fail -// This enum has two variants. -enum Number { - // This variant has no fields. - Zero, - // This variant has one field. - One(u32) -} - -// Assuming x is a Number we can pattern match on its contents. -match x { - Number::Zero(inside) => {}, - Number::One(inside) => {}, -} -``` - -The pattern match `Zero(inside)` is incorrect because the `Zero` variant -contains no fields, yet the `inside` name attempts to bind the first field of -the enum. -"##, - E0025: r##" Each field of a struct can only be bound once in a pattern. Erroneous code example: @@ -978,18 +953,18 @@ are generic. This will cause an error: ```compile_fail -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Bad(T, T, T); ``` This will not: ``` -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Good(u32, u32, u32); ``` "##, @@ -1026,18 +1001,18 @@ will trigger this error. This will cause an error: ```compile_fail -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Bad(u16, u32, u32); ``` This will not: ``` -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Good(u32, u32, u32); ``` "##, @@ -1049,18 +1024,18 @@ must be machine types so SIMD operations can be applied to them. This will cause an error: ```compile_fail -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Bad(String); ``` This will not: ``` -#![feature(simd)] +#![feature(repr_simd)] -#[simd] +#[repr(simd)] struct Good(u32, u32, u32); ``` "##, @@ -1193,12 +1168,32 @@ discriminant values so that they fit within the existing type. "##, E0084: r##" +An unsupported representation was attempted on a zero-variant enum. + +Erroneous code example: + +```compile_fail +#[repr(i32)] +enum NightWatch {} // error: unsupported representation for zero-variant enum +``` + It is impossible to define an integer type to be used to represent zero-variant enum values because there are no zero-variant enum values. There is no way to -construct an instance of the following type using only safe code: +construct an instance of the following type using only safe code. So you have +two solutions. Either you add variants in your enum: ``` -enum Empty {} +#[repr(i32)] +enum NightWatch { + JohnSnow, + Commander, +} +``` + +or you remove the integer represention of your enum: + +``` +enum NightWatch {} ``` "##, @@ -2387,39 +2382,135 @@ impl Copy for &'static Bar { } // error "##, E0207: r##" -You declared an unused type parameter when implementing a trait on an object. -Erroneous code example: +Any type parameter or lifetime parameter of an `impl` must meet at least one of +the following criteria: + + - it appears in the self type of the impl + - for a trait impl, it appears in the trait reference + - it is bound as an associated type + +### Error example 1 + +Suppose we have a struct `Foo` and we would like to define some methods for it. +The following definition leads to a compiler error: ```compile_fail -trait MyTrait { - fn get(&self) -> usize; +struct Foo; + +impl Foo { +// error: the type parameter `T` is not constrained by the impl trait, self +// type, or predicates [E0207] + fn get(&self) -> T { + ::default() + } } +``` + +The problem is that the parameter `T` does not appear in the self type (`Foo`) +of the impl. In this case, we can fix the error by moving the type parameter +from the `impl` to the method `get`: + +``` struct Foo; -impl MyTrait for Foo { - fn get(&self) -> usize { - 0 +// Move the type parameter from the impl to the method +impl Foo { + fn get(&self) -> T { + ::default() } } ``` -Please check your object definition and remove unused type -parameter(s). Example: +### Error example 2 + +As another example, suppose we have a `Maker` trait and want to establish a +type `FooMaker` that makes `Foo`s: + +```compile_fail +trait Maker { + type Item; + fn make(&mut self) -> Self::Item; +} + +struct Foo { + foo: T +} + +struct FooMaker; + +impl Maker for FooMaker { +// error: the type parameter `T` is not constrained by the impl trait, self +// type, or predicates [E0207] + type Item = Foo; + fn make(&mut self) -> Foo { + Foo { foo: ::default() } + } +} ``` -trait MyTrait { - fn get(&self) -> usize; + +This fails to compile because `T` does not appear in the trait or in the +implementing type. + +One way to work around this is to introduce a phantom type parameter into +`FooMaker`, like so: + +``` +use std::marker::PhantomData; + +trait Maker { + type Item; + fn make(&mut self) -> Self::Item; } -struct Foo; +struct Foo { + foo: T +} -impl MyTrait for Foo { - fn get(&self) -> usize { - 0 +// Add a type parameter to `FooMaker` +struct FooMaker { + phantom: PhantomData, +} + +impl Maker for FooMaker { + type Item = Foo; + + fn make(&mut self) -> Foo { + Foo { + foo: ::default(), + } + } +} +``` + +Another way is to do away with the associated type in `Maker` and use an input +type parameter instead: + +``` +// Use a type parameter instead of an associated type here +trait Maker { + fn make(&mut self) -> Item; +} + +struct Foo { + foo: T +} + +struct FooMaker; + +impl Maker> for FooMaker { + fn make(&mut self) -> Foo { + Foo { foo: ::default() } } } ``` + +### Additional information + +For more information, please see [RFC 447]. + +[RFC 447]: https://github.com/rust-lang/rfcs/blob/master/text/0447-no-unused-impl-parameters.md "##, E0210: r##" diff --git a/src/librustc_unicode/tables.rs b/src/librustc_unicode/tables.rs index ad17016eae8cb..43e7c26fd7215 100644 --- a/src/librustc_unicode/tables.rs +++ b/src/librustc_unicode/tables.rs @@ -16,1187 +16,1306 @@ /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on. pub const UNICODE_VERSION: (u64, u64, u64) = (8, 0, 0); -fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool { - use core::cmp::Ordering::{Equal, Less, Greater}; - r.binary_search_by(|&(lo, hi)| { - if c < lo { - Greater - } else if hi < c { - Less - } else { - Equal - } - }) - .is_ok() + +// BoolTrie is a trie for representing a set of Unicode codepoints. It is +// implemented with postfix compression (sharing of identical child nodes), +// which gives both compact size and fast lookup. +// +// The space of Unicode codepoints is divided into 3 subareas, each +// represented by a trie with different depth. In the first (0..0x800), there +// is no trie structure at all; each u64 entry corresponds to a bitvector +// effectively holding 64 bool values. +// +// In the second (0x800..0x10000), each child of the root node represents a +// 64-wide subrange, but instead of storing the full 64-bit value of the leaf, +// the trie stores an 8-bit index into a shared table of leaf values. This +// exploits the fact that in reasonable sets, many such leaves can be shared. +// +// In the third (0x10000..0x110000), each child of the root node represents a +// 4096-wide subrange, and the trie stores an 8-bit index into a 64-byte slice +// of a child tree. Each of these 64 bytes represents an index into the table +// of shared 64-bit leaf values. This exploits the sparse structure in the +// non-BMP range of most Unicode sets. +pub struct BoolTrie { + // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences) + r1: [u64; 32], // leaves + + // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences) + r2: [u8; 992], // first level + r3: &'static [u64], // leaves + + // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences) + r4: [u8; 256], // first level + r5: &'static [u8], // second level + r6: &'static [u64], // leaves +} + +fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool { + ((bitmap_chunk >> (c & 63)) & 1) != 0 +} + +fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool { + let c = c as usize; + if c < 0x800 { + trie_range_leaf(c, r.r1[c >> 6]) + } else if c < 0x10000 { + let child = r.r2[(c >> 6) - 0x20]; + trie_range_leaf(c, r.r3[child as usize]) + } else { + let child = r.r4[(c >> 12) - 0x10]; + let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)]; + trie_range_leaf(c, r.r6[leaf as usize]) + } } pub mod general_category { - pub const Cc_table: &'static [(char, char)] = &[ - ('\0', '\u{1f}'), ('\u{7f}', '\u{9f}') - ]; + pub const Cc_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x00000000ffffffff, 0x8000000000000000, 0x00000000ffffffff, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r3: &[ + 0x0000000000000000 + ], + r4: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000 + ], + }; pub fn Cc(c: char) -> bool { - super::bsearch_range_table(c, Cc_table) + super::trie_lookup_range_table(c, Cc_table) } - pub const N_table: &'static [(char, char)] = &[ - ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'), ('\u{7c0}', - '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'), ('\u{a66}', '\u{a6f}'), - ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'), ('\u{be6}', '\u{bef}'), ('\u{c66}', - '\u{c6f}'), ('\u{ce6}', '\u{cef}'), ('\u{d66}', '\u{d6f}'), ('\u{de6}', '\u{def}'), - ('\u{e50}', '\u{e59}'), ('\u{ed0}', '\u{ed9}'), ('\u{f20}', '\u{f29}'), ('\u{1040}', - '\u{1049}'), ('\u{1090}', '\u{1099}'), ('\u{16ee}', '\u{16f0}'), ('\u{17e0}', '\u{17e9}'), - ('\u{1810}', '\u{1819}'), ('\u{1946}', '\u{194f}'), ('\u{19d0}', '\u{19d9}'), ('\u{1a80}', - '\u{1a89}'), ('\u{1a90}', '\u{1a99}'), ('\u{1b50}', '\u{1b59}'), ('\u{1bb0}', '\u{1bb9}'), - ('\u{1c40}', '\u{1c49}'), ('\u{1c50}', '\u{1c59}'), ('\u{2160}', '\u{2182}'), ('\u{2185}', - '\u{2188}'), ('\u{3007}', '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303a}'), - ('\u{a620}', '\u{a629}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{a8d0}', '\u{a8d9}'), ('\u{a900}', - '\u{a909}'), ('\u{a9d0}', '\u{a9d9}'), ('\u{a9f0}', '\u{a9f9}'), ('\u{aa50}', '\u{aa59}'), - ('\u{abf0}', '\u{abf9}'), ('\u{ff10}', '\u{ff19}'), ('\u{10140}', '\u{10174}'), - ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'), ('\u{103d1}', '\u{103d5}'), - ('\u{104a0}', '\u{104a9}'), ('\u{11066}', '\u{1106f}'), ('\u{110f0}', '\u{110f9}'), - ('\u{11136}', '\u{1113f}'), ('\u{111d0}', '\u{111d9}'), ('\u{112f0}', '\u{112f9}'), - ('\u{114d0}', '\u{114d9}'), ('\u{11650}', '\u{11659}'), ('\u{116c0}', '\u{116c9}'), - ('\u{11730}', '\u{11739}'), ('\u{118e0}', '\u{118e9}'), ('\u{12400}', '\u{1246e}'), - ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'), ('\u{1d7ce}', '\u{1d7ff}') - ]; + pub const N_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x03ff000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x000003ff00000000, 0x0000000000000000, 0x03ff000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000000003ff + ], + r2: [ + 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 3, + 0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 2, 0, 0, 7, 0, 0, 2, 8, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 2, 4, 0, 0, 12, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0x0000ffc000000000, 0x0000000003ff0000, 0x000003ff00000000, + 0x00000000000003ff, 0x0001c00000000000, 0x000000000000ffc0, 0x0000000003ff03ff, + 0x03ff000000000000, 0xffffffff00000000, 0x00000000000001e7, 0x070003fe00000080, + 0x03ff000003ff0000 + ], + r4: [ + 0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + ], + r5: &[ + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 7, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 8, 0, 9, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000, 0x001fffffffffffff, 0x0000000000000402, 0x00000000003e0000, + 0x000003ff00000000, 0x0000ffc000000000, 0x03ff000000000000, 0xffc0000000000000, + 0x0000000003ff0000, 0x00000000000003ff, 0xffffffffffffffff, 0x00007fffffffffff, + 0xffffffffffffc000 + ], + }; pub fn N(c: char) -> bool { - super::bsearch_range_table(c, N_table) + super::trie_lookup_range_table(c, N_table) } } pub mod derived_property { - pub const Alphabetic_table: &'static [(char, char)] = &[ - ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), - ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), - ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', - '\u{2ee}'), ('\u{345}', '\u{345}'), ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), - ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', - '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), - ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'), ('\u{559}', - '\u{559}'), ('\u{561}', '\u{587}'), ('\u{5b0}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), - ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', - '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{610}', '\u{61a}'), ('\u{620}', '\u{657}'), - ('\u{659}', '\u{65f}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'), ('\u{6e1}', - '\u{6e8}'), ('\u{6ed}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'), - ('\u{710}', '\u{73f}'), ('\u{74d}', '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', - '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), ('\u{800}', '\u{817}'), ('\u{81a}', '\u{82c}'), - ('\u{840}', '\u{858}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', '\u{8e9}'), ('\u{8f0}', - '\u{93b}'), ('\u{93d}', '\u{94c}'), ('\u{94e}', '\u{950}'), ('\u{955}', '\u{963}'), - ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', - '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), - ('\u{9bd}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cc}'), ('\u{9ce}', - '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e3}'), - ('\u{9f0}', '\u{9f1}'), ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', - '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), - ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3e}', '\u{a42}'), ('\u{a47}', - '\u{a48}'), ('\u{a4b}', '\u{a4c}'), ('\u{a51}', '\u{a51}'), ('\u{a59}', '\u{a5c}'), - ('\u{a5e}', '\u{a5e}'), ('\u{a70}', '\u{a75}'), ('\u{a81}', '\u{a83}'), ('\u{a85}', - '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), - ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abd}', '\u{ac5}'), ('\u{ac7}', - '\u{ac9}'), ('\u{acb}', '\u{acc}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae3}'), - ('\u{af9}', '\u{af9}'), ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', - '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), - ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', - '\u{b4c}'), ('\u{b56}', '\u{b57}'), ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'), - ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', - '\u{b90}'), ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), - ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', - '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcc}'), - ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{c00}', '\u{c03}'), ('\u{c05}', - '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), - ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4c}'), ('\u{c55}', - '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), ('\u{c81}', '\u{c83}'), - ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', - '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), - ('\u{cca}', '\u{ccc}'), ('\u{cd5}', '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', - '\u{ce3}'), ('\u{cf1}', '\u{cf2}'), ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), - ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', - '\u{d48}'), ('\u{d4a}', '\u{d4c}'), ('\u{d4e}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), - ('\u{d5f}', '\u{d63}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', - '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), - ('\u{dc0}', '\u{dc6}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', - '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'), ('\u{e40}', '\u{e46}'), - ('\u{e4d}', '\u{e4d}'), ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', - '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), - ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', - '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), - ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{ecd}', '\u{ecd}'), ('\u{edc}', - '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), - ('\u{f71}', '\u{f81}'), ('\u{f88}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{1000}', - '\u{1036}'), ('\u{1038}', '\u{1038}'), ('\u{103b}', '\u{103f}'), ('\u{1050}', '\u{1062}'), - ('\u{1065}', '\u{1068}'), ('\u{106e}', '\u{1086}'), ('\u{108e}', '\u{108e}'), ('\u{109c}', - '\u{109d}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), - ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', - '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), - ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', - '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), - ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{135f}', - '\u{135f}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), - ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}', - '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1713}'), - ('\u{1720}', '\u{1733}'), ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', - '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17b3}'), ('\u{17b6}', '\u{17c8}'), - ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', - '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), - ('\u{1930}', '\u{1938}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'), ('\u{1980}', - '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'), - ('\u{1a61}', '\u{1a74}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1b00}', '\u{1b33}'), ('\u{1b35}', - '\u{1b43}'), ('\u{1b45}', '\u{1b4b}'), ('\u{1b80}', '\u{1ba9}'), ('\u{1bac}', '\u{1baf}'), - ('\u{1bba}', '\u{1be5}'), ('\u{1be7}', '\u{1bf1}'), ('\u{1c00}', '\u{1c35}'), ('\u{1c4d}', - '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf3}'), - ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1de7}', '\u{1df4}'), ('\u{1e00}', - '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), - ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', - '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), - ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', - '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), - ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', - '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), - ('\u{2115}', '\u{2115}'), ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', - '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2139}'), - ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', - '\u{2188}'), ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), - ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', - '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), - ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', - '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), - ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{2de0}', - '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{3029}'), - ('\u{3031}', '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}', - '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'), - ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', - '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), - ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a640}', - '\u{a66e}'), ('\u{a674}', '\u{a67b}'), ('\u{a67f}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), - ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', - '\u{a801}'), ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a827}'), - ('\u{a840}', '\u{a873}'), ('\u{a880}', '\u{a8c3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', - '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}', '\u{a92a}'), ('\u{a930}', '\u{a952}'), - ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9b2}'), ('\u{a9b4}', '\u{a9bf}'), ('\u{a9cf}', - '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), - ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', - '\u{aa7a}'), ('\u{aa7e}', '\u{aabe}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), - ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf5}'), ('\u{ab01}', - '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), - ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', - '\u{abea}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), - ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', - '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), - ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', - '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), - ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', - '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), - ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', - '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', - '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', - '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', - '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{1034a}'), ('\u{10350}', - '\u{1037a}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', - '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', - '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', - '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', - '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', - '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', - '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', - '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', - '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}', - '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', - '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', - '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', - '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', - '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{11000}', '\u{11045}'), ('\u{11082}', - '\u{110b8}'), ('\u{110d0}', '\u{110e8}'), ('\u{11100}', '\u{11132}'), ('\u{11150}', - '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11180}', '\u{111bf}'), ('\u{111c1}', - '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', - '\u{11211}'), ('\u{11213}', '\u{11234}'), ('\u{11237}', '\u{11237}'), ('\u{11280}', - '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'), ('\u{1128f}', - '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112e8}'), ('\u{11300}', - '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', - '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', - '\u{11339}'), ('\u{1133d}', '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}', - '\u{1134c}'), ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}', - '\u{11363}'), ('\u{11480}', '\u{114c1}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', - '\u{114c7}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115be}'), ('\u{115d8}', - '\u{115dd}'), ('\u{11600}', '\u{1163e}'), ('\u{11640}', '\u{11640}'), ('\u{11644}', - '\u{11644}'), ('\u{11680}', '\u{116b5}'), ('\u{11700}', '\u{11719}'), ('\u{1171d}', - '\u{1172a}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', - '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', - '\u{12543}'), ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', - '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}', - '\u{16b36}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', - '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f93}', - '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', - '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9e}', - '\u{1bc9e}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', - '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', - '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', - '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', - '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', - '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', - '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', - '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', - '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', - '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', - '\u{1d7cb}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', - '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', - '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', - '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', - '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', - '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', - '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', - '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', - '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', - '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', - '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', - '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'), ('\u{1f150}', - '\u{1f169}'), ('\u{1f170}', '\u{1f189}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', - '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', - '\u{2fa1d}') - ]; + pub const Alphabetic_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, + 0x0000000000000000, 0xbcdf000000000020, 0xfffffffbffffd740, 0xffbfffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff, + 0xfffeffffffffffff, 0xfffffffe027fffff, 0xbfff0000000000ff, 0x000707ffffff00b6, + 0xffffffff07ff0000, 0xffffc000feffffff, 0xffffffffffffffff, 0x9c00e1fe1fefffff, + 0xffffffffffff0000, 0xffffffffffffe000, 0x0003ffffffffffff, 0x043007fffffffc00 + ], + r2: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 36, 36, 36, 36, 36, 36, 36, 36, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 31, 63, 64, 65, 66, 55, 67, 31, 68, 36, 36, 36, 69, 36, 36, + 36, 36, 70, 71, 72, 73, 31, 74, 75, 31, 76, 77, 78, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 79, 80, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 81, 82, 36, 83, 84, 85, 86, 87, 88, 31, 31, 31, + 31, 31, 31, 31, 89, 44, 90, 91, 92, 36, 93, 94, 31, 31, 31, 31, 31, 31, 31, 31, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 55, 31, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 96, 97, 36, 36, 36, 36, 98, 99, 36, 100, 101, 36, 102, + 103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 117, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 127, 128, + 129, 31, 130, 36, 131, 132, 133, 113, 134 + ], + r3: &[ + 0x00001ffffcffffff, 0x0000000001ffffff, 0x001fffff00000000, 0xffff03f800000000, + 0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x0003000fb080599f, + 0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x0200000f00011bbf, + 0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7, + 0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfee, 0x0006000f40601ddf, + 0xe7fffffffffddfee, 0xfc00000f80805ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f, + 0x07fffffffffffffe, 0x000000000000207f, 0x3bffecaefef02596, 0x00000000f000205f, + 0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000, + 0xf97fffffffffffff, 0xffffc1e7ffff0000, 0xffffffff3000407f, 0xf7ffffffffff20bf, + 0xffffffffffffffff, 0xffffffff3d7f3dff, 0x7f3dffffffff3dff, 0xffffffffff7fff3d, + 0xffffffffff3dffff, 0x0000000087ffffff, 0xffffffff0000ffff, 0x3f3fffffffffffff, + 0xfffffffffffffffe, 0xffff9fffffffffff, 0xffffffff07fffffe, 0x01ffc7ffffffffff, + 0x000fffff000fdfff, 0x000ddfff000fffff, 0xffcfffffffffffff, 0x00000000108001ff, + 0xffffffff00000000, 0x00ffffffffffffff, 0xffff07ffffffffff, 0x003fffffffffffff, + 0x01ff0fff7fffffff, 0x001f3fffffff0000, 0xffff0fffffffffff, 0x00000000000003ff, + 0xffffffff0fffffff, 0x001ffffe7fffffff, 0x0000008000000000, 0xffefffffffffffff, + 0x0000000000000fef, 0xfc00f3ffffffffff, 0x0003ffbfffffffff, 0x3ffffffffc00e000, + 0x006fde0000000000, 0x001fff8000000000, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, + 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, + 0xf3ffbd503e2ffc84, 0xffffffff000043e0, 0x00000000000001ff, 0xffc0000000000000, + 0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, + 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, + 0x0000800000000000, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, + 0xfffe3fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, + 0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x8ff07fffffffffff, + 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff3ffffffff9ff, 0xff80000000000000, + 0x000000fffffff7bb, 0x000fffffffffffff, 0x28fc00000000000f, 0xffff07fffffffc00, + 0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffdf00008000, 0x007fffffffffffff, + 0xc47fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e, + 0xffff003ff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, + 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, + 0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, + 0xfffffffffffcffff, 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, + 0x07fffffe00000000, 0xffffffc007fffffe, 0x000000001cfcfcfc + ], + r4: [ + 0, 1, 2, 3, 4, 5, 6, 5, 5, 5, 5, 7, 5, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 13, 14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + ], + r5: &[ + 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 4, 13, 14, 4, 4, 2, 2, 2, 2, + 15, 16, 4, 4, 17, 18, 19, 20, 21, 4, 22, 4, 23, 24, 25, 26, 27, 28, 29, 4, 2, 30, 31, + 31, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 32, 33, 34, 31, 35, 2, 36, 37, 4, 38, 39, 40, + 41, 4, 4, 4, 4, 2, 42, 4, 4, 43, 44, 45, 46, 27, 4, 47, 4, 4, 4, 4, 4, 48, 49, 4, 4, 4, + 4, 4, 4, 4, 50, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 52, 2, 2, 2, 53, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 50, 19, 4, 55, 15, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 58, 59, 4, + 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 61, 62, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64, 65, 66, 67, + 2, 2, 2, 2, 68, 69, 70, 71, 72, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 74, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 75, 76, 77, 4, 4, 4, 4, 4, 4, 4, 4, 4, 78, 79, + 80, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 81, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 82, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4 + ], + r6: &[ + 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, + 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, + 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0x000000003fffffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, + 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, + 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, 0x000ffffffeeff06f, + 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff, 0x003fffffffffffff, + 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff, 0x0007ffffffffffff, + 0x000000000000003f, 0x01fffffffffffffc, 0x000001ffffff0000, 0x0047ffffffff0000, + 0x000000001400001e, 0x009ffffffffbffff, 0xffff01ffbfffbd7f, 0x000001ffffffffff, + 0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000000000b3, 0x7f3fffffffffffff, + 0x000000003f000000, 0x7fffffffffffffff, 0x0000000000000011, 0x000007ffe3ffffff, + 0xffffffff00000000, 0x80000000ffffffff, 0x01ffffffffffffff, 0x0000000003ffffff, + 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, 0x00003fffffff0000, + 0xe0fffff80000000f, 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000fff80000, + 0x0000000000000003, 0x1fff07ffffffffff, 0x0000000043ff01ff, 0xffffffffffdfffff, + 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, + 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, + 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef, + 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0xffff000000000000, 0xffff03ffffff03ff, + 0x00000000000003ff, 0x00000000007fffff, 0x00000003ffffffff + ], + }; pub fn Alphabetic(c: char) -> bool { - super::bsearch_range_table(c, Alphabetic_table) + super::trie_lookup_range_table(c, Alphabetic_table) } - pub const Case_Ignorable_table: &'static [(char, char)] = &[ - ('\u{27}', '\u{27}'), ('\u{2e}', '\u{2e}'), ('\u{3a}', '\u{3a}'), ('\u{5e}', '\u{5e}'), - ('\u{60}', '\u{60}'), ('\u{a8}', '\u{a8}'), ('\u{ad}', '\u{ad}'), ('\u{af}', '\u{af}'), - ('\u{b4}', '\u{b4}'), ('\u{b7}', '\u{b8}'), ('\u{2b0}', '\u{36f}'), ('\u{374}', '\u{375}'), - ('\u{37a}', '\u{37a}'), ('\u{384}', '\u{385}'), ('\u{387}', '\u{387}'), ('\u{483}', - '\u{489}'), ('\u{559}', '\u{559}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), - ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{5f4}', - '\u{5f4}'), ('\u{600}', '\u{605}'), ('\u{610}', '\u{61a}'), ('\u{61c}', '\u{61c}'), - ('\u{640}', '\u{640}'), ('\u{64b}', '\u{65f}'), ('\u{670}', '\u{670}'), ('\u{6d6}', - '\u{6dd}'), ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), ('\u{70f}', '\u{70f}'), - ('\u{711}', '\u{711}'), ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', - '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), ('\u{816}', '\u{82d}'), ('\u{859}', '\u{85b}'), - ('\u{8e3}', '\u{902}'), ('\u{93a}', '\u{93a}'), ('\u{93c}', '\u{93c}'), ('\u{941}', - '\u{948}'), ('\u{94d}', '\u{94d}'), ('\u{951}', '\u{957}'), ('\u{962}', '\u{963}'), - ('\u{971}', '\u{971}'), ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9c1}', - '\u{9c4}'), ('\u{9cd}', '\u{9cd}'), ('\u{9e2}', '\u{9e3}'), ('\u{a01}', '\u{a02}'), - ('\u{a3c}', '\u{a3c}'), ('\u{a41}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', - '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', '\u{a71}'), ('\u{a75}', '\u{a75}'), - ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'), ('\u{ac1}', '\u{ac5}'), ('\u{ac7}', - '\u{ac8}'), ('\u{acd}', '\u{acd}'), ('\u{ae2}', '\u{ae3}'), ('\u{b01}', '\u{b01}'), - ('\u{b3c}', '\u{b3c}'), ('\u{b3f}', '\u{b3f}'), ('\u{b41}', '\u{b44}'), ('\u{b4d}', - '\u{b4d}'), ('\u{b56}', '\u{b56}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', '\u{b82}'), - ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), ('\u{c00}', '\u{c00}'), ('\u{c3e}', - '\u{c40}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'), - ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c81}'), ('\u{cbc}', '\u{cbc}'), ('\u{cbf}', - '\u{cbf}'), ('\u{cc6}', '\u{cc6}'), ('\u{ccc}', '\u{ccd}'), ('\u{ce2}', '\u{ce3}'), - ('\u{d01}', '\u{d01}'), ('\u{d41}', '\u{d44}'), ('\u{d4d}', '\u{d4d}'), ('\u{d62}', - '\u{d63}'), ('\u{dca}', '\u{dca}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), - ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'), ('\u{e46}', '\u{e4e}'), ('\u{eb1}', - '\u{eb1}'), ('\u{eb4}', '\u{eb9}'), ('\u{ebb}', '\u{ebc}'), ('\u{ec6}', '\u{ec6}'), - ('\u{ec8}', '\u{ecd}'), ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', - '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f71}', '\u{f7e}'), ('\u{f80}', '\u{f84}'), - ('\u{f86}', '\u{f87}'), ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{fc6}', - '\u{fc6}'), ('\u{102d}', '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{1039}', '\u{103a}'), - ('\u{103d}', '\u{103e}'), ('\u{1058}', '\u{1059}'), ('\u{105e}', '\u{1060}'), ('\u{1071}', - '\u{1074}'), ('\u{1082}', '\u{1082}'), ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'), - ('\u{109d}', '\u{109d}'), ('\u{10fc}', '\u{10fc}'), ('\u{135d}', '\u{135f}'), ('\u{1712}', - '\u{1714}'), ('\u{1732}', '\u{1734}'), ('\u{1752}', '\u{1753}'), ('\u{1772}', '\u{1773}'), - ('\u{17b4}', '\u{17b5}'), ('\u{17b7}', '\u{17bd}'), ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', - '\u{17d3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dd}', '\u{17dd}'), ('\u{180b}', '\u{180e}'), - ('\u{1843}', '\u{1843}'), ('\u{18a9}', '\u{18a9}'), ('\u{1920}', '\u{1922}'), ('\u{1927}', - '\u{1928}'), ('\u{1932}', '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}', '\u{1a18}'), - ('\u{1a1b}', '\u{1a1b}'), ('\u{1a56}', '\u{1a56}'), ('\u{1a58}', '\u{1a5e}'), ('\u{1a60}', - '\u{1a60}'), ('\u{1a62}', '\u{1a62}'), ('\u{1a65}', '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'), - ('\u{1a7f}', '\u{1a7f}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1ab0}', '\u{1abe}'), ('\u{1b00}', - '\u{1b03}'), ('\u{1b34}', '\u{1b34}'), ('\u{1b36}', '\u{1b3a}'), ('\u{1b3c}', '\u{1b3c}'), - ('\u{1b42}', '\u{1b42}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', - '\u{1ba5}'), ('\u{1ba8}', '\u{1ba9}'), ('\u{1bab}', '\u{1bad}'), ('\u{1be6}', '\u{1be6}'), - ('\u{1be8}', '\u{1be9}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bef}', '\u{1bf1}'), ('\u{1c2c}', - '\u{1c33}'), ('\u{1c36}', '\u{1c37}'), ('\u{1c78}', '\u{1c7d}'), ('\u{1cd0}', '\u{1cd2}'), - ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}', - '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), ('\u{1d2c}', '\u{1d6a}'), ('\u{1d78}', '\u{1d78}'), - ('\u{1d9b}', '\u{1df5}'), ('\u{1dfc}', '\u{1dff}'), ('\u{1fbd}', '\u{1fbd}'), ('\u{1fbf}', - '\u{1fc1}'), ('\u{1fcd}', '\u{1fcf}'), ('\u{1fdd}', '\u{1fdf}'), ('\u{1fed}', '\u{1fef}'), - ('\u{1ffd}', '\u{1ffe}'), ('\u{200b}', '\u{200f}'), ('\u{2018}', '\u{2019}'), ('\u{2024}', - '\u{2024}'), ('\u{2027}', '\u{2027}'), ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{2064}'), - ('\u{2066}', '\u{206f}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', - '\u{209c}'), ('\u{20d0}', '\u{20f0}'), ('\u{2c7c}', '\u{2c7d}'), ('\u{2cef}', '\u{2cf1}'), - ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', - '\u{2e2f}'), ('\u{3005}', '\u{3005}'), ('\u{302a}', '\u{302d}'), ('\u{3031}', '\u{3035}'), - ('\u{303b}', '\u{303b}'), ('\u{3099}', '\u{309e}'), ('\u{30fc}', '\u{30fe}'), ('\u{a015}', - '\u{a015}'), ('\u{a4f8}', '\u{a4fd}'), ('\u{a60c}', '\u{a60c}'), ('\u{a66f}', '\u{a672}'), - ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a67f}'), ('\u{a69c}', '\u{a69f}'), ('\u{a6f0}', - '\u{a6f1}'), ('\u{a700}', '\u{a721}'), ('\u{a770}', '\u{a770}'), ('\u{a788}', '\u{a78a}'), - ('\u{a7f8}', '\u{a7f9}'), ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), ('\u{a80b}', - '\u{a80b}'), ('\u{a825}', '\u{a826}'), ('\u{a8c4}', '\u{a8c4}'), ('\u{a8e0}', '\u{a8f1}'), - ('\u{a926}', '\u{a92d}'), ('\u{a947}', '\u{a951}'), ('\u{a980}', '\u{a982}'), ('\u{a9b3}', - '\u{a9b3}'), ('\u{a9b6}', '\u{a9b9}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9cf}', '\u{a9cf}'), - ('\u{a9e5}', '\u{a9e6}'), ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'), ('\u{aa35}', - '\u{aa36}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa4c}', '\u{aa4c}'), ('\u{aa70}', '\u{aa70}'), - ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab2}', '\u{aab4}'), ('\u{aab7}', - '\u{aab8}'), ('\u{aabe}', '\u{aabf}'), ('\u{aac1}', '\u{aac1}'), ('\u{aadd}', '\u{aadd}'), - ('\u{aaec}', '\u{aaed}'), ('\u{aaf3}', '\u{aaf4}'), ('\u{aaf6}', '\u{aaf6}'), ('\u{ab5b}', - '\u{ab5f}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}', '\u{abe8}'), ('\u{abed}', '\u{abed}'), - ('\u{fb1e}', '\u{fb1e}'), ('\u{fbb2}', '\u{fbc1}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe13}', - '\u{fe13}'), ('\u{fe20}', '\u{fe2f}'), ('\u{fe52}', '\u{fe52}'), ('\u{fe55}', '\u{fe55}'), - ('\u{feff}', '\u{feff}'), ('\u{ff07}', '\u{ff07}'), ('\u{ff0e}', '\u{ff0e}'), ('\u{ff1a}', - '\u{ff1a}'), ('\u{ff3e}', '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'), ('\u{ff70}', '\u{ff70}'), - ('\u{ff9e}', '\u{ff9f}'), ('\u{ffe3}', '\u{ffe3}'), ('\u{fff9}', '\u{fffb}'), ('\u{101fd}', - '\u{101fd}'), ('\u{102e0}', '\u{102e0}'), ('\u{10376}', '\u{1037a}'), ('\u{10a01}', - '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', - '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{11001}', - '\u{11001}'), ('\u{11038}', '\u{11046}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}', - '\u{110b6}'), ('\u{110b9}', '\u{110ba}'), ('\u{110bd}', '\u{110bd}'), ('\u{11100}', - '\u{11102}'), ('\u{11127}', '\u{1112b}'), ('\u{1112d}', '\u{11134}'), ('\u{11173}', - '\u{11173}'), ('\u{11180}', '\u{11181}'), ('\u{111b6}', '\u{111be}'), ('\u{111ca}', - '\u{111cc}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}', '\u{11234}'), ('\u{11236}', - '\u{11237}'), ('\u{112df}', '\u{112df}'), ('\u{112e3}', '\u{112ea}'), ('\u{11300}', - '\u{11301}'), ('\u{1133c}', '\u{1133c}'), ('\u{11340}', '\u{11340}'), ('\u{11366}', - '\u{1136c}'), ('\u{11370}', '\u{11374}'), ('\u{114b3}', '\u{114b8}'), ('\u{114ba}', - '\u{114ba}'), ('\u{114bf}', '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115b2}', - '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}', '\u{115c0}'), ('\u{115dc}', - '\u{115dd}'), ('\u{11633}', '\u{1163a}'), ('\u{1163d}', '\u{1163d}'), ('\u{1163f}', - '\u{11640}'), ('\u{116ab}', '\u{116ab}'), ('\u{116ad}', '\u{116ad}'), ('\u{116b0}', - '\u{116b5}'), ('\u{116b7}', '\u{116b7}'), ('\u{1171d}', '\u{1171f}'), ('\u{11722}', - '\u{11725}'), ('\u{11727}', '\u{1172b}'), ('\u{16af0}', '\u{16af4}'), ('\u{16b30}', - '\u{16b36}'), ('\u{16b40}', '\u{16b43}'), ('\u{16f8f}', '\u{16f9f}'), ('\u{1bc9d}', - '\u{1bc9e}'), ('\u{1bca0}', '\u{1bca3}'), ('\u{1d167}', '\u{1d169}'), ('\u{1d173}', - '\u{1d182}'), ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', - '\u{1d244}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}', - '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', - '\u{1daaf}'), ('\u{1e8d0}', '\u{1e8d6}'), ('\u{1f3fb}', '\u{1f3ff}'), ('\u{e0001}', - '\u{e0001}'), ('\u{e0020}', '\u{e007f}'), ('\u{e0100}', '\u{e01ef}') - ]; + pub const Case_Ignorable_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0400408000000000, 0x0000000140000000, 0x0190a10000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0xffff000000000000, 0xffffffffffffffff, + 0xffffffffffffffff, 0x0430ffffffffffff, 0x00000000000000b0, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x00000000000003f8, 0x0000000000000000, + 0x0000000000000000, 0x0000000002000000, 0xbffffffffffe0000, 0x00100000000000b6, + 0x0000000017ff003f, 0x00010000fffff801, 0x0000000000000000, 0x00003dffbfc00000, + 0xffff000000028000, 0x00000000000007ff, 0x0001ffc000000000, 0x043ff80000000000 + ], + r2: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 11, 12, 13, 14, 15, 16, 11, 17, 18, 7, 2, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 34, 35, 36, 37, 38, 39, 2, 40, 2, 2, 2, 41, 42, 43, 2, + 44, 45, 46, 47, 48, 49, 2, 50, 51, 52, 53, 54, 2, 2, 2, 2, 2, 2, 55, 56, 57, 58, 59, 60, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 2, 62, 2, 63, 2, 64, 65, 2, 2, 2, 2, + 2, 2, 2, 66, 2, 67, 68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 49, 2, 2, 2, 2, 70, 71, 72, 73, 74, 75, 76, 77, 78, 2, 2, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 2, 88, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 91, 92, 2, 2, 2, 2, 2, 2, 2, 2, 93, 94, 2, 95, + 96, 97, 98, 99 + ], + r3: &[ + 0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffff800000000, + 0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x0000000c0000201e, + 0x1000000000000006, 0x0023000000023986, 0x0000000c000021be, 0x9000000000000002, + 0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000001, + 0x0000000c00603dc1, 0x0000000c00003040, 0x0000000000000002, 0x00000000005c0400, + 0x07f2000000000000, 0x0000000000007fc0, 0x1bf2000000000000, 0x0000000000003f40, + 0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x0000000000000040, + 0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064, 0x1000000000000000, + 0x00000000e0000000, 0x001c0000001c0000, 0x000c0000000c0000, 0x3fb0000000000000, + 0x00000000208ffe40, 0x0000000000007800, 0x0000000000000008, 0x0000020000000000, + 0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff008000000000, + 0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000, + 0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000, 0xfffff00000000000, + 0x010007ffffffffff, 0xfffffffff8000000, 0xf03fffffffffffff, 0xa000000000000000, + 0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000, 0x000000001fff0000, + 0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000, 0x8000800000000000, + 0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020, 0x000000007e000000, + 0x7000000000000000, 0x0000000000200000, 0x0000000000001000, 0xbff7800000000000, + 0x00000000f0000000, 0x0003000000000000, 0x00000003ffffffff, 0x0001000000000000, + 0x0000000000000700, 0x0300000000000000, 0x0000006000000844, 0x0003ffff00000010, + 0x00003fc000000000, 0x000000000003ff80, 0x13c8000000000007, 0x0000006000008000, + 0x00667e0000000000, 0x1001000000001008, 0xc19d000000000000, 0x0058300020000002, + 0x00000000f8000000, 0x0000212000000000, 0x0000000040000000, 0xfffc000000000000, + 0x0000000000000003, 0x0000ffff0008ffff, 0x0000000000240000, 0x8000000000000000, + 0x4000000004004080, 0x0001000000000001, 0x00000000c0000000, 0x0e00000800000000 + ], + r4: [ + 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 4, 2, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 0, 0, 0, 0, 17, 18, + 0, 0, 19, 20, 21, 22, 23, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, + 0, 0, 39, 39, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000, + 0x870000000000f06e, 0x0000006000000000, 0xff00000000000002, 0x800000000000007f, + 0x2678000000000003, 0x001fef8000000007, 0x0008000000000000, 0x7fc0000000000003, + 0x0000000000001c00, 0x00d3800000000000, 0x000007f880000000, 0x1000000000000003, + 0x001f1fc000000001, 0x85f8000000000000, 0x000000000000000d, 0xb03c000000000000, + 0x0000000030000001, 0xa7f8000000000000, 0x0000000000000001, 0x00bf280000000000, + 0x00000fbce0000000, 0x001f000000000000, 0x007f000000000000, 0x000000000000000f, + 0x00000000ffff8000, 0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7, + 0x000000000000001c, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, + 0x00000000007f0000, 0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff, + 0x0000ffffffffffff + ], + }; pub fn Case_Ignorable(c: char) -> bool { - super::bsearch_range_table(c, Case_Ignorable_table) + super::trie_lookup_range_table(c, Case_Ignorable_table) } - pub const Cased_table: &'static [(char, char)] = &[ - ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), - ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), - ('\u{1bc}', '\u{1bf}'), ('\u{1c4}', '\u{293}'), ('\u{295}', '\u{2b8}'), ('\u{2c0}', - '\u{2c1}'), ('\u{2e0}', '\u{2e4}'), ('\u{345}', '\u{345}'), ('\u{370}', '\u{373}'), - ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{386}', - '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), - ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{48a}', '\u{52f}'), ('\u{531}', - '\u{556}'), ('\u{561}', '\u{587}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), - ('\u{10cd}', '\u{10cd}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', - '\u{1dbf}'), ('\u{1e00}', '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), - ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', - '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), - ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', - '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), - ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', - '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), - ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'), ('\u{2119}', '\u{211d}'), ('\u{2124}', - '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'), - ('\u{212f}', '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213f}'), ('\u{2145}', - '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{217f}'), ('\u{2183}', '\u{2184}'), - ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', - '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), - ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{a640}', '\u{a66d}'), ('\u{a680}', - '\u{a69d}'), ('\u{a722}', '\u{a787}'), ('\u{a78b}', '\u{a78e}'), ('\u{a790}', '\u{a7ad}'), - ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f8}', '\u{a7fa}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', - '\u{ab65}'), ('\u{ab70}', '\u{abbf}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), - ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10400}', '\u{1044f}'), - ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{118a0}', '\u{118df}'), - ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), - ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), - ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), - ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), - ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), - ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), - ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), - ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), - ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), - ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), - ('\u{1f130}', '\u{1f149}'), ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}') - ]; + pub const Cased_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xf7ffffffffffffff, 0xfffffffffffffff0, + 0xffffffffffffffff, 0xffffffffffffffff, 0x01ffffffffefffff, 0x0000001f00000003, + 0x0000000000000000, 0xbccf000000000020, 0xfffffffbffffd740, 0xffbfffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff, + 0xfffeffffffffffff, 0xfffffffe007fffff, 0x00000000000000ff, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, + 0, 4, 4, 4, 4, 5, 6, 7, 8, 0, 9, 10, 0, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 17, 4, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 0, + 22, 4, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 26, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28, 29, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0xffffffff00000000, 0x00000000000020bf, 0x3f3fffffffffffff, + 0xffffffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, + 0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf21fbd503e2ffc84, + 0xffffffff000043e0, 0x0000000000000018, 0xffc0000000000000, 0x000003ffffffffff, + 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, 0x000020bfffffffff, + 0x00003fffffffffff, 0x000000003fffffff, 0xfffffffc00000000, 0x00ff3fffffff78ff, + 0x0700000000000000, 0xffff000000000000, 0xffff003ff7ffffff, 0x0000000000f8007f, + 0x07fffffe00000000, 0x0000000007fffffe + ], + r4: [ + 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 6, 7, 8, 9, 10, 1, 1, 1, 1, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000, 0xffffffffffffffff, 0x000000000000ffff, 0x0007ffffffffffff, + 0xffffffff00000000, 0x00000000ffffffff, 0xffffffffffdfffff, 0xebffde64dfffffff, + 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, + 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, + 0x0000000000000ff7, 0xffff000000000000, 0xffff03ffffff03ff, 0x00000000000003ff + ], + }; pub fn Cased(c: char) -> bool { - super::bsearch_range_table(c, Cased_table) + super::trie_lookup_range_table(c, Cased_table) } - pub const Lowercase_table: &'static [(char, char)] = &[ - ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), - ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'), - ('\u{105}', '\u{105}'), ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'), ('\u{10b}', - '\u{10b}'), ('\u{10d}', '\u{10d}'), ('\u{10f}', '\u{10f}'), ('\u{111}', '\u{111}'), - ('\u{113}', '\u{113}'), ('\u{115}', '\u{115}'), ('\u{117}', '\u{117}'), ('\u{119}', - '\u{119}'), ('\u{11b}', '\u{11b}'), ('\u{11d}', '\u{11d}'), ('\u{11f}', '\u{11f}'), - ('\u{121}', '\u{121}'), ('\u{123}', '\u{123}'), ('\u{125}', '\u{125}'), ('\u{127}', - '\u{127}'), ('\u{129}', '\u{129}'), ('\u{12b}', '\u{12b}'), ('\u{12d}', '\u{12d}'), - ('\u{12f}', '\u{12f}'), ('\u{131}', '\u{131}'), ('\u{133}', '\u{133}'), ('\u{135}', - '\u{135}'), ('\u{137}', '\u{138}'), ('\u{13a}', '\u{13a}'), ('\u{13c}', '\u{13c}'), - ('\u{13e}', '\u{13e}'), ('\u{140}', '\u{140}'), ('\u{142}', '\u{142}'), ('\u{144}', - '\u{144}'), ('\u{146}', '\u{146}'), ('\u{148}', '\u{149}'), ('\u{14b}', '\u{14b}'), - ('\u{14d}', '\u{14d}'), ('\u{14f}', '\u{14f}'), ('\u{151}', '\u{151}'), ('\u{153}', - '\u{153}'), ('\u{155}', '\u{155}'), ('\u{157}', '\u{157}'), ('\u{159}', '\u{159}'), - ('\u{15b}', '\u{15b}'), ('\u{15d}', '\u{15d}'), ('\u{15f}', '\u{15f}'), ('\u{161}', - '\u{161}'), ('\u{163}', '\u{163}'), ('\u{165}', '\u{165}'), ('\u{167}', '\u{167}'), - ('\u{169}', '\u{169}'), ('\u{16b}', '\u{16b}'), ('\u{16d}', '\u{16d}'), ('\u{16f}', - '\u{16f}'), ('\u{171}', '\u{171}'), ('\u{173}', '\u{173}'), ('\u{175}', '\u{175}'), - ('\u{177}', '\u{177}'), ('\u{17a}', '\u{17a}'), ('\u{17c}', '\u{17c}'), ('\u{17e}', - '\u{180}'), ('\u{183}', '\u{183}'), ('\u{185}', '\u{185}'), ('\u{188}', '\u{188}'), - ('\u{18c}', '\u{18d}'), ('\u{192}', '\u{192}'), ('\u{195}', '\u{195}'), ('\u{199}', - '\u{19b}'), ('\u{19e}', '\u{19e}'), ('\u{1a1}', '\u{1a1}'), ('\u{1a3}', '\u{1a3}'), - ('\u{1a5}', '\u{1a5}'), ('\u{1a8}', '\u{1a8}'), ('\u{1aa}', '\u{1ab}'), ('\u{1ad}', - '\u{1ad}'), ('\u{1b0}', '\u{1b0}'), ('\u{1b4}', '\u{1b4}'), ('\u{1b6}', '\u{1b6}'), - ('\u{1b9}', '\u{1ba}'), ('\u{1bd}', '\u{1bf}'), ('\u{1c6}', '\u{1c6}'), ('\u{1c9}', - '\u{1c9}'), ('\u{1cc}', '\u{1cc}'), ('\u{1ce}', '\u{1ce}'), ('\u{1d0}', '\u{1d0}'), - ('\u{1d2}', '\u{1d2}'), ('\u{1d4}', '\u{1d4}'), ('\u{1d6}', '\u{1d6}'), ('\u{1d8}', - '\u{1d8}'), ('\u{1da}', '\u{1da}'), ('\u{1dc}', '\u{1dd}'), ('\u{1df}', '\u{1df}'), - ('\u{1e1}', '\u{1e1}'), ('\u{1e3}', '\u{1e3}'), ('\u{1e5}', '\u{1e5}'), ('\u{1e7}', - '\u{1e7}'), ('\u{1e9}', '\u{1e9}'), ('\u{1eb}', '\u{1eb}'), ('\u{1ed}', '\u{1ed}'), - ('\u{1ef}', '\u{1f0}'), ('\u{1f3}', '\u{1f3}'), ('\u{1f5}', '\u{1f5}'), ('\u{1f9}', - '\u{1f9}'), ('\u{1fb}', '\u{1fb}'), ('\u{1fd}', '\u{1fd}'), ('\u{1ff}', '\u{1ff}'), - ('\u{201}', '\u{201}'), ('\u{203}', '\u{203}'), ('\u{205}', '\u{205}'), ('\u{207}', - '\u{207}'), ('\u{209}', '\u{209}'), ('\u{20b}', '\u{20b}'), ('\u{20d}', '\u{20d}'), - ('\u{20f}', '\u{20f}'), ('\u{211}', '\u{211}'), ('\u{213}', '\u{213}'), ('\u{215}', - '\u{215}'), ('\u{217}', '\u{217}'), ('\u{219}', '\u{219}'), ('\u{21b}', '\u{21b}'), - ('\u{21d}', '\u{21d}'), ('\u{21f}', '\u{21f}'), ('\u{221}', '\u{221}'), ('\u{223}', - '\u{223}'), ('\u{225}', '\u{225}'), ('\u{227}', '\u{227}'), ('\u{229}', '\u{229}'), - ('\u{22b}', '\u{22b}'), ('\u{22d}', '\u{22d}'), ('\u{22f}', '\u{22f}'), ('\u{231}', - '\u{231}'), ('\u{233}', '\u{239}'), ('\u{23c}', '\u{23c}'), ('\u{23f}', '\u{240}'), - ('\u{242}', '\u{242}'), ('\u{247}', '\u{247}'), ('\u{249}', '\u{249}'), ('\u{24b}', - '\u{24b}'), ('\u{24d}', '\u{24d}'), ('\u{24f}', '\u{293}'), ('\u{295}', '\u{2b8}'), - ('\u{2c0}', '\u{2c1}'), ('\u{2e0}', '\u{2e4}'), ('\u{345}', '\u{345}'), ('\u{371}', - '\u{371}'), ('\u{373}', '\u{373}'), ('\u{377}', '\u{377}'), ('\u{37a}', '\u{37d}'), - ('\u{390}', '\u{390}'), ('\u{3ac}', '\u{3ce}'), ('\u{3d0}', '\u{3d1}'), ('\u{3d5}', - '\u{3d7}'), ('\u{3d9}', '\u{3d9}'), ('\u{3db}', '\u{3db}'), ('\u{3dd}', '\u{3dd}'), - ('\u{3df}', '\u{3df}'), ('\u{3e1}', '\u{3e1}'), ('\u{3e3}', '\u{3e3}'), ('\u{3e5}', - '\u{3e5}'), ('\u{3e7}', '\u{3e7}'), ('\u{3e9}', '\u{3e9}'), ('\u{3eb}', '\u{3eb}'), - ('\u{3ed}', '\u{3ed}'), ('\u{3ef}', '\u{3f3}'), ('\u{3f5}', '\u{3f5}'), ('\u{3f8}', - '\u{3f8}'), ('\u{3fb}', '\u{3fc}'), ('\u{430}', '\u{45f}'), ('\u{461}', '\u{461}'), - ('\u{463}', '\u{463}'), ('\u{465}', '\u{465}'), ('\u{467}', '\u{467}'), ('\u{469}', - '\u{469}'), ('\u{46b}', '\u{46b}'), ('\u{46d}', '\u{46d}'), ('\u{46f}', '\u{46f}'), - ('\u{471}', '\u{471}'), ('\u{473}', '\u{473}'), ('\u{475}', '\u{475}'), ('\u{477}', - '\u{477}'), ('\u{479}', '\u{479}'), ('\u{47b}', '\u{47b}'), ('\u{47d}', '\u{47d}'), - ('\u{47f}', '\u{47f}'), ('\u{481}', '\u{481}'), ('\u{48b}', '\u{48b}'), ('\u{48d}', - '\u{48d}'), ('\u{48f}', '\u{48f}'), ('\u{491}', '\u{491}'), ('\u{493}', '\u{493}'), - ('\u{495}', '\u{495}'), ('\u{497}', '\u{497}'), ('\u{499}', '\u{499}'), ('\u{49b}', - '\u{49b}'), ('\u{49d}', '\u{49d}'), ('\u{49f}', '\u{49f}'), ('\u{4a1}', '\u{4a1}'), - ('\u{4a3}', '\u{4a3}'), ('\u{4a5}', '\u{4a5}'), ('\u{4a7}', '\u{4a7}'), ('\u{4a9}', - '\u{4a9}'), ('\u{4ab}', '\u{4ab}'), ('\u{4ad}', '\u{4ad}'), ('\u{4af}', '\u{4af}'), - ('\u{4b1}', '\u{4b1}'), ('\u{4b3}', '\u{4b3}'), ('\u{4b5}', '\u{4b5}'), ('\u{4b7}', - '\u{4b7}'), ('\u{4b9}', '\u{4b9}'), ('\u{4bb}', '\u{4bb}'), ('\u{4bd}', '\u{4bd}'), - ('\u{4bf}', '\u{4bf}'), ('\u{4c2}', '\u{4c2}'), ('\u{4c4}', '\u{4c4}'), ('\u{4c6}', - '\u{4c6}'), ('\u{4c8}', '\u{4c8}'), ('\u{4ca}', '\u{4ca}'), ('\u{4cc}', '\u{4cc}'), - ('\u{4ce}', '\u{4cf}'), ('\u{4d1}', '\u{4d1}'), ('\u{4d3}', '\u{4d3}'), ('\u{4d5}', - '\u{4d5}'), ('\u{4d7}', '\u{4d7}'), ('\u{4d9}', '\u{4d9}'), ('\u{4db}', '\u{4db}'), - ('\u{4dd}', '\u{4dd}'), ('\u{4df}', '\u{4df}'), ('\u{4e1}', '\u{4e1}'), ('\u{4e3}', - '\u{4e3}'), ('\u{4e5}', '\u{4e5}'), ('\u{4e7}', '\u{4e7}'), ('\u{4e9}', '\u{4e9}'), - ('\u{4eb}', '\u{4eb}'), ('\u{4ed}', '\u{4ed}'), ('\u{4ef}', '\u{4ef}'), ('\u{4f1}', - '\u{4f1}'), ('\u{4f3}', '\u{4f3}'), ('\u{4f5}', '\u{4f5}'), ('\u{4f7}', '\u{4f7}'), - ('\u{4f9}', '\u{4f9}'), ('\u{4fb}', '\u{4fb}'), ('\u{4fd}', '\u{4fd}'), ('\u{4ff}', - '\u{4ff}'), ('\u{501}', '\u{501}'), ('\u{503}', '\u{503}'), ('\u{505}', '\u{505}'), - ('\u{507}', '\u{507}'), ('\u{509}', '\u{509}'), ('\u{50b}', '\u{50b}'), ('\u{50d}', - '\u{50d}'), ('\u{50f}', '\u{50f}'), ('\u{511}', '\u{511}'), ('\u{513}', '\u{513}'), - ('\u{515}', '\u{515}'), ('\u{517}', '\u{517}'), ('\u{519}', '\u{519}'), ('\u{51b}', - '\u{51b}'), ('\u{51d}', '\u{51d}'), ('\u{51f}', '\u{51f}'), ('\u{521}', '\u{521}'), - ('\u{523}', '\u{523}'), ('\u{525}', '\u{525}'), ('\u{527}', '\u{527}'), ('\u{529}', - '\u{529}'), ('\u{52b}', '\u{52b}'), ('\u{52d}', '\u{52d}'), ('\u{52f}', '\u{52f}'), - ('\u{561}', '\u{587}'), ('\u{13f8}', '\u{13fd}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e01}', - '\u{1e01}'), ('\u{1e03}', '\u{1e03}'), ('\u{1e05}', '\u{1e05}'), ('\u{1e07}', '\u{1e07}'), - ('\u{1e09}', '\u{1e09}'), ('\u{1e0b}', '\u{1e0b}'), ('\u{1e0d}', '\u{1e0d}'), ('\u{1e0f}', - '\u{1e0f}'), ('\u{1e11}', '\u{1e11}'), ('\u{1e13}', '\u{1e13}'), ('\u{1e15}', '\u{1e15}'), - ('\u{1e17}', '\u{1e17}'), ('\u{1e19}', '\u{1e19}'), ('\u{1e1b}', '\u{1e1b}'), ('\u{1e1d}', - '\u{1e1d}'), ('\u{1e1f}', '\u{1e1f}'), ('\u{1e21}', '\u{1e21}'), ('\u{1e23}', '\u{1e23}'), - ('\u{1e25}', '\u{1e25}'), ('\u{1e27}', '\u{1e27}'), ('\u{1e29}', '\u{1e29}'), ('\u{1e2b}', - '\u{1e2b}'), ('\u{1e2d}', '\u{1e2d}'), ('\u{1e2f}', '\u{1e2f}'), ('\u{1e31}', '\u{1e31}'), - ('\u{1e33}', '\u{1e33}'), ('\u{1e35}', '\u{1e35}'), ('\u{1e37}', '\u{1e37}'), ('\u{1e39}', - '\u{1e39}'), ('\u{1e3b}', '\u{1e3b}'), ('\u{1e3d}', '\u{1e3d}'), ('\u{1e3f}', '\u{1e3f}'), - ('\u{1e41}', '\u{1e41}'), ('\u{1e43}', '\u{1e43}'), ('\u{1e45}', '\u{1e45}'), ('\u{1e47}', - '\u{1e47}'), ('\u{1e49}', '\u{1e49}'), ('\u{1e4b}', '\u{1e4b}'), ('\u{1e4d}', '\u{1e4d}'), - ('\u{1e4f}', '\u{1e4f}'), ('\u{1e51}', '\u{1e51}'), ('\u{1e53}', '\u{1e53}'), ('\u{1e55}', - '\u{1e55}'), ('\u{1e57}', '\u{1e57}'), ('\u{1e59}', '\u{1e59}'), ('\u{1e5b}', '\u{1e5b}'), - ('\u{1e5d}', '\u{1e5d}'), ('\u{1e5f}', '\u{1e5f}'), ('\u{1e61}', '\u{1e61}'), ('\u{1e63}', - '\u{1e63}'), ('\u{1e65}', '\u{1e65}'), ('\u{1e67}', '\u{1e67}'), ('\u{1e69}', '\u{1e69}'), - ('\u{1e6b}', '\u{1e6b}'), ('\u{1e6d}', '\u{1e6d}'), ('\u{1e6f}', '\u{1e6f}'), ('\u{1e71}', - '\u{1e71}'), ('\u{1e73}', '\u{1e73}'), ('\u{1e75}', '\u{1e75}'), ('\u{1e77}', '\u{1e77}'), - ('\u{1e79}', '\u{1e79}'), ('\u{1e7b}', '\u{1e7b}'), ('\u{1e7d}', '\u{1e7d}'), ('\u{1e7f}', - '\u{1e7f}'), ('\u{1e81}', '\u{1e81}'), ('\u{1e83}', '\u{1e83}'), ('\u{1e85}', '\u{1e85}'), - ('\u{1e87}', '\u{1e87}'), ('\u{1e89}', '\u{1e89}'), ('\u{1e8b}', '\u{1e8b}'), ('\u{1e8d}', - '\u{1e8d}'), ('\u{1e8f}', '\u{1e8f}'), ('\u{1e91}', '\u{1e91}'), ('\u{1e93}', '\u{1e93}'), - ('\u{1e95}', '\u{1e9d}'), ('\u{1e9f}', '\u{1e9f}'), ('\u{1ea1}', '\u{1ea1}'), ('\u{1ea3}', - '\u{1ea3}'), ('\u{1ea5}', '\u{1ea5}'), ('\u{1ea7}', '\u{1ea7}'), ('\u{1ea9}', '\u{1ea9}'), - ('\u{1eab}', '\u{1eab}'), ('\u{1ead}', '\u{1ead}'), ('\u{1eaf}', '\u{1eaf}'), ('\u{1eb1}', - '\u{1eb1}'), ('\u{1eb3}', '\u{1eb3}'), ('\u{1eb5}', '\u{1eb5}'), ('\u{1eb7}', '\u{1eb7}'), - ('\u{1eb9}', '\u{1eb9}'), ('\u{1ebb}', '\u{1ebb}'), ('\u{1ebd}', '\u{1ebd}'), ('\u{1ebf}', - '\u{1ebf}'), ('\u{1ec1}', '\u{1ec1}'), ('\u{1ec3}', '\u{1ec3}'), ('\u{1ec5}', '\u{1ec5}'), - ('\u{1ec7}', '\u{1ec7}'), ('\u{1ec9}', '\u{1ec9}'), ('\u{1ecb}', '\u{1ecb}'), ('\u{1ecd}', - '\u{1ecd}'), ('\u{1ecf}', '\u{1ecf}'), ('\u{1ed1}', '\u{1ed1}'), ('\u{1ed3}', '\u{1ed3}'), - ('\u{1ed5}', '\u{1ed5}'), ('\u{1ed7}', '\u{1ed7}'), ('\u{1ed9}', '\u{1ed9}'), ('\u{1edb}', - '\u{1edb}'), ('\u{1edd}', '\u{1edd}'), ('\u{1edf}', '\u{1edf}'), ('\u{1ee1}', '\u{1ee1}'), - ('\u{1ee3}', '\u{1ee3}'), ('\u{1ee5}', '\u{1ee5}'), ('\u{1ee7}', '\u{1ee7}'), ('\u{1ee9}', - '\u{1ee9}'), ('\u{1eeb}', '\u{1eeb}'), ('\u{1eed}', '\u{1eed}'), ('\u{1eef}', '\u{1eef}'), - ('\u{1ef1}', '\u{1ef1}'), ('\u{1ef3}', '\u{1ef3}'), ('\u{1ef5}', '\u{1ef5}'), ('\u{1ef7}', - '\u{1ef7}'), ('\u{1ef9}', '\u{1ef9}'), ('\u{1efb}', '\u{1efb}'), ('\u{1efd}', '\u{1efd}'), - ('\u{1eff}', '\u{1f07}'), ('\u{1f10}', '\u{1f15}'), ('\u{1f20}', '\u{1f27}'), ('\u{1f30}', - '\u{1f37}'), ('\u{1f40}', '\u{1f45}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f60}', '\u{1f67}'), - ('\u{1f70}', '\u{1f7d}'), ('\u{1f80}', '\u{1f87}'), ('\u{1f90}', '\u{1f97}'), ('\u{1fa0}', - '\u{1fa7}'), ('\u{1fb0}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fb7}'), ('\u{1fbe}', '\u{1fbe}'), - ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fc7}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', - '\u{1fd7}'), ('\u{1fe0}', '\u{1fe7}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ff7}'), - ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{210a}', - '\u{210a}'), ('\u{210e}', '\u{210f}'), ('\u{2113}', '\u{2113}'), ('\u{212f}', '\u{212f}'), - ('\u{2134}', '\u{2134}'), ('\u{2139}', '\u{2139}'), ('\u{213c}', '\u{213d}'), ('\u{2146}', - '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2170}', '\u{217f}'), ('\u{2184}', '\u{2184}'), - ('\u{24d0}', '\u{24e9}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c61}', '\u{2c61}'), ('\u{2c65}', - '\u{2c66}'), ('\u{2c68}', '\u{2c68}'), ('\u{2c6a}', '\u{2c6a}'), ('\u{2c6c}', '\u{2c6c}'), - ('\u{2c71}', '\u{2c71}'), ('\u{2c73}', '\u{2c74}'), ('\u{2c76}', '\u{2c7d}'), ('\u{2c81}', - '\u{2c81}'), ('\u{2c83}', '\u{2c83}'), ('\u{2c85}', '\u{2c85}'), ('\u{2c87}', '\u{2c87}'), - ('\u{2c89}', '\u{2c89}'), ('\u{2c8b}', '\u{2c8b}'), ('\u{2c8d}', '\u{2c8d}'), ('\u{2c8f}', - '\u{2c8f}'), ('\u{2c91}', '\u{2c91}'), ('\u{2c93}', '\u{2c93}'), ('\u{2c95}', '\u{2c95}'), - ('\u{2c97}', '\u{2c97}'), ('\u{2c99}', '\u{2c99}'), ('\u{2c9b}', '\u{2c9b}'), ('\u{2c9d}', - '\u{2c9d}'), ('\u{2c9f}', '\u{2c9f}'), ('\u{2ca1}', '\u{2ca1}'), ('\u{2ca3}', '\u{2ca3}'), - ('\u{2ca5}', '\u{2ca5}'), ('\u{2ca7}', '\u{2ca7}'), ('\u{2ca9}', '\u{2ca9}'), ('\u{2cab}', - '\u{2cab}'), ('\u{2cad}', '\u{2cad}'), ('\u{2caf}', '\u{2caf}'), ('\u{2cb1}', '\u{2cb1}'), - ('\u{2cb3}', '\u{2cb3}'), ('\u{2cb5}', '\u{2cb5}'), ('\u{2cb7}', '\u{2cb7}'), ('\u{2cb9}', - '\u{2cb9}'), ('\u{2cbb}', '\u{2cbb}'), ('\u{2cbd}', '\u{2cbd}'), ('\u{2cbf}', '\u{2cbf}'), - ('\u{2cc1}', '\u{2cc1}'), ('\u{2cc3}', '\u{2cc3}'), ('\u{2cc5}', '\u{2cc5}'), ('\u{2cc7}', - '\u{2cc7}'), ('\u{2cc9}', '\u{2cc9}'), ('\u{2ccb}', '\u{2ccb}'), ('\u{2ccd}', '\u{2ccd}'), - ('\u{2ccf}', '\u{2ccf}'), ('\u{2cd1}', '\u{2cd1}'), ('\u{2cd3}', '\u{2cd3}'), ('\u{2cd5}', - '\u{2cd5}'), ('\u{2cd7}', '\u{2cd7}'), ('\u{2cd9}', '\u{2cd9}'), ('\u{2cdb}', '\u{2cdb}'), - ('\u{2cdd}', '\u{2cdd}'), ('\u{2cdf}', '\u{2cdf}'), ('\u{2ce1}', '\u{2ce1}'), ('\u{2ce3}', - '\u{2ce4}'), ('\u{2cec}', '\u{2cec}'), ('\u{2cee}', '\u{2cee}'), ('\u{2cf3}', '\u{2cf3}'), - ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{a641}', - '\u{a641}'), ('\u{a643}', '\u{a643}'), ('\u{a645}', '\u{a645}'), ('\u{a647}', '\u{a647}'), - ('\u{a649}', '\u{a649}'), ('\u{a64b}', '\u{a64b}'), ('\u{a64d}', '\u{a64d}'), ('\u{a64f}', - '\u{a64f}'), ('\u{a651}', '\u{a651}'), ('\u{a653}', '\u{a653}'), ('\u{a655}', '\u{a655}'), - ('\u{a657}', '\u{a657}'), ('\u{a659}', '\u{a659}'), ('\u{a65b}', '\u{a65b}'), ('\u{a65d}', - '\u{a65d}'), ('\u{a65f}', '\u{a65f}'), ('\u{a661}', '\u{a661}'), ('\u{a663}', '\u{a663}'), - ('\u{a665}', '\u{a665}'), ('\u{a667}', '\u{a667}'), ('\u{a669}', '\u{a669}'), ('\u{a66b}', - '\u{a66b}'), ('\u{a66d}', '\u{a66d}'), ('\u{a681}', '\u{a681}'), ('\u{a683}', '\u{a683}'), - ('\u{a685}', '\u{a685}'), ('\u{a687}', '\u{a687}'), ('\u{a689}', '\u{a689}'), ('\u{a68b}', - '\u{a68b}'), ('\u{a68d}', '\u{a68d}'), ('\u{a68f}', '\u{a68f}'), ('\u{a691}', '\u{a691}'), - ('\u{a693}', '\u{a693}'), ('\u{a695}', '\u{a695}'), ('\u{a697}', '\u{a697}'), ('\u{a699}', - '\u{a699}'), ('\u{a69b}', '\u{a69d}'), ('\u{a723}', '\u{a723}'), ('\u{a725}', '\u{a725}'), - ('\u{a727}', '\u{a727}'), ('\u{a729}', '\u{a729}'), ('\u{a72b}', '\u{a72b}'), ('\u{a72d}', - '\u{a72d}'), ('\u{a72f}', '\u{a731}'), ('\u{a733}', '\u{a733}'), ('\u{a735}', '\u{a735}'), - ('\u{a737}', '\u{a737}'), ('\u{a739}', '\u{a739}'), ('\u{a73b}', '\u{a73b}'), ('\u{a73d}', - '\u{a73d}'), ('\u{a73f}', '\u{a73f}'), ('\u{a741}', '\u{a741}'), ('\u{a743}', '\u{a743}'), - ('\u{a745}', '\u{a745}'), ('\u{a747}', '\u{a747}'), ('\u{a749}', '\u{a749}'), ('\u{a74b}', - '\u{a74b}'), ('\u{a74d}', '\u{a74d}'), ('\u{a74f}', '\u{a74f}'), ('\u{a751}', '\u{a751}'), - ('\u{a753}', '\u{a753}'), ('\u{a755}', '\u{a755}'), ('\u{a757}', '\u{a757}'), ('\u{a759}', - '\u{a759}'), ('\u{a75b}', '\u{a75b}'), ('\u{a75d}', '\u{a75d}'), ('\u{a75f}', '\u{a75f}'), - ('\u{a761}', '\u{a761}'), ('\u{a763}', '\u{a763}'), ('\u{a765}', '\u{a765}'), ('\u{a767}', - '\u{a767}'), ('\u{a769}', '\u{a769}'), ('\u{a76b}', '\u{a76b}'), ('\u{a76d}', '\u{a76d}'), - ('\u{a76f}', '\u{a778}'), ('\u{a77a}', '\u{a77a}'), ('\u{a77c}', '\u{a77c}'), ('\u{a77f}', - '\u{a77f}'), ('\u{a781}', '\u{a781}'), ('\u{a783}', '\u{a783}'), ('\u{a785}', '\u{a785}'), - ('\u{a787}', '\u{a787}'), ('\u{a78c}', '\u{a78c}'), ('\u{a78e}', '\u{a78e}'), ('\u{a791}', - '\u{a791}'), ('\u{a793}', '\u{a795}'), ('\u{a797}', '\u{a797}'), ('\u{a799}', '\u{a799}'), - ('\u{a79b}', '\u{a79b}'), ('\u{a79d}', '\u{a79d}'), ('\u{a79f}', '\u{a79f}'), ('\u{a7a1}', - '\u{a7a1}'), ('\u{a7a3}', '\u{a7a3}'), ('\u{a7a5}', '\u{a7a5}'), ('\u{a7a7}', '\u{a7a7}'), - ('\u{a7a9}', '\u{a7a9}'), ('\u{a7b5}', '\u{a7b5}'), ('\u{a7b7}', '\u{a7b7}'), ('\u{a7f8}', - '\u{a7fa}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abbf}'), - ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{ff41}', '\u{ff5a}'), ('\u{10428}', - '\u{1044f}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{118c0}', '\u{118df}'), ('\u{1d41a}', - '\u{1d433}'), ('\u{1d44e}', '\u{1d454}'), ('\u{1d456}', '\u{1d467}'), ('\u{1d482}', - '\u{1d49b}'), ('\u{1d4b6}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', - '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d4cf}'), ('\u{1d4ea}', '\u{1d503}'), ('\u{1d51e}', - '\u{1d537}'), ('\u{1d552}', '\u{1d56b}'), ('\u{1d586}', '\u{1d59f}'), ('\u{1d5ba}', - '\u{1d5d3}'), ('\u{1d5ee}', '\u{1d607}'), ('\u{1d622}', '\u{1d63b}'), ('\u{1d656}', - '\u{1d66f}'), ('\u{1d68a}', '\u{1d6a5}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', - '\u{1d6e1}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d71b}'), ('\u{1d736}', - '\u{1d74e}'), ('\u{1d750}', '\u{1d755}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', - '\u{1d78f}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7c9}'), ('\u{1d7cb}', - '\u{1d7cb}') - ]; + pub const Lowercase_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000000000000, 0x07fffffe00000000, 0x0420040000000000, 0xff7fffff80000000, + 0x55aaaaaaaaaaaaaa, 0xd4aaaaaaaaaaab55, 0xe6512d2a4e243129, 0xaa29aaaab5555240, + 0x93faaaaaaaaaaaaa, 0xffffffffffffaa85, 0x01ffffffffefffff, 0x0000001f00000003, + 0x0000000000000000, 0x3c8a000000000020, 0xfffff00000010000, 0x192faaaaaae37fff, + 0xffff000000000000, 0xaaaaaaaaffffffff, 0xaaaaaaaaaaaaa802, 0xaaaaaaaaaaaad554, + 0x0000aaaaaaaaaaaa, 0xfffffffe00000000, 0x00000000000000ff, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, + 0, 3, 3, 4, 3, 5, 6, 7, 8, 0, 9, 10, 0, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 16, 3, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, + 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 25, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 27, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0x3f00000000000000, 0xffffffffffffffff, 0xaaaaaaaaaaaaaaaa, + 0xaaaaaaaabfeaaaaa, 0x00ff00ff003f00ff, 0x3fff00ff00ff003f, 0x40df00ff00ff00ff, + 0x00dc00ff00cf00dc, 0x8002000000000000, 0x000000001fff0000, 0x321080000008c400, + 0xffff0000000043c0, 0x0000000000000010, 0x000003ffffff0000, 0xffff000000000000, + 0x3fda15627fffffff, 0x0008501aaaaaaaaa, 0x000020bfffffffff, 0x00002aaaaaaaaaaa, + 0x000000003aaaaaaa, 0xaaabaaa800000000, 0x95ffaaaaaaaaaaaa, 0x00a002aaaaba50aa, + 0x0700000000000000, 0xffff003ff7ffffff, 0x0000000000f8007f, 0x0000000007fffffe + ], + r4: [ + 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000, 0xffffff0000000000, 0x000000000000ffff, 0x0007ffffffffffff, + 0x00000000ffffffff, 0x000ffffffc000000, 0x000000ffffdfc000, 0xebc000000ffffffc, + 0xfffffc000000ffef, 0x00ffffffc000000f, 0x00000ffffffc0000, 0xfc000000ffffffc0, + 0xffffc000000fffff, 0x0ffffffc000000ff, 0x0000ffffffc00000, 0x0000003ffffffc00, + 0xf0000003f7fffffc, 0xffc000000fdfffff, 0xffff0000003f7fff, 0xfffffc000000fdff, + 0x0000000000000bf7 + ], + }; pub fn Lowercase(c: char) -> bool { - super::bsearch_range_table(c, Lowercase_table) + super::trie_lookup_range_table(c, Lowercase_table) } - pub const Uppercase_table: &'static [(char, char)] = &[ - ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'), ('\u{100}', '\u{100}'), - ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'), ('\u{106}', '\u{106}'), ('\u{108}', - '\u{108}'), ('\u{10a}', '\u{10a}'), ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), - ('\u{110}', '\u{110}'), ('\u{112}', '\u{112}'), ('\u{114}', '\u{114}'), ('\u{116}', - '\u{116}'), ('\u{118}', '\u{118}'), ('\u{11a}', '\u{11a}'), ('\u{11c}', '\u{11c}'), - ('\u{11e}', '\u{11e}'), ('\u{120}', '\u{120}'), ('\u{122}', '\u{122}'), ('\u{124}', - '\u{124}'), ('\u{126}', '\u{126}'), ('\u{128}', '\u{128}'), ('\u{12a}', '\u{12a}'), - ('\u{12c}', '\u{12c}'), ('\u{12e}', '\u{12e}'), ('\u{130}', '\u{130}'), ('\u{132}', - '\u{132}'), ('\u{134}', '\u{134}'), ('\u{136}', '\u{136}'), ('\u{139}', '\u{139}'), - ('\u{13b}', '\u{13b}'), ('\u{13d}', '\u{13d}'), ('\u{13f}', '\u{13f}'), ('\u{141}', - '\u{141}'), ('\u{143}', '\u{143}'), ('\u{145}', '\u{145}'), ('\u{147}', '\u{147}'), - ('\u{14a}', '\u{14a}'), ('\u{14c}', '\u{14c}'), ('\u{14e}', '\u{14e}'), ('\u{150}', - '\u{150}'), ('\u{152}', '\u{152}'), ('\u{154}', '\u{154}'), ('\u{156}', '\u{156}'), - ('\u{158}', '\u{158}'), ('\u{15a}', '\u{15a}'), ('\u{15c}', '\u{15c}'), ('\u{15e}', - '\u{15e}'), ('\u{160}', '\u{160}'), ('\u{162}', '\u{162}'), ('\u{164}', '\u{164}'), - ('\u{166}', '\u{166}'), ('\u{168}', '\u{168}'), ('\u{16a}', '\u{16a}'), ('\u{16c}', - '\u{16c}'), ('\u{16e}', '\u{16e}'), ('\u{170}', '\u{170}'), ('\u{172}', '\u{172}'), - ('\u{174}', '\u{174}'), ('\u{176}', '\u{176}'), ('\u{178}', '\u{179}'), ('\u{17b}', - '\u{17b}'), ('\u{17d}', '\u{17d}'), ('\u{181}', '\u{182}'), ('\u{184}', '\u{184}'), - ('\u{186}', '\u{187}'), ('\u{189}', '\u{18b}'), ('\u{18e}', '\u{191}'), ('\u{193}', - '\u{194}'), ('\u{196}', '\u{198}'), ('\u{19c}', '\u{19d}'), ('\u{19f}', '\u{1a0}'), - ('\u{1a2}', '\u{1a2}'), ('\u{1a4}', '\u{1a4}'), ('\u{1a6}', '\u{1a7}'), ('\u{1a9}', - '\u{1a9}'), ('\u{1ac}', '\u{1ac}'), ('\u{1ae}', '\u{1af}'), ('\u{1b1}', '\u{1b3}'), - ('\u{1b5}', '\u{1b5}'), ('\u{1b7}', '\u{1b8}'), ('\u{1bc}', '\u{1bc}'), ('\u{1c4}', - '\u{1c4}'), ('\u{1c7}', '\u{1c7}'), ('\u{1ca}', '\u{1ca}'), ('\u{1cd}', '\u{1cd}'), - ('\u{1cf}', '\u{1cf}'), ('\u{1d1}', '\u{1d1}'), ('\u{1d3}', '\u{1d3}'), ('\u{1d5}', - '\u{1d5}'), ('\u{1d7}', '\u{1d7}'), ('\u{1d9}', '\u{1d9}'), ('\u{1db}', '\u{1db}'), - ('\u{1de}', '\u{1de}'), ('\u{1e0}', '\u{1e0}'), ('\u{1e2}', '\u{1e2}'), ('\u{1e4}', - '\u{1e4}'), ('\u{1e6}', '\u{1e6}'), ('\u{1e8}', '\u{1e8}'), ('\u{1ea}', '\u{1ea}'), - ('\u{1ec}', '\u{1ec}'), ('\u{1ee}', '\u{1ee}'), ('\u{1f1}', '\u{1f1}'), ('\u{1f4}', - '\u{1f4}'), ('\u{1f6}', '\u{1f8}'), ('\u{1fa}', '\u{1fa}'), ('\u{1fc}', '\u{1fc}'), - ('\u{1fe}', '\u{1fe}'), ('\u{200}', '\u{200}'), ('\u{202}', '\u{202}'), ('\u{204}', - '\u{204}'), ('\u{206}', '\u{206}'), ('\u{208}', '\u{208}'), ('\u{20a}', '\u{20a}'), - ('\u{20c}', '\u{20c}'), ('\u{20e}', '\u{20e}'), ('\u{210}', '\u{210}'), ('\u{212}', - '\u{212}'), ('\u{214}', '\u{214}'), ('\u{216}', '\u{216}'), ('\u{218}', '\u{218}'), - ('\u{21a}', '\u{21a}'), ('\u{21c}', '\u{21c}'), ('\u{21e}', '\u{21e}'), ('\u{220}', - '\u{220}'), ('\u{222}', '\u{222}'), ('\u{224}', '\u{224}'), ('\u{226}', '\u{226}'), - ('\u{228}', '\u{228}'), ('\u{22a}', '\u{22a}'), ('\u{22c}', '\u{22c}'), ('\u{22e}', - '\u{22e}'), ('\u{230}', '\u{230}'), ('\u{232}', '\u{232}'), ('\u{23a}', '\u{23b}'), - ('\u{23d}', '\u{23e}'), ('\u{241}', '\u{241}'), ('\u{243}', '\u{246}'), ('\u{248}', - '\u{248}'), ('\u{24a}', '\u{24a}'), ('\u{24c}', '\u{24c}'), ('\u{24e}', '\u{24e}'), - ('\u{370}', '\u{370}'), ('\u{372}', '\u{372}'), ('\u{376}', '\u{376}'), ('\u{37f}', - '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), - ('\u{38e}', '\u{38f}'), ('\u{391}', '\u{3a1}'), ('\u{3a3}', '\u{3ab}'), ('\u{3cf}', - '\u{3cf}'), ('\u{3d2}', '\u{3d4}'), ('\u{3d8}', '\u{3d8}'), ('\u{3da}', '\u{3da}'), - ('\u{3dc}', '\u{3dc}'), ('\u{3de}', '\u{3de}'), ('\u{3e0}', '\u{3e0}'), ('\u{3e2}', - '\u{3e2}'), ('\u{3e4}', '\u{3e4}'), ('\u{3e6}', '\u{3e6}'), ('\u{3e8}', '\u{3e8}'), - ('\u{3ea}', '\u{3ea}'), ('\u{3ec}', '\u{3ec}'), ('\u{3ee}', '\u{3ee}'), ('\u{3f4}', - '\u{3f4}'), ('\u{3f7}', '\u{3f7}'), ('\u{3f9}', '\u{3fa}'), ('\u{3fd}', '\u{42f}'), - ('\u{460}', '\u{460}'), ('\u{462}', '\u{462}'), ('\u{464}', '\u{464}'), ('\u{466}', - '\u{466}'), ('\u{468}', '\u{468}'), ('\u{46a}', '\u{46a}'), ('\u{46c}', '\u{46c}'), - ('\u{46e}', '\u{46e}'), ('\u{470}', '\u{470}'), ('\u{472}', '\u{472}'), ('\u{474}', - '\u{474}'), ('\u{476}', '\u{476}'), ('\u{478}', '\u{478}'), ('\u{47a}', '\u{47a}'), - ('\u{47c}', '\u{47c}'), ('\u{47e}', '\u{47e}'), ('\u{480}', '\u{480}'), ('\u{48a}', - '\u{48a}'), ('\u{48c}', '\u{48c}'), ('\u{48e}', '\u{48e}'), ('\u{490}', '\u{490}'), - ('\u{492}', '\u{492}'), ('\u{494}', '\u{494}'), ('\u{496}', '\u{496}'), ('\u{498}', - '\u{498}'), ('\u{49a}', '\u{49a}'), ('\u{49c}', '\u{49c}'), ('\u{49e}', '\u{49e}'), - ('\u{4a0}', '\u{4a0}'), ('\u{4a2}', '\u{4a2}'), ('\u{4a4}', '\u{4a4}'), ('\u{4a6}', - '\u{4a6}'), ('\u{4a8}', '\u{4a8}'), ('\u{4aa}', '\u{4aa}'), ('\u{4ac}', '\u{4ac}'), - ('\u{4ae}', '\u{4ae}'), ('\u{4b0}', '\u{4b0}'), ('\u{4b2}', '\u{4b2}'), ('\u{4b4}', - '\u{4b4}'), ('\u{4b6}', '\u{4b6}'), ('\u{4b8}', '\u{4b8}'), ('\u{4ba}', '\u{4ba}'), - ('\u{4bc}', '\u{4bc}'), ('\u{4be}', '\u{4be}'), ('\u{4c0}', '\u{4c1}'), ('\u{4c3}', - '\u{4c3}'), ('\u{4c5}', '\u{4c5}'), ('\u{4c7}', '\u{4c7}'), ('\u{4c9}', '\u{4c9}'), - ('\u{4cb}', '\u{4cb}'), ('\u{4cd}', '\u{4cd}'), ('\u{4d0}', '\u{4d0}'), ('\u{4d2}', - '\u{4d2}'), ('\u{4d4}', '\u{4d4}'), ('\u{4d6}', '\u{4d6}'), ('\u{4d8}', '\u{4d8}'), - ('\u{4da}', '\u{4da}'), ('\u{4dc}', '\u{4dc}'), ('\u{4de}', '\u{4de}'), ('\u{4e0}', - '\u{4e0}'), ('\u{4e2}', '\u{4e2}'), ('\u{4e4}', '\u{4e4}'), ('\u{4e6}', '\u{4e6}'), - ('\u{4e8}', '\u{4e8}'), ('\u{4ea}', '\u{4ea}'), ('\u{4ec}', '\u{4ec}'), ('\u{4ee}', - '\u{4ee}'), ('\u{4f0}', '\u{4f0}'), ('\u{4f2}', '\u{4f2}'), ('\u{4f4}', '\u{4f4}'), - ('\u{4f6}', '\u{4f6}'), ('\u{4f8}', '\u{4f8}'), ('\u{4fa}', '\u{4fa}'), ('\u{4fc}', - '\u{4fc}'), ('\u{4fe}', '\u{4fe}'), ('\u{500}', '\u{500}'), ('\u{502}', '\u{502}'), - ('\u{504}', '\u{504}'), ('\u{506}', '\u{506}'), ('\u{508}', '\u{508}'), ('\u{50a}', - '\u{50a}'), ('\u{50c}', '\u{50c}'), ('\u{50e}', '\u{50e}'), ('\u{510}', '\u{510}'), - ('\u{512}', '\u{512}'), ('\u{514}', '\u{514}'), ('\u{516}', '\u{516}'), ('\u{518}', - '\u{518}'), ('\u{51a}', '\u{51a}'), ('\u{51c}', '\u{51c}'), ('\u{51e}', '\u{51e}'), - ('\u{520}', '\u{520}'), ('\u{522}', '\u{522}'), ('\u{524}', '\u{524}'), ('\u{526}', - '\u{526}'), ('\u{528}', '\u{528}'), ('\u{52a}', '\u{52a}'), ('\u{52c}', '\u{52c}'), - ('\u{52e}', '\u{52e}'), ('\u{531}', '\u{556}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', - '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{13a0}', '\u{13f5}'), ('\u{1e00}', '\u{1e00}'), - ('\u{1e02}', '\u{1e02}'), ('\u{1e04}', '\u{1e04}'), ('\u{1e06}', '\u{1e06}'), ('\u{1e08}', - '\u{1e08}'), ('\u{1e0a}', '\u{1e0a}'), ('\u{1e0c}', '\u{1e0c}'), ('\u{1e0e}', '\u{1e0e}'), - ('\u{1e10}', '\u{1e10}'), ('\u{1e12}', '\u{1e12}'), ('\u{1e14}', '\u{1e14}'), ('\u{1e16}', - '\u{1e16}'), ('\u{1e18}', '\u{1e18}'), ('\u{1e1a}', '\u{1e1a}'), ('\u{1e1c}', '\u{1e1c}'), - ('\u{1e1e}', '\u{1e1e}'), ('\u{1e20}', '\u{1e20}'), ('\u{1e22}', '\u{1e22}'), ('\u{1e24}', - '\u{1e24}'), ('\u{1e26}', '\u{1e26}'), ('\u{1e28}', '\u{1e28}'), ('\u{1e2a}', '\u{1e2a}'), - ('\u{1e2c}', '\u{1e2c}'), ('\u{1e2e}', '\u{1e2e}'), ('\u{1e30}', '\u{1e30}'), ('\u{1e32}', - '\u{1e32}'), ('\u{1e34}', '\u{1e34}'), ('\u{1e36}', '\u{1e36}'), ('\u{1e38}', '\u{1e38}'), - ('\u{1e3a}', '\u{1e3a}'), ('\u{1e3c}', '\u{1e3c}'), ('\u{1e3e}', '\u{1e3e}'), ('\u{1e40}', - '\u{1e40}'), ('\u{1e42}', '\u{1e42}'), ('\u{1e44}', '\u{1e44}'), ('\u{1e46}', '\u{1e46}'), - ('\u{1e48}', '\u{1e48}'), ('\u{1e4a}', '\u{1e4a}'), ('\u{1e4c}', '\u{1e4c}'), ('\u{1e4e}', - '\u{1e4e}'), ('\u{1e50}', '\u{1e50}'), ('\u{1e52}', '\u{1e52}'), ('\u{1e54}', '\u{1e54}'), - ('\u{1e56}', '\u{1e56}'), ('\u{1e58}', '\u{1e58}'), ('\u{1e5a}', '\u{1e5a}'), ('\u{1e5c}', - '\u{1e5c}'), ('\u{1e5e}', '\u{1e5e}'), ('\u{1e60}', '\u{1e60}'), ('\u{1e62}', '\u{1e62}'), - ('\u{1e64}', '\u{1e64}'), ('\u{1e66}', '\u{1e66}'), ('\u{1e68}', '\u{1e68}'), ('\u{1e6a}', - '\u{1e6a}'), ('\u{1e6c}', '\u{1e6c}'), ('\u{1e6e}', '\u{1e6e}'), ('\u{1e70}', '\u{1e70}'), - ('\u{1e72}', '\u{1e72}'), ('\u{1e74}', '\u{1e74}'), ('\u{1e76}', '\u{1e76}'), ('\u{1e78}', - '\u{1e78}'), ('\u{1e7a}', '\u{1e7a}'), ('\u{1e7c}', '\u{1e7c}'), ('\u{1e7e}', '\u{1e7e}'), - ('\u{1e80}', '\u{1e80}'), ('\u{1e82}', '\u{1e82}'), ('\u{1e84}', '\u{1e84}'), ('\u{1e86}', - '\u{1e86}'), ('\u{1e88}', '\u{1e88}'), ('\u{1e8a}', '\u{1e8a}'), ('\u{1e8c}', '\u{1e8c}'), - ('\u{1e8e}', '\u{1e8e}'), ('\u{1e90}', '\u{1e90}'), ('\u{1e92}', '\u{1e92}'), ('\u{1e94}', - '\u{1e94}'), ('\u{1e9e}', '\u{1e9e}'), ('\u{1ea0}', '\u{1ea0}'), ('\u{1ea2}', '\u{1ea2}'), - ('\u{1ea4}', '\u{1ea4}'), ('\u{1ea6}', '\u{1ea6}'), ('\u{1ea8}', '\u{1ea8}'), ('\u{1eaa}', - '\u{1eaa}'), ('\u{1eac}', '\u{1eac}'), ('\u{1eae}', '\u{1eae}'), ('\u{1eb0}', '\u{1eb0}'), - ('\u{1eb2}', '\u{1eb2}'), ('\u{1eb4}', '\u{1eb4}'), ('\u{1eb6}', '\u{1eb6}'), ('\u{1eb8}', - '\u{1eb8}'), ('\u{1eba}', '\u{1eba}'), ('\u{1ebc}', '\u{1ebc}'), ('\u{1ebe}', '\u{1ebe}'), - ('\u{1ec0}', '\u{1ec0}'), ('\u{1ec2}', '\u{1ec2}'), ('\u{1ec4}', '\u{1ec4}'), ('\u{1ec6}', - '\u{1ec6}'), ('\u{1ec8}', '\u{1ec8}'), ('\u{1eca}', '\u{1eca}'), ('\u{1ecc}', '\u{1ecc}'), - ('\u{1ece}', '\u{1ece}'), ('\u{1ed0}', '\u{1ed0}'), ('\u{1ed2}', '\u{1ed2}'), ('\u{1ed4}', - '\u{1ed4}'), ('\u{1ed6}', '\u{1ed6}'), ('\u{1ed8}', '\u{1ed8}'), ('\u{1eda}', '\u{1eda}'), - ('\u{1edc}', '\u{1edc}'), ('\u{1ede}', '\u{1ede}'), ('\u{1ee0}', '\u{1ee0}'), ('\u{1ee2}', - '\u{1ee2}'), ('\u{1ee4}', '\u{1ee4}'), ('\u{1ee6}', '\u{1ee6}'), ('\u{1ee8}', '\u{1ee8}'), - ('\u{1eea}', '\u{1eea}'), ('\u{1eec}', '\u{1eec}'), ('\u{1eee}', '\u{1eee}'), ('\u{1ef0}', - '\u{1ef0}'), ('\u{1ef2}', '\u{1ef2}'), ('\u{1ef4}', '\u{1ef4}'), ('\u{1ef6}', '\u{1ef6}'), - ('\u{1ef8}', '\u{1ef8}'), ('\u{1efa}', '\u{1efa}'), ('\u{1efc}', '\u{1efc}'), ('\u{1efe}', - '\u{1efe}'), ('\u{1f08}', '\u{1f0f}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f28}', '\u{1f2f}'), - ('\u{1f38}', '\u{1f3f}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', - '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f5f}'), ('\u{1f68}', '\u{1f6f}'), - ('\u{1fb8}', '\u{1fbb}'), ('\u{1fc8}', '\u{1fcb}'), ('\u{1fd8}', '\u{1fdb}'), ('\u{1fe8}', - '\u{1fec}'), ('\u{1ff8}', '\u{1ffb}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), - ('\u{210b}', '\u{210d}'), ('\u{2110}', '\u{2112}'), ('\u{2115}', '\u{2115}'), ('\u{2119}', - '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}', '\u{2128}'), - ('\u{212a}', '\u{212d}'), ('\u{2130}', '\u{2133}'), ('\u{213e}', '\u{213f}'), ('\u{2145}', - '\u{2145}'), ('\u{2160}', '\u{216f}'), ('\u{2183}', '\u{2183}'), ('\u{24b6}', '\u{24cf}'), - ('\u{2c00}', '\u{2c2e}'), ('\u{2c60}', '\u{2c60}'), ('\u{2c62}', '\u{2c64}'), ('\u{2c67}', - '\u{2c67}'), ('\u{2c69}', '\u{2c69}'), ('\u{2c6b}', '\u{2c6b}'), ('\u{2c6d}', '\u{2c70}'), - ('\u{2c72}', '\u{2c72}'), ('\u{2c75}', '\u{2c75}'), ('\u{2c7e}', '\u{2c80}'), ('\u{2c82}', - '\u{2c82}'), ('\u{2c84}', '\u{2c84}'), ('\u{2c86}', '\u{2c86}'), ('\u{2c88}', '\u{2c88}'), - ('\u{2c8a}', '\u{2c8a}'), ('\u{2c8c}', '\u{2c8c}'), ('\u{2c8e}', '\u{2c8e}'), ('\u{2c90}', - '\u{2c90}'), ('\u{2c92}', '\u{2c92}'), ('\u{2c94}', '\u{2c94}'), ('\u{2c96}', '\u{2c96}'), - ('\u{2c98}', '\u{2c98}'), ('\u{2c9a}', '\u{2c9a}'), ('\u{2c9c}', '\u{2c9c}'), ('\u{2c9e}', - '\u{2c9e}'), ('\u{2ca0}', '\u{2ca0}'), ('\u{2ca2}', '\u{2ca2}'), ('\u{2ca4}', '\u{2ca4}'), - ('\u{2ca6}', '\u{2ca6}'), ('\u{2ca8}', '\u{2ca8}'), ('\u{2caa}', '\u{2caa}'), ('\u{2cac}', - '\u{2cac}'), ('\u{2cae}', '\u{2cae}'), ('\u{2cb0}', '\u{2cb0}'), ('\u{2cb2}', '\u{2cb2}'), - ('\u{2cb4}', '\u{2cb4}'), ('\u{2cb6}', '\u{2cb6}'), ('\u{2cb8}', '\u{2cb8}'), ('\u{2cba}', - '\u{2cba}'), ('\u{2cbc}', '\u{2cbc}'), ('\u{2cbe}', '\u{2cbe}'), ('\u{2cc0}', '\u{2cc0}'), - ('\u{2cc2}', '\u{2cc2}'), ('\u{2cc4}', '\u{2cc4}'), ('\u{2cc6}', '\u{2cc6}'), ('\u{2cc8}', - '\u{2cc8}'), ('\u{2cca}', '\u{2cca}'), ('\u{2ccc}', '\u{2ccc}'), ('\u{2cce}', '\u{2cce}'), - ('\u{2cd0}', '\u{2cd0}'), ('\u{2cd2}', '\u{2cd2}'), ('\u{2cd4}', '\u{2cd4}'), ('\u{2cd6}', - '\u{2cd6}'), ('\u{2cd8}', '\u{2cd8}'), ('\u{2cda}', '\u{2cda}'), ('\u{2cdc}', '\u{2cdc}'), - ('\u{2cde}', '\u{2cde}'), ('\u{2ce0}', '\u{2ce0}'), ('\u{2ce2}', '\u{2ce2}'), ('\u{2ceb}', - '\u{2ceb}'), ('\u{2ced}', '\u{2ced}'), ('\u{2cf2}', '\u{2cf2}'), ('\u{a640}', '\u{a640}'), - ('\u{a642}', '\u{a642}'), ('\u{a644}', '\u{a644}'), ('\u{a646}', '\u{a646}'), ('\u{a648}', - '\u{a648}'), ('\u{a64a}', '\u{a64a}'), ('\u{a64c}', '\u{a64c}'), ('\u{a64e}', '\u{a64e}'), - ('\u{a650}', '\u{a650}'), ('\u{a652}', '\u{a652}'), ('\u{a654}', '\u{a654}'), ('\u{a656}', - '\u{a656}'), ('\u{a658}', '\u{a658}'), ('\u{a65a}', '\u{a65a}'), ('\u{a65c}', '\u{a65c}'), - ('\u{a65e}', '\u{a65e}'), ('\u{a660}', '\u{a660}'), ('\u{a662}', '\u{a662}'), ('\u{a664}', - '\u{a664}'), ('\u{a666}', '\u{a666}'), ('\u{a668}', '\u{a668}'), ('\u{a66a}', '\u{a66a}'), - ('\u{a66c}', '\u{a66c}'), ('\u{a680}', '\u{a680}'), ('\u{a682}', '\u{a682}'), ('\u{a684}', - '\u{a684}'), ('\u{a686}', '\u{a686}'), ('\u{a688}', '\u{a688}'), ('\u{a68a}', '\u{a68a}'), - ('\u{a68c}', '\u{a68c}'), ('\u{a68e}', '\u{a68e}'), ('\u{a690}', '\u{a690}'), ('\u{a692}', - '\u{a692}'), ('\u{a694}', '\u{a694}'), ('\u{a696}', '\u{a696}'), ('\u{a698}', '\u{a698}'), - ('\u{a69a}', '\u{a69a}'), ('\u{a722}', '\u{a722}'), ('\u{a724}', '\u{a724}'), ('\u{a726}', - '\u{a726}'), ('\u{a728}', '\u{a728}'), ('\u{a72a}', '\u{a72a}'), ('\u{a72c}', '\u{a72c}'), - ('\u{a72e}', '\u{a72e}'), ('\u{a732}', '\u{a732}'), ('\u{a734}', '\u{a734}'), ('\u{a736}', - '\u{a736}'), ('\u{a738}', '\u{a738}'), ('\u{a73a}', '\u{a73a}'), ('\u{a73c}', '\u{a73c}'), - ('\u{a73e}', '\u{a73e}'), ('\u{a740}', '\u{a740}'), ('\u{a742}', '\u{a742}'), ('\u{a744}', - '\u{a744}'), ('\u{a746}', '\u{a746}'), ('\u{a748}', '\u{a748}'), ('\u{a74a}', '\u{a74a}'), - ('\u{a74c}', '\u{a74c}'), ('\u{a74e}', '\u{a74e}'), ('\u{a750}', '\u{a750}'), ('\u{a752}', - '\u{a752}'), ('\u{a754}', '\u{a754}'), ('\u{a756}', '\u{a756}'), ('\u{a758}', '\u{a758}'), - ('\u{a75a}', '\u{a75a}'), ('\u{a75c}', '\u{a75c}'), ('\u{a75e}', '\u{a75e}'), ('\u{a760}', - '\u{a760}'), ('\u{a762}', '\u{a762}'), ('\u{a764}', '\u{a764}'), ('\u{a766}', '\u{a766}'), - ('\u{a768}', '\u{a768}'), ('\u{a76a}', '\u{a76a}'), ('\u{a76c}', '\u{a76c}'), ('\u{a76e}', - '\u{a76e}'), ('\u{a779}', '\u{a779}'), ('\u{a77b}', '\u{a77b}'), ('\u{a77d}', '\u{a77e}'), - ('\u{a780}', '\u{a780}'), ('\u{a782}', '\u{a782}'), ('\u{a784}', '\u{a784}'), ('\u{a786}', - '\u{a786}'), ('\u{a78b}', '\u{a78b}'), ('\u{a78d}', '\u{a78d}'), ('\u{a790}', '\u{a790}'), - ('\u{a792}', '\u{a792}'), ('\u{a796}', '\u{a796}'), ('\u{a798}', '\u{a798}'), ('\u{a79a}', - '\u{a79a}'), ('\u{a79c}', '\u{a79c}'), ('\u{a79e}', '\u{a79e}'), ('\u{a7a0}', '\u{a7a0}'), - ('\u{a7a2}', '\u{a7a2}'), ('\u{a7a4}', '\u{a7a4}'), ('\u{a7a6}', '\u{a7a6}'), ('\u{a7a8}', - '\u{a7a8}'), ('\u{a7aa}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b4}'), ('\u{a7b6}', '\u{a7b6}'), - ('\u{ff21}', '\u{ff3a}'), ('\u{10400}', '\u{10427}'), ('\u{10c80}', '\u{10cb2}'), - ('\u{118a0}', '\u{118bf}'), ('\u{1d400}', '\u{1d419}'), ('\u{1d434}', '\u{1d44d}'), - ('\u{1d468}', '\u{1d481}'), ('\u{1d49c}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), - ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), - ('\u{1d4ae}', '\u{1d4b5}'), ('\u{1d4d0}', '\u{1d4e9}'), ('\u{1d504}', '\u{1d505}'), - ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), - ('\u{1d538}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), - ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d56c}', '\u{1d585}'), - ('\u{1d5a0}', '\u{1d5b9}'), ('\u{1d5d4}', '\u{1d5ed}'), ('\u{1d608}', '\u{1d621}'), - ('\u{1d63c}', '\u{1d655}'), ('\u{1d670}', '\u{1d689}'), ('\u{1d6a8}', '\u{1d6c0}'), - ('\u{1d6e2}', '\u{1d6fa}'), ('\u{1d71c}', '\u{1d734}'), ('\u{1d756}', '\u{1d76e}'), - ('\u{1d790}', '\u{1d7a8}'), ('\u{1d7ca}', '\u{1d7ca}'), ('\u{1f130}', '\u{1f149}'), - ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}') - ]; + pub const Uppercase_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000000000000, 0x0000000007fffffe, 0x0000000000000000, 0x000000007f7fffff, + 0xaa55555555555555, 0x2b555555555554aa, 0x11aed2d5b1dbced6, 0x55d255554aaaa490, + 0x6c05555555555555, 0x000000000000557a, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x8045000000000000, 0x00000ffbfffed740, 0xe6905555551c8000, + 0x0000ffffffffffff, 0x5555555500000000, 0x5555555555555401, 0x5555555555552aab, + 0xfffe555555555555, 0x00000000007fffff, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 4, 5, 4, 6, 7, 8, 9, 0, 0, 0, 0, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 16, 4, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, + 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 0, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0xffffffff00000000, 0x00000000000020bf, 0x003fffffffffffff, + 0x5555555555555555, 0x5555555540155555, 0xff00ff003f00ff00, 0x0000ff00aa003f00, + 0x0f00000000000000, 0x0f001f000f000f00, 0xc00f3d503e273884, 0x0000ffff00000020, + 0x0000000000000008, 0xffc0000000000000, 0x000000000000ffff, 0x00007fffffffffff, + 0xc025ea9d00000000, 0x0004280555555555, 0x0000155555555555, 0x0000000005555555, + 0x5554555400000000, 0x6a00555555555555, 0x005f3d5555452855, 0x07fffffe00000000 + ], + r4: [ + 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000, 0x000000ffffffffff, 0x0007ffffffffffff, 0xffffffff00000000, + 0xfff0000003ffffff, 0xffffff0000003fff, 0x003fde64d0000003, 0x000003ffffff0000, + 0x7b0000001fdfe7b0, 0xfffff0000001fc5f, 0x03ffffff0000003f, 0x00003ffffff00000, + 0xf0000003ffffff00, 0xffff0000003fffff, 0xffffff00000003ff, 0x07fffffc00000001, + 0x001ffffff0000000, 0x00007fffffc00000, 0x000001ffffff0000, 0x0000000000000400, + 0xffff000000000000, 0xffff03ffffff03ff, 0x00000000000003ff + ], + }; pub fn Uppercase(c: char) -> bool { - super::bsearch_range_table(c, Uppercase_table) + super::trie_lookup_range_table(c, Uppercase_table) } - pub const XID_Continue_table: &'static [(char, char)] = &[ - ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'), ('\u{61}', '\u{7a}'), - ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{b7}', '\u{b7}'), ('\u{ba}', '\u{ba}'), - ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), - ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{300}', - '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'), ('\u{37f}', '\u{37f}'), - ('\u{386}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', - '\u{3f5}'), ('\u{3f7}', '\u{481}'), ('\u{483}', '\u{487}'), ('\u{48a}', '\u{52f}'), - ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}', '\u{587}'), ('\u{591}', - '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), - ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{610}', - '\u{61a}'), ('\u{620}', '\u{669}'), ('\u{66e}', '\u{6d3}'), ('\u{6d5}', '\u{6dc}'), - ('\u{6df}', '\u{6e8}'), ('\u{6ea}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'), ('\u{710}', - '\u{74a}'), ('\u{74d}', '\u{7b1}'), ('\u{7c0}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), - ('\u{800}', '\u{82d}'), ('\u{840}', '\u{85b}'), ('\u{8a0}', '\u{8b4}'), ('\u{8e3}', - '\u{963}'), ('\u{966}', '\u{96f}'), ('\u{971}', '\u{983}'), ('\u{985}', '\u{98c}'), - ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', - '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'), - ('\u{9cb}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9dc}', '\u{9dd}'), ('\u{9df}', - '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{a01}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), - ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', - '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'), - ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a51}', - '\u{a51}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a66}', '\u{a75}'), - ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', - '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), - ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}', - '\u{ad0}'), ('\u{ae0}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'), ('\u{af9}', '\u{af9}'), - ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', - '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), - ('\u{b3c}', '\u{b44}'), ('\u{b47}', '\u{b48}'), ('\u{b4b}', '\u{b4d}'), ('\u{b56}', - '\u{b57}'), ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b63}'), ('\u{b66}', '\u{b6f}'), - ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', - '\u{b90}'), ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), - ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', - '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'), - ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{bef}'), ('\u{c00}', - '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), - ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', - '\u{c4d}'), ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c63}'), - ('\u{c66}', '\u{c6f}'), ('\u{c81}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', - '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), - ('\u{cbc}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'), ('\u{cd5}', - '\u{cd6}'), ('\u{cde}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{ce6}', '\u{cef}'), - ('\u{cf1}', '\u{cf2}'), ('\u{d01}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', - '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'), - ('\u{d4a}', '\u{d4e}'), ('\u{d57}', '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d66}', - '\u{d6f}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'), - ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', - '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), - ('\u{dd8}', '\u{ddf}'), ('\u{de6}', '\u{def}'), ('\u{df2}', '\u{df3}'), ('\u{e01}', - '\u{e3a}'), ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'), - ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', - '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), - ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), ('\u{ead}', - '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), - ('\u{ec8}', '\u{ecd}'), ('\u{ed0}', '\u{ed9}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', - '\u{f00}'), ('\u{f18}', '\u{f19}'), ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'), - ('\u{f37}', '\u{f37}'), ('\u{f39}', '\u{f39}'), ('\u{f3e}', '\u{f47}'), ('\u{f49}', - '\u{f6c}'), ('\u{f71}', '\u{f84}'), ('\u{f86}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), - ('\u{fc6}', '\u{fc6}'), ('\u{1000}', '\u{1049}'), ('\u{1050}', '\u{109d}'), ('\u{10a0}', - '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), - ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', - '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), - ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', - '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), - ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{135d}', '\u{135f}'), ('\u{1369}', - '\u{1371}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), - ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}', - '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1714}'), - ('\u{1720}', '\u{1734}'), ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', - '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17d3}'), ('\u{17d7}', '\u{17d7}'), - ('\u{17dc}', '\u{17dd}'), ('\u{17e0}', '\u{17e9}'), ('\u{180b}', '\u{180d}'), ('\u{1810}', - '\u{1819}'), ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), - ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'), ('\u{1930}', '\u{193b}'), ('\u{1946}', - '\u{196d}'), ('\u{1970}', '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), - ('\u{19d0}', '\u{19da}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'), ('\u{1a60}', - '\u{1a7c}'), ('\u{1a7f}', '\u{1a89}'), ('\u{1a90}', '\u{1a99}'), ('\u{1aa7}', '\u{1aa7}'), - ('\u{1ab0}', '\u{1abd}'), ('\u{1b00}', '\u{1b4b}'), ('\u{1b50}', '\u{1b59}'), ('\u{1b6b}', - '\u{1b73}'), ('\u{1b80}', '\u{1bf3}'), ('\u{1c00}', '\u{1c37}'), ('\u{1c40}', '\u{1c49}'), - ('\u{1c4d}', '\u{1c7d}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1cf6}'), ('\u{1cf8}', - '\u{1cf9}'), ('\u{1d00}', '\u{1df5}'), ('\u{1dfc}', '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), - ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', - '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), - ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', - '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), - ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'), ('\u{203f}', - '\u{2040}'), ('\u{2054}', '\u{2054}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), - ('\u{2090}', '\u{209c}'), ('\u{20d0}', '\u{20dc}'), ('\u{20e1}', '\u{20e1}'), ('\u{20e5}', - '\u{20f0}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), - ('\u{2115}', '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', - '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}', '\u{213f}'), - ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}', - '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cf3}'), - ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}', - '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d7f}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), - ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', - '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), - ('\u{2de0}', '\u{2dff}'), ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{302f}'), ('\u{3031}', - '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{3099}', '\u{309a}'), - ('\u{309d}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', - '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), - ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', - '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a62b}'), ('\u{a640}', '\u{a66f}'), - ('\u{a674}', '\u{a67d}'), ('\u{a67f}', '\u{a6f1}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}', - '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a827}'), - ('\u{a840}', '\u{a873}'), ('\u{a880}', '\u{a8c4}'), ('\u{a8d0}', '\u{a8d9}'), ('\u{a8e0}', - '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8fd}'), ('\u{a900}', '\u{a92d}'), - ('\u{a930}', '\u{a953}'), ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9c0}'), ('\u{a9cf}', - '\u{a9d9}'), ('\u{a9e0}', '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), - ('\u{aa50}', '\u{aa59}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aac2}'), ('\u{aadb}', - '\u{aadd}'), ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf6}'), ('\u{ab01}', '\u{ab06}'), - ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', - '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abea}'), - ('\u{abec}', '\u{abed}'), ('\u{abf0}', '\u{abf9}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', - '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), - ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}', - '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), - ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}', - '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdf9}'), - ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', '\u{fe2f}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', - '\u{fe4f}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}', '\u{fe73}'), ('\u{fe77}', '\u{fe77}'), - ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'), ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}', - '\u{fefc}'), ('\u{ff10}', '\u{ff19}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff3f}', '\u{ff3f}'), - ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', - '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), - ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), - ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), - ('\u{10140}', '\u{10174}'), ('\u{101fd}', '\u{101fd}'), ('\u{10280}', '\u{1029c}'), - ('\u{102a0}', '\u{102d0}'), ('\u{102e0}', '\u{102e0}'), ('\u{10300}', '\u{1031f}'), - ('\u{10330}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'), ('\u{10380}', '\u{1039d}'), - ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), - ('\u{10400}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}'), ('\u{10500}', '\u{10527}'), - ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), - ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), - ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), - ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), - ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', '\u{10915}'), - ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'), - ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}', '\u{10a13}'), - ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a38}', '\u{10a3a}'), - ('\u{10a3f}', '\u{10a3f}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), - ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae6}'), ('\u{10b00}', '\u{10b35}'), - ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), - ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), - ('\u{11000}', '\u{11046}'), ('\u{11066}', '\u{1106f}'), ('\u{1107f}', '\u{110ba}'), - ('\u{110d0}', '\u{110e8}'), ('\u{110f0}', '\u{110f9}'), ('\u{11100}', '\u{11134}'), - ('\u{11136}', '\u{1113f}'), ('\u{11150}', '\u{11173}'), ('\u{11176}', '\u{11176}'), - ('\u{11180}', '\u{111c4}'), ('\u{111ca}', '\u{111cc}'), ('\u{111d0}', '\u{111da}'), - ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{11237}'), - ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'), - ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112ea}'), - ('\u{112f0}', '\u{112f9}'), ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), - ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), - ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}', '\u{11344}'), - ('\u{11347}', '\u{11348}'), ('\u{1134b}', '\u{1134d}'), ('\u{11350}', '\u{11350}'), - ('\u{11357}', '\u{11357}'), ('\u{1135d}', '\u{11363}'), ('\u{11366}', '\u{1136c}'), - ('\u{11370}', '\u{11374}'), ('\u{11480}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), - ('\u{114d0}', '\u{114d9}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}', '\u{115c0}'), - ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{11640}'), ('\u{11644}', '\u{11644}'), - ('\u{11650}', '\u{11659}'), ('\u{11680}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}'), - ('\u{11700}', '\u{11719}'), ('\u{1171d}', '\u{1172b}'), ('\u{11730}', '\u{11739}'), - ('\u{118a0}', '\u{118e9}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), - ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'), - ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'), - ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16ad0}', '\u{16aed}'), - ('\u{16af0}', '\u{16af4}'), ('\u{16b00}', '\u{16b36}'), ('\u{16b40}', '\u{16b43}'), - ('\u{16b50}', '\u{16b59}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), - ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f7e}'), ('\u{16f8f}', '\u{16f9f}'), - ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), - ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9d}', '\u{1bc9e}'), - ('\u{1d165}', '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), - ('\u{1d185}', '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'), - ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), - ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), - ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), - ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), - ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), - ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), - ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), - ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), - ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), - ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), - ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1da00}', '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), - ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'), - ('\u{1daa1}', '\u{1daaf}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8d0}', '\u{1e8d6}'), - ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), - ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), - ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), - ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), - ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), - ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), - ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), - ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), - ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), - ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), - ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), - ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), - ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}'), ('\u{e0100}', '\u{e01ef}') - ]; + pub const XID_Continue_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, + 0xffffffffffffffff, 0xb8dfffffffffffff, 0xfffffffbffffd7c0, 0xffbfffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffcfb, 0xffffffffffffffff, + 0xfffeffffffffffff, 0xfffffffe027fffff, 0xbffffffffffe00ff, 0x000707ffffff00b6, + 0xffffffff07ff0000, 0xffffc3ffffffffff, 0xffffffffffffffff, 0x9ffffdff9fefffff, + 0xffffffffffff0000, 0xffffffffffffe7ff, 0x0003ffffffffffff, 0x043fffffffffffff + ], + r2: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 4, 32, 33, 34, 4, 4, 4, 4, 4, 35, 36, 37, 38, 39, 40, + 41, 42, 4, 4, 4, 4, 4, 4, 4, 4, 43, 44, 45, 46, 47, 4, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 4, 61, 4, 62, 50, 63, 60, 64, 4, 4, 4, 65, 4, 4, 4, 4, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 77, 78, 4, 79, 80, 81, 82, 83, 60, 60, 60, 60, 60, 60, 60, 60, 84, + 42, 85, 86, 87, 4, 88, 89, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 52, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 91, 92, 4, 4, 4, 4, 93, 94, 4, 95, 96, 4, 97, 98, 99, 62, 4, 100, 101, + 102, 4, 103, 104, 105, 4, 106, 107, 108, 4, 109, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 110, 111, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 4, 4, 4, 4, 4, 101, 4, 112, + 113, 114, 95, 115, 4, 116, 4, 4, 117, 118, 119, 120, 121, 122, 4, 123, 124, 125, 126, + 127 + ], + r3: &[ + 0x00003fffffffffff, 0x000000000fffffff, 0x001fffff00000000, 0xfffffff800000000, + 0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x0003ffcfb080799f, + 0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0x0200ffcf00013bbf, + 0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7, + 0xe3fffdfffffddfef, 0x0000ffcf07603ddf, 0xf3effdfffffddfee, 0x0006ffcf40603ddf, + 0xe7fffffffffddfee, 0xfc00ffcf80807ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f, + 0x07fffffffffffffe, 0x0000000003ff7fff, 0x3bffecaefef02596, 0x00000000f3ff3f5f, + 0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040, + 0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff, + 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0003fe00e7ffffff, + 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, + 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x001fffff001fdfff, 0x000ddfff000fffff, + 0x000003ff308fffff, 0xffffffff03ff3800, 0x00ffffffffffffff, 0xffff07ffffffffff, + 0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff, + 0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff, + 0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x3fffffffffffe3ff, + 0x037ffffffff70000, 0xf03fffffffffffff, 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, + 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8000000000000000, 0x8002000000100001, + 0x000000001fff0000, 0x0001ffe21fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, + 0x00000000000001ff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000ff81fffffffff, + 0xffff20bfffffffff, 0x800080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f, + 0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x3fffffffffff0000, 0x00000fffffff1fff, 0xbff0ffffffffffff, 0x0003ffffffffffff, + 0xfffffffcff800000, 0x00ff3ffffffff9ff, 0xff80000000000000, 0x000000ffffffffff, + 0x28ffffff03ff001f, 0xffff3fffffffffff, 0x1fffffff000fffff, 0x7fffffff03ff8001, + 0x007fffffffffffff, 0xfc7fffff03ff3fff, 0x007cffff38000007, 0xffff7f7f007e7e7e, + 0xffff003ff7ffffff, 0x03ff37ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, + 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, 0xfffffffffff80000, + 0xfffffff03fffffff, 0x3fffffffffffffff, 0xffffffffffff0000, 0xfffffffffffcffff, + 0x03ff0000000000ff, 0x0018ffff0000ffff, 0xaa8a00000000e000, 0x1fffffffffffffff, + 0x87fffffe03ff0000, 0xffffffc007fffffe, 0x7fffffffffffffff, 0x000000001cfcfcfc + ], + r4: [ + 0, 1, 2, 3, 4, 5, 6, 5, 5, 5, 5, 7, 5, 8, 9, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 12, 13, 5, 5, 14, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + ], + r5: &[ + 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 4, 14, 15, 4, 4, 2, 2, 2, + 2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32, + 32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 33, 3, 34, 35, 36, 2, 37, 38, 4, 39, 40, 41, + 42, 4, 4, 4, 4, 2, 43, 4, 4, 44, 45, 2, 46, 47, 48, 49, 4, 4, 4, 4, 4, 50, 51, 4, 4, 4, + 4, 4, 4, 4, 52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 4, 2, 54, 2, 2, 2, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 56, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 52, 57, 4, 58, 16, 59, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 61, 62, 4, + 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 64, 65, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 66, 67, 4, 4, 68, 4, 4, 4, 4, 4, 4, 2, 69, 70, 71, 72, + 73, 2, 2, 2, 2, 74, 75, 76, 77, 78, 79, 4, 4, 4, 4, 4, 4, 4, 4, 80, 81, 82, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 83, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 85, 86, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, + 2, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4 + ], + r6: &[ + 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, + 0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff, + 0x000000010001ffff, 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, + 0x00000000003eff0f, 0x000003ff3fffffff, 0xffff00ffffffffff, 0x0000000fffffffff, + 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, + 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, + 0x870ffffffeeff06f, 0x1fffffff00000000, 0x000000001fffffff, 0x0000007ffffffeff, + 0x003fffffffffffff, 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff, + 0x0007ffffffffffff, 0x8000ffc00000007f, 0x03ff01ffffff0000, 0xffdfffffffffffff, + 0x004fffffffff0000, 0x0000000017ff1c1f, 0x00fffffffffbffff, 0xffff01ffbfffbd7f, + 0x03ff07ffffffffff, 0xf3edfdfffff99fef, 0x001f1fcfe081399f, 0x0000000003ff00bf, + 0xff3fffffffffffff, 0x000000003f000001, 0x0000000003ff0011, 0x00ffffffffffffff, + 0x00000000000003ff, 0x03ff0fffe3ffffff, 0xffffffff00000000, 0x800003ffffffffff, + 0x01ffffffffffffff, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, + 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000, 0xe0fffff803ff000f, + 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000ffff8000, 0x0000000000000003, + 0x1fff07ffffffffff, 0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, + 0x000000000000001c, 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, + 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, + 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, + 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010, 0x00000000007f001f, + 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, + 0x00000003ffffffff, 0x000000003fffffff, 0x0000ffffffffffff + ], + }; pub fn XID_Continue(c: char) -> bool { - super::bsearch_range_table(c, XID_Continue_table) + super::trie_lookup_range_table(c, XID_Continue_table) } - pub const XID_Start_table: &'static [(char, char)] = &[ - ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), - ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), - ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', - '\u{2ee}'), ('\u{370}', '\u{374}'), ('\u{376}', '\u{377}'), ('\u{37b}', '\u{37d}'), - ('\u{37f}', '\u{37f}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', - '\u{38c}'), ('\u{38e}', '\u{3a1}'), ('\u{3a3}', '\u{3f5}'), ('\u{3f7}', '\u{481}'), - ('\u{48a}', '\u{52f}'), ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{561}', - '\u{587}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{64a}'), - ('\u{66e}', '\u{66f}'), ('\u{671}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'), ('\u{6e5}', - '\u{6e6}'), ('\u{6ee}', '\u{6ef}'), ('\u{6fa}', '\u{6fc}'), ('\u{6ff}', '\u{6ff}'), - ('\u{710}', '\u{710}'), ('\u{712}', '\u{72f}'), ('\u{74d}', '\u{7a5}'), ('\u{7b1}', - '\u{7b1}'), ('\u{7ca}', '\u{7ea}'), ('\u{7f4}', '\u{7f5}'), ('\u{7fa}', '\u{7fa}'), - ('\u{800}', '\u{815}'), ('\u{81a}', '\u{81a}'), ('\u{824}', '\u{824}'), ('\u{828}', - '\u{828}'), ('\u{840}', '\u{858}'), ('\u{8a0}', '\u{8b4}'), ('\u{904}', '\u{939}'), - ('\u{93d}', '\u{93d}'), ('\u{950}', '\u{950}'), ('\u{958}', '\u{961}'), ('\u{971}', - '\u{980}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), - ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bd}', - '\u{9bd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9dc}', '\u{9dd}'), ('\u{9df}', '\u{9e1}'), - ('\u{9f0}', '\u{9f1}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', - '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), - ('\u{a38}', '\u{a39}'), ('\u{a59}', '\u{a5c}'), ('\u{a5e}', '\u{a5e}'), ('\u{a72}', - '\u{a74}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'), - ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abd}', - '\u{abd}'), ('\u{ad0}', '\u{ad0}'), ('\u{ae0}', '\u{ae1}'), ('\u{af9}', '\u{af9}'), - ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', - '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3d}', '\u{b3d}'), - ('\u{b5c}', '\u{b5d}'), ('\u{b5f}', '\u{b61}'), ('\u{b71}', '\u{b71}'), ('\u{b83}', - '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'), - ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', - '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'), ('\u{bd0}', '\u{bd0}'), - ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', - '\u{c39}'), ('\u{c3d}', '\u{c3d}'), ('\u{c58}', '\u{c5a}'), ('\u{c60}', '\u{c61}'), - ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', - '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}', '\u{cbd}'), ('\u{cde}', '\u{cde}'), - ('\u{ce0}', '\u{ce1}'), ('\u{cf1}', '\u{cf2}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', - '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'), ('\u{d4e}', '\u{d4e}'), - ('\u{d5f}', '\u{d61}'), ('\u{d7a}', '\u{d7f}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', - '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), - ('\u{e01}', '\u{e30}'), ('\u{e32}', '\u{e32}'), ('\u{e40}', '\u{e46}'), ('\u{e81}', - '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), - ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', - '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', '\u{eab}'), - ('\u{ead}', '\u{eb0}'), ('\u{eb2}', '\u{eb2}'), ('\u{ebd}', '\u{ebd}'), ('\u{ec0}', - '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), - ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f88}', '\u{f8c}'), ('\u{1000}', - '\u{102a}'), ('\u{103f}', '\u{103f}'), ('\u{1050}', '\u{1055}'), ('\u{105a}', '\u{105d}'), - ('\u{1061}', '\u{1061}'), ('\u{1065}', '\u{1066}'), ('\u{106e}', '\u{1070}'), ('\u{1075}', - '\u{1081}'), ('\u{108e}', '\u{108e}'), ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), - ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}', - '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), - ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}', - '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), - ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', - '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), - ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}', - '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1711}'), - ('\u{1720}', '\u{1731}'), ('\u{1740}', '\u{1751}'), ('\u{1760}', '\u{176c}'), ('\u{176e}', - '\u{1770}'), ('\u{1780}', '\u{17b3}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), - ('\u{1820}', '\u{1877}'), ('\u{1880}', '\u{18a8}'), ('\u{18aa}', '\u{18aa}'), ('\u{18b0}', - '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'), - ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}', '\u{1a16}'), ('\u{1a20}', - '\u{1a54}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1b05}', '\u{1b33}'), ('\u{1b45}', '\u{1b4b}'), - ('\u{1b83}', '\u{1ba0}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'), ('\u{1c00}', - '\u{1c23}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'), ('\u{1ce9}', '\u{1cec}'), - ('\u{1cee}', '\u{1cf1}'), ('\u{1cf5}', '\u{1cf6}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1e00}', - '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), - ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', - '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), - ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', - '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), - ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', - '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), - ('\u{2115}', '\u{2115}'), ('\u{2118}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', - '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{2139}'), ('\u{213c}', '\u{213f}'), - ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{2c00}', - '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}'), ('\u{2c60}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), - ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', - '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), - ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', - '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), - ('\u{2dd8}', '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3031}', - '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), - ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'), ('\u{3131}', - '\u{318e}'), ('\u{31a0}', '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'), - ('\u{4e00}', '\u{9fd5}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}', - '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), - ('\u{a67f}', '\u{a69d}'), ('\u{a6a0}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}', - '\u{a788}'), ('\u{a78b}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b7}'), ('\u{a7f7}', '\u{a801}'), - ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}', - '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), - ('\u{a8fd}', '\u{a8fd}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', - '\u{a97c}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), - ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'), ('\u{aa40}', - '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), - ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}', - '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), - ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', - '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), - ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab65}'), ('\u{ab70}', '\u{abe2}'), ('\u{ac00}', - '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), - ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', - '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), - ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', - '\u{fbb1}'), ('\u{fbd3}', '\u{fc5d}'), ('\u{fc64}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), - ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdf9}'), ('\u{fe71}', '\u{fe71}'), ('\u{fe73}', - '\u{fe73}'), ('\u{fe77}', '\u{fe77}'), ('\u{fe79}', '\u{fe79}'), ('\u{fe7b}', '\u{fe7b}'), - ('\u{fe7d}', '\u{fe7d}'), ('\u{fe7f}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', - '\u{ff5a}'), ('\u{ff66}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), - ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', - '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', - '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', - '\u{100fa}'), ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', - '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{1034a}'), ('\u{10350}', - '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', - '\u{103cf}'), ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', - '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', - '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', - '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', - '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', - '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}', - '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', - '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', - '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', - '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', - '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', - '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', - '\u{10cf2}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'), ('\u{110d0}', - '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', - '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}', - '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', - '\u{1122b}'), ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', - '\u{1128d}'), ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', - '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', - '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', - '\u{11339}'), ('\u{1133d}', '\u{1133d}'), ('\u{11350}', '\u{11350}'), ('\u{1135d}', - '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', - '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{115d8}', '\u{115db}'), ('\u{11600}', - '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'), ('\u{11700}', - '\u{11719}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'), ('\u{11ac0}', - '\u{11af8}'), ('\u{12000}', '\u{12399}'), ('\u{12400}', '\u{1246e}'), ('\u{12480}', - '\u{12543}'), ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', - '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), ('\u{16b00}', - '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', - '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), ('\u{16f93}', - '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', - '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1d400}', - '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', - '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', - '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', - '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', - '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', - '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', - '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', - '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', - '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', - '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1e800}', - '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', - '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', - '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', - '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', - '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', - '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', - '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', - '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', - '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', - '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', - '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', - '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', - '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2f800}', '\u{2fa1d}') - ]; + pub const XID_Start_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x0000501f0003ffc3, + 0x0000000000000000, 0xb8df000000000000, 0xfffffffbffffd740, 0xffbfffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffffffffc03, 0xffffffffffffffff, + 0xfffeffffffffffff, 0xfffffffe027fffff, 0x00000000000000ff, 0x000707ffffff0000, + 0xffffffff00000000, 0xfffec000000007ff, 0xffffffffffffffff, 0x9c00c060002fffff, + 0x0000fffffffd0000, 0xffffffffffffe000, 0x0002003fffffffff, 0x043007fffffffc00 + ], + r2: [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 23, 25, 26, 27, 28, 29, 3, 30, 31, 32, 33, 34, 34, 34, 34, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 34, 34, 34, 34, 34, 34, 34, 34, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 3, 61, 62, 63, 64, 65, 66, 3, 67, 34, 34, 34, 3, 34, 34, 34, + 34, 68, 69, 70, 71, 3, 72, 73, 3, 74, 75, 76, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 77, 78, + 34, 79, 80, 81, 82, 83, 3, 3, 3, 3, 3, 3, 3, 3, 84, 42, 85, 86, 87, 34, 88, 89, 3, 3, 3, + 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 53, 3, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91, 92, 34, 34, 34, 34, 93, 94, + 95, 96, 97, 34, 98, 99, 100, 48, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 34, 113, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 114, 115, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, 34, 34, 34, 34, + 116, 34, 117, 118, 119, 120, 121, 34, 122, 34, 34, 123, 124, 125, 126, 3, 127, 34, 128, + 129, 130, 131, 132 + ], + r3: &[ + 0x00000110043fffff, 0x0000000001ffffff, 0x001fffff00000000, 0x0000000000000000, + 0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x00030003b0004000, + 0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000, + 0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000, + 0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe0, 0x0006000340000000, + 0x27fffffffffddfe0, 0xfc00000380004000, 0x2ffbfffffc7fffe0, 0x000000000000007f, + 0x0005fffffffffffe, 0x2005ecaefef02596, 0x00000000f000005f, 0x0000000000000001, + 0x00001ffffffffeff, 0x0000000000001f00, 0x800007ffffffffff, 0xffe1c0623c3f0000, + 0xffffffff00004003, 0xf7ffffffffff20bf, 0xffffffffffffffff, 0xffffffff3d7f3dff, + 0x7f3dffffffff3dff, 0xffffffffff7fff3d, 0xffffffffff3dffff, 0x0000000007ffffff, + 0xffffffff0000ffff, 0x3f3fffffffffffff, 0xfffffffffffffffe, 0xffff9fffffffffff, + 0xffffffff07fffffe, 0x01ffc7ffffffffff, 0x0003ffff0003dfff, 0x0001dfff0003ffff, + 0x000fffffffffffff, 0x0000000010800000, 0xffffffff00000000, 0x00ffffffffffffff, + 0xffff05ffffffffff, 0x003fffffffffffff, 0x000000007fffffff, 0x001f3fffffff0000, + 0xffff0fffffffffff, 0x00000000000003ff, 0xffffffff007fffff, 0x00000000001fffff, + 0x0000008000000000, 0x000fffffffffffe0, 0x0000000000000fe0, 0xfc00c001fffffff8, + 0x0000003fffffffff, 0x0000000fffffffff, 0x3ffffffffc00e000, 0x0063de0000000000, + 0xffffffff3f3fffff, 0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, + 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84, 0xffffffff000043e0, + 0x00000000000001ff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff, + 0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0x000000007f7f7f7f, + 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0, + 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff, + 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, 0xffffffff3fffffff, + 0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff3ffffffff9ff, 0xff80000000000000, + 0x00000007fffff7bb, 0x000ffffffffffffc, 0x28fc000000000000, 0xffff003ffffffc00, + 0x1fffffff0000007f, 0x0007fffffffffff0, 0x7c00ffdf00008000, 0x000001ffffffffff, + 0xc47fffff00000ff7, 0x3e62ffffffffffff, 0x001c07ff38000005, 0xffff7f7f007e7e7e, + 0xffff003ff7ffffff, 0x00000007ffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, + 0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffa0f8007f, 0xffffffffffffffdb, + 0x0003ffffffffffff, 0xfffffffffff80000, 0xfffffff03fffffff, 0x3fffffffffffffff, + 0xffffffffffff0000, 0xfffffffffffcffff, 0x03ff0000000000ff, 0xaa8a000000000000, + 0x1fffffffffffffff, 0x07fffffe00000000, 0xffffffc007fffffe, 0x7fffffff3fffffff, + 0x000000001cfcfcfc + ], + r4: [ + 0, 1, 2, 3, 4, 5, 6, 5, 5, 5, 5, 7, 5, 8, 9, 5, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 12, 13, 5, 5, 14, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + ], + r5: &[ + 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 4, 13, 14, 4, 4, 2, 2, 2, 2, + 15, 16, 4, 4, 17, 18, 19, 20, 21, 4, 22, 4, 23, 24, 25, 26, 27, 28, 29, 4, 2, 30, 31, + 31, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 32, 4, 33, 34, 35, 36, 37, 38, 39, 4, 40, 19, + 41, 42, 4, 4, 4, 4, 43, 44, 4, 4, 45, 46, 43, 47, 48, 4, 49, 4, 4, 4, 4, 4, 50, 51, 4, + 4, 4, 4, 4, 4, 4, 52, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 49, 4, 2, 45, 2, 2, 2, 53, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 54, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, + 2, 2, 2, 2, 2, 52, 19, 4, 55, 43, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 58, + 59, 4, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 61, 62, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64, 65, + 66, 67, 2, 2, 2, 2, 68, 69, 70, 71, 72, 73, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 74, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 75, 76, 77, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 78, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, + 2, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + ], + r6: &[ + 0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff, + 0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff, + 0xffff0000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f, + 0x000000003fffffff, 0xffff00ffffffffff, 0x0000000fffffffff, 0x007fffffffffffff, + 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff, 0x000000007fffffff, + 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff, 0x000ffffffeef0001, + 0x1fffffff00000000, 0x000000001fffffff, 0x0000001ffffffeff, 0x003fffffffffffff, + 0x0007ffff003fffff, 0x000000000003ffff, 0x00000000000001ff, 0x0007ffffffffffff, + 0x00fffffffffffff8, 0x0000fffffffffff8, 0x000001ffffff0000, 0x0000007ffffffff8, + 0x0047ffffffff0000, 0x0007fffffffffff8, 0x000000001400001e, 0x00000ffffffbffff, + 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000, 0x0000ffffffffffff, + 0x00000000000000b0, 0x00007fffffffffff, 0x000000000f000000, 0x0000000000000010, + 0x000007ffffffffff, 0x0000000003ffffff, 0xffffffff00000000, 0x80000000ffffffff, + 0x01ffffffffffffff, 0x000000000000000f, 0x000000000000007f, 0x00003fffffff0000, + 0xe0fffff80000000f, 0x000000000000ffff, 0x000000000001001f, 0x00000000fff80000, + 0x0000000000000003, 0x1fff07ffffffffff, 0x0000000003ff01ff, 0xffffffffffdfffff, + 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, + 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, + 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef, + 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0x00000003ffffffff + ], + }; pub fn XID_Start(c: char) -> bool { - super::bsearch_range_table(c, XID_Start_table) + super::trie_lookup_range_table(c, XID_Start_table) } } pub mod property { - pub const Pattern_White_Space_table: &'static [(char, char)] = &[ - ('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'), ('\u{200e}', '\u{200f}'), - ('\u{2028}', '\u{2029}') - ]; + pub const Pattern_White_Space_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0x000003000000c000 + ], + r4: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000 + ], + }; pub fn Pattern_White_Space(c: char) -> bool { - super::bsearch_range_table(c, Pattern_White_Space_table) + super::trie_lookup_range_table(c, Pattern_White_Space_table) } - pub const White_Space_table: &'static [(char, char)] = &[ - ('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'), ('\u{a0}', '\u{a0}'), - ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}', - '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}') - ]; + pub const White_Space_table: &'static super::BoolTrie = &super::BoolTrie { + r1: [ + 0x0000000100003e00, 0x0000000000000000, 0x0000000100000020, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + ], + r2: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r3: &[ + 0x0000000000000000, 0x0000000000000001, 0x00008300000007ff, 0x0000000080000000 + ], + r4: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], + r5: &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0 + ], + r6: &[ + 0x0000000000000000 + ], + }; pub fn White_Space(c: char) -> bool { - super::bsearch_range_table(c, White_Space_table) + super::trie_lookup_range_table(c, White_Space_table) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ca138168b2954..4831ee9a2e041 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2579,7 +2579,7 @@ fn name_from_pat(p: &hir::Pat) -> String { match p.node { PatKind::Wild => "_".to_string(), PatKind::Ident(_, ref p, _) => p.node.to_string(), - PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p), + PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p), PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \ which is not allowed in function arguments"), PatKind::Struct(ref name, ref fields, etc) => { @@ -2590,7 +2590,7 @@ fn name_from_pat(p: &hir::Pat) -> String { if etc { ", ..." } else { "" } ) }, - PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) + PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::>().join(", ")), PatKind::Box(ref p) => name_from_pat(&**p), PatKind::Ref(ref p, _) => name_from_pat(&**p), diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index a168fe98a94cf..265ed6be1552d 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -103,6 +103,8 @@ r##"
Move down in search results
Go to active search result
+
+
+
Collapse/expand all sections
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a368b4197a395..14661dbaec4c5 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -124,6 +124,11 @@ focusSearchBar(); break; + case "+": + ev.preventDefault(); + toggleAllDocs(); + break; + case "?": if (ev.shiftKey && $("#help").hasClass("hidden")) { ev.preventDefault(); @@ -931,7 +936,7 @@ return "\u2212"; // "\u2212" is '−' minus sign } - $("#toggle-all-docs").on("click", function() { + function toggleAllDocs() { var toggle = $("#toggle-all-docs"); if (toggle.hasClass("will-expand")) { toggle.removeClass("will-expand"); @@ -950,7 +955,9 @@ $(".toggle-wrapper").addClass("collapsed"); $(".collapse-toggle").children(".inner").text(labelForToggleButton(true)); } - }); + } + + $("#toggle-all-docs").on("click", toggleAllDocs); $(document).on("click", ".collapse-toggle", function() { var toggle = $(this); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index a52a914fea680..8e4245d4ebf12 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -472,7 +472,7 @@ body.blur > :not(#help) { background: #e9e9e9; box-shadow: 0 0 6px rgba(0,0,0,.2); width: 550px; - height: 300px; + height: 330px; border: 1px solid #bfbfbf; } #help dt { diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 59b2ff7e3d649..aa08cee13ef72 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -30,6 +30,10 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t background-color: white; } +div.stability > em > code { + background-color: initial; +} + .docblock code { background-color: #F5F5F5; } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index e0a489bd2f965..37045822d47ec 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -864,7 +864,6 @@ impl HashMap /// # Examples /// /// ``` - /// # #![feature(map_values_mut)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); @@ -881,8 +880,8 @@ impl HashMap /// print!("{}", val); /// } /// ``` - #[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] - pub fn values_mut<'a>(&'a mut self) -> ValuesMut { + #[stable(feature = "map_values_mut", since = "1.10.0")] + pub fn values_mut(&mut self) -> ValuesMut { ValuesMut { inner: self.iter_mut() } } @@ -1288,7 +1287,7 @@ pub struct Drain<'a, K: 'a, V: 'a> { } /// Mutable HashMap values iterator. -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V> } @@ -1491,14 +1490,14 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; #[inline] fn next(&mut self) -> Option<(&'a mut V)> { self.inner.next().map(|(_, v)| v) } #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")] +#[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } @@ -1537,7 +1536,7 @@ impl<'a, K, V> Entry<'a, K, V> { } /// Returns a reference to this entry's key. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { match *self { Occupied(ref entry) => entry.key(), @@ -1548,7 +1547,7 @@ impl<'a, K, V> Entry<'a, K, V> { impl<'a, K, V> OccupiedEntry<'a, K, V> { /// Gets a reference to the key in the entry. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { self.elem.read().0 } @@ -1596,7 +1595,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. - #[unstable(feature = "map_entry_keys", issue = "32281")] + #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { &self.key } diff --git a/src/libstd/error.rs b/src/libstd/error.rs index d49d97649467a..2a2d41112ffae 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -212,6 +212,13 @@ impl Error for Box { } } +#[stable(feature = "fmt_error", since = "1.11.0")] +impl Error for fmt::Error { + fn description(&self) -> &str { + "an error occurred when formatting an argument" + } +} + // copied from any.rs impl Error + 'static { /// Returns true if the boxed type is the same as `T` diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index fbc8886ce8f8c..2bc7585f5fba9 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -159,6 +159,12 @@ pub struct CStr { #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); +/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul +/// byte was found too early in the slice provided or one wasn't found at all. +#[derive(Clone, PartialEq, Debug)] +#[stable(feature = "cstr_from_bytes", since = "1.10.0")] +pub struct FromBytesWithNulError { _a: () } + /// An error returned from `CString::into_string` to indicate that a UTF-8 error /// was encountered during the conversion. #[derive(Clone, PartialEq, Debug)] @@ -461,20 +467,18 @@ impl CStr { /// # Examples /// /// ``` - /// # #![feature(cstr_from_bytes)] /// use std::ffi::CStr; /// - /// # fn main() { /// let cstr = CStr::from_bytes_with_nul(b"hello\0"); - /// assert!(cstr.is_some()); - /// # } + /// assert!(cstr.is_ok()); /// ``` - #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")] - pub fn from_bytes_with_nul(bytes: &[u8]) -> Option<&CStr> { + #[stable(feature = "cstr_from_bytes", since = "1.10.0")] + pub fn from_bytes_with_nul(bytes: &[u8]) + -> Result<&CStr, FromBytesWithNulError> { if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) { - None + Err(FromBytesWithNulError { _a: () }) } else { - Some(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) + Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) } } @@ -487,18 +491,15 @@ impl CStr { /// # Examples /// /// ``` - /// # #![feature(cstr_from_bytes)] /// use std::ffi::{CStr, CString}; /// - /// # fn main() { /// unsafe { /// let cstring = CString::new("hello").unwrap(); /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); /// assert_eq!(cstr, &*cstring); /// } - /// # } /// ``` - #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")] + #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { mem::transmute(bytes) } @@ -742,12 +743,14 @@ mod tests { fn from_bytes_with_nul() { let data = b"123\0"; let cstr = CStr::from_bytes_with_nul(data); - assert_eq!(cstr.map(CStr::to_bytes), Some(&b"123"[..])); - assert_eq!(cstr.map(CStr::to_bytes_with_nul), Some(&b"123\0"[..])); + assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..])); + let cstr = CStr::from_bytes_with_nul(data); + assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..])); unsafe { + let cstr = CStr::from_bytes_with_nul(data); let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data); - assert_eq!(cstr, Some(cstr_unchecked)); + assert_eq!(cstr, Ok(cstr_unchecked)); } } @@ -755,13 +758,13 @@ mod tests { fn from_bytes_with_nul_unterminated() { let data = b"123"; let cstr = CStr::from_bytes_with_nul(data); - assert!(cstr.is_none()); + assert!(cstr.is_err()); } #[test] fn from_bytes_with_nul_interior() { let data = b"1\023\0"; let cstr = CStr::from_bytes_with_nul(data); - assert!(cstr.is_none()); + assert!(cstr.is_err()); } } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index bfd6ab52289b2..ca1ff18f1cad8 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -14,6 +14,8 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use self::c_str::{CString, CStr, NulError, IntoStringError}; +#[stable(feature = "cstr_from_bytes", since = "1.10.0")] +pub use self::c_str::{FromBytesWithNulError}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::{OsString, OsStr}; diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 587c7a95861c1..125170bd47bc9 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -657,7 +657,7 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. - #[unstable(feature = "fs_time", issue = "31399")] + #[stable(feature = "fs_time", since = "1.10.0")] pub fn modified(&self) -> io::Result { self.0.modified().map(FromInner::from_inner) } @@ -675,7 +675,7 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. - #[unstable(feature = "fs_time", issue = "31399")] + #[stable(feature = "fs_time", since = "1.10.0")] pub fn accessed(&self) -> io::Result { self.0.accessed().map(FromInner::from_inner) } @@ -689,7 +689,7 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. - #[unstable(feature = "fs_time", issue = "31399")] + #[stable(feature = "fs_time", since = "1.10.0")] pub fn created(&self) -> io::Result { self.0.created().map(FromInner::from_inner) } diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index 65667f24dda6c..1155160120750 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -12,11 +12,12 @@ use prelude::v1::*; use cell::Cell; use ptr; -use sync::{StaticMutex, Arc}; +use sync::Arc; use sys_common; +use sys_common::mutex::Mutex; pub struct Lazy { - lock: StaticMutex, + lock: Mutex, ptr: Cell<*mut Arc>, init: fn() -> Arc, } @@ -26,23 +27,25 @@ unsafe impl Sync for Lazy {} impl Lazy { pub const fn new(init: fn() -> Arc) -> Lazy { Lazy { - lock: StaticMutex::new(), + lock: Mutex::new(), ptr: Cell::new(ptr::null_mut()), init: init } } pub fn get(&'static self) -> Option> { - let _g = self.lock.lock(); - let ptr = self.ptr.get(); unsafe { - if ptr.is_null() { + self.lock.lock(); + let ptr = self.ptr.get(); + let ret = if ptr.is_null() { Some(self.init()) } else if ptr as usize == 1 { None } else { Some((*ptr).clone()) - } + }; + self.lock.unlock(); + return ret } } @@ -52,10 +55,10 @@ impl Lazy { // the at exit handler). Otherwise we just return the freshly allocated // `Arc`. let registered = sys_common::at_exit(move || { - let g = self.lock.lock(); + self.lock.lock(); let ptr = self.ptr.get(); self.ptr.set(1 as *mut _); - drop(g); + self.lock.unlock(); drop(Box::from_raw(ptr)) }); let ret = (self.init)(); diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 45b85d600a656..ba485f819f880 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -251,7 +251,7 @@ impl PartialOrd for Ipv4Addr { #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { - self.octets().cmp(&other.octets()) + ntoh(self.inner.s_addr).cmp(&ntoh(other.inner.s_addr)) } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 94aa3d6b513ef..c0031aa42e606 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -829,6 +829,13 @@ impl f32 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_deprecated(since = "1.10.0", + reason = "you probably meant `(self - other).abs()`: \ + this operation is `(self - other).max(0.0)` (also \ + known as `fdimf` in C). If you truly need the positive \ + difference, consider using that expression or the C function \ + `fdimf`, depending on how you wish to handle NaN (please consider \ + filing an issue describing your use-case too).")] pub fn abs_sub(self, other: f32) -> f32 { unsafe { cmath::fdimf(self, other) } } @@ -939,7 +946,7 @@ impl f32 { /// let f = f32::consts::PI / 2.0; /// /// // asin(sin(pi/2)) - /// let abs_difference = f.sin().asin().abs_sub(f32::consts::PI / 2.0); + /// let abs_difference = (f.sin().asin() - f32::consts::PI / 2.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -959,7 +966,7 @@ impl f32 { /// let f = f32::consts::PI / 4.0; /// /// // acos(cos(pi/4)) - /// let abs_difference = f.cos().acos().abs_sub(f32::consts::PI / 4.0); + /// let abs_difference = (f.cos().acos() - f32::consts::PI / 4.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -978,7 +985,7 @@ impl f32 { /// let f = 1.0f32; /// /// // atan(tan(1)) - /// let abs_difference = f.tan().atan().abs_sub(1.0); + /// let abs_difference = (f.tan().atan() - 1.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// ``` @@ -1048,7 +1055,7 @@ impl f32 { /// let x = 7.0f64; /// /// // e^(ln(7)) - 1 - /// let abs_difference = x.ln().exp_m1().abs_sub(6.0); + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); /// /// assert!(abs_difference < 1e-10); /// ``` @@ -1108,7 +1115,7 @@ impl f32 { /// let f = x.cosh(); /// // Solving cosh() at 1 gives this result /// let g = (e*e + 1.0)/(2.0*e); - /// let abs_difference = f.abs_sub(g); + /// let abs_difference = (f - g).abs(); /// /// // Same result /// assert!(abs_difference <= f32::EPSILON); @@ -1191,9 +1198,9 @@ impl f32 { /// let e = f32::consts::E; /// let f = e.tanh().atanh(); /// - /// let abs_difference = f.abs_sub(e); + /// let abs_difference = (f - e).abs(); /// - /// assert!(abs_difference <= f32::EPSILON); + /// assert!(abs_difference <= 1e-5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1747,24 +1754,6 @@ mod tests { assert!(match nan.frexp() { (x, _) => x.is_nan() }) } - #[test] - fn test_abs_sub() { - assert_eq!((-1f32).abs_sub(1f32), 0f32); - assert_eq!(1f32.abs_sub(1f32), 0f32); - assert_eq!(1f32.abs_sub(0f32), 1f32); - assert_eq!(1f32.abs_sub(-1f32), 2f32); - assert_eq!(NEG_INFINITY.abs_sub(0f32), 0f32); - assert_eq!(INFINITY.abs_sub(1f32), INFINITY); - assert_eq!(0f32.abs_sub(NEG_INFINITY), INFINITY); - assert_eq!(0f32.abs_sub(INFINITY), 0f32); - } - - #[test] - fn test_abs_sub_nowin() { - assert!(NAN.abs_sub(-1f32).is_nan()); - assert!(1f32.abs_sub(NAN).is_nan()); - } - #[test] fn test_asinh() { assert_eq!(0.0f32.asinh(), 0.0f32); diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 2beffb64d3dc4..1a46d9a389578 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -718,9 +718,16 @@ impl f64 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } - } + #[rustc_deprecated(since = "1.10.0", + reason = "you probably meant `(self - other).abs()`: \ + this operation is `(self - other).max(0.0)` (also \ + known as `fdim` in C). If you truly need the positive \ + difference, consider using that expression or the C function \ + `fdim`, depending on how you wish to handle NaN (please consider \ + filing an issue describing your use-case too).")] + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } /// Takes the cubic root of a number. /// @@ -1642,24 +1649,6 @@ mod tests { assert!(match nan.frexp() { (x, _) => x.is_nan() }) } - #[test] - fn test_abs_sub() { - assert_eq!((-1f64).abs_sub(1f64), 0f64); - assert_eq!(1f64.abs_sub(1f64), 0f64); - assert_eq!(1f64.abs_sub(0f64), 1f64); - assert_eq!(1f64.abs_sub(-1f64), 2f64); - assert_eq!(NEG_INFINITY.abs_sub(0f64), 0f64); - assert_eq!(INFINITY.abs_sub(1f64), INFINITY); - assert_eq!(0f64.abs_sub(NEG_INFINITY), INFINITY); - assert_eq!(0f64.abs_sub(INFINITY), 0f64); - } - - #[test] - fn test_abs_sub_nowin() { - assert!(NAN.abs_sub(-1f64).is_nan()); - assert!(1f64.abs_sub(NAN).is_nan()); - } - #[test] fn test_asinh() { assert_eq!(0.0f64.asinh(), 0.0f64); diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index a2c6e79fb92fc..016130e99989e 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -22,7 +22,7 @@ use rc::Rc; use sync::{Arc, Mutex, RwLock}; use thread::Result; -#[unstable(feature = "panic_handler", issue = "30449")] +#[stable(feature = "panic_hooks", since = "1.10.0")] pub use panicking::{take_hook, set_hook, PanicInfo, Location}; /// @@ -39,14 +39,14 @@ pub fn take_handler() -> Box { take_hook() } -/// A marker trait which represents "panic safe" types in Rust. +/// A marker trait which represents "unwind safe" types in Rust. /// /// This trait is implemented by default for many types and behaves similarly in /// terms of inference of implementation to the `Send` and `Sync` traits. The -/// purpose of this trait is to encode what types are safe to cross a `recover` -/// boundary with no fear of panic safety. +/// purpose of this trait is to encode what types are safe to cross a `catch_unwind` +/// boundary with no fear of unwind safety. /// -/// ## What is panic safety? +/// ## What is unwind safety? /// /// In Rust a function can "return" early if it either panics or calls a /// function which transitively panics. This sort of control flow is not always @@ -59,62 +59,62 @@ pub fn take_handler() -> Box { /// /// Typically in Rust, it is difficult to perform step (2) because catching a /// panic involves either spawning a thread (which in turns makes it difficult -/// to later witness broken invariants) or using the `recover` function in this +/// to later witness broken invariants) or using the `catch_unwind` function in this /// module. Additionally, even if an invariant is witnessed, it typically isn't a -/// problem in Rust because there's no uninitialized values (like in C or C++). +/// problem in Rust because there are no uninitialized values (like in C or C++). /// /// It is possible, however, for **logical** invariants to be broken in Rust, -/// which can end up causing behavioral bugs. Another key aspect of panic safety +/// which can end up causing behavioral bugs. Another key aspect of unwind safety /// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to /// memory unsafety. /// -/// That was a bit of a whirlwind tour of panic safety, but for more information -/// about panic safety and how it applies to Rust, see an [associated RFC][rfc]. +/// That was a bit of a whirlwind tour of unwind safety, but for more information +/// about unwind safety and how it applies to Rust, see an [associated RFC][rfc]. /// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md /// /// ## What is `UnwindSafe`? /// -/// Now that we've got an idea of what panic safety is in Rust, it's also +/// Now that we've got an idea of what unwind safety is in Rust, it's also /// important to understand what this trait represents. As mentioned above, one -/// way to witness broken invariants is through the `recover` function in this +/// way to witness broken invariants is through the `catch_unwind` function in this /// module as it allows catching a panic and then re-using the environment of /// the closure. /// /// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow -/// witnessing a broken invariant through the use of `recover` (catching a +/// witnessing a broken invariant through the use of `catch_unwind` (catching a /// panic). This trait is a marker trait, so it is automatically implemented for -/// many types, and it is also structurally composed (e.g. a struct is recover -/// safe if all of its components are recover safe). +/// many types, and it is also structurally composed (e.g. a struct is unwind +/// safe if all of its components are unwind safe). /// /// Note, however, that this is not an unsafe trait, so there is not a succinct /// contract that this trait is providing. Instead it is intended as more of a -/// "speed bump" to alert users of `recover` that broken invariants may be +/// "speed bump" to alert users of `catch_unwind` that broken invariants may be /// witnessed and may need to be accounted for. /// /// ## Who implements `UnwindSafe`? /// /// Types such as `&mut T` and `&RefCell` are examples which are **not** -/// recover safe. The general idea is that any mutable state which can be shared -/// across `recover` is not recover safe by default. This is because it is very -/// easy to witness a broken invariant outside of `recover` as the data is +/// unwind safe. The general idea is that any mutable state which can be shared +/// across `catch_unwind` is not unwind safe by default. This is because it is very +/// easy to witness a broken invariant outside of `catch_unwind` as the data is /// simply accessed as usual. /// -/// Types like `&Mutex`, however, are recover safe because they implement +/// Types like `&Mutex`, however, are unwind safe because they implement /// poisoning by default. They still allow witnessing a broken invariant, but /// they already provide their own "speed bumps" to do so. /// /// ## When should `UnwindSafe` be used? /// /// Is not intended that most types or functions need to worry about this trait. -/// It is only used as a bound on the `recover` function and as mentioned above, +/// It is only used as a bound on the `catch_unwind` function and as mentioned above, /// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe` /// wrapper struct in this module can be used to force this trait to be -/// implemented for any closed over variables passed to the `recover` function +/// implemented for any closed over variables passed to the `catch_unwind` function /// (more on this below). #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \ - across a recover boundary"] + across an unwind boundary"] pub trait UnwindSafe {} /// Deprecated, renamed to UnwindSafe @@ -126,7 +126,7 @@ pub trait RecoverSafe {} impl RecoverSafe for T {} /// A marker trait representing types where a shared reference is considered -/// recover safe. +/// unwind safe. /// /// This trait is namely not implemented by `UnsafeCell`, the root of all /// interior mutability. @@ -136,23 +136,23 @@ impl RecoverSafe for T {} #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} contains interior mutability \ and a reference may not be safely transferrable \ - across a recover boundary"] + across a catch_unwind boundary"] pub trait RefUnwindSafe {} -/// A simple wrapper around a type to assert that it is panic safe. +/// A simple wrapper around a type to assert that it is unwind safe. /// -/// When using `recover` it may be the case that some of the closed over -/// variables are not panic safe. For example if `&mut T` is captured the -/// compiler will generate a warning indicating that it is not panic safe. It +/// When using `catch_unwind` it may be the case that some of the closed over +/// variables are not unwind safe. For example if `&mut T` is captured the +/// compiler will generate a warning indicating that it is not unwind safe. It /// may not be the case, however, that this is actually a problem due to the -/// specific usage of `recover` if panic safety is specifically taken into +/// specific usage of `catch_unwind` if unwind safety is specifically taken into /// account. This wrapper struct is useful for a quick and lightweight -/// annotation that a variable is indeed panic safe. +/// annotation that a variable is indeed unwind safe. /// /// # Examples /// /// One way to use `AssertUnwindSafe` is to assert that the entire closure -/// itself is recover safe, bypassing all checks for all variables: +/// itself is unwind safe, bypassing all checks for all variables: /// /// ``` /// use std::panic::{self, AssertUnwindSafe}; @@ -160,7 +160,7 @@ pub trait RefUnwindSafe {} /// let mut variable = 4; /// /// // This code will not compile because the closure captures `&mut variable` -/// // which is not considered panic safe by default. +/// // which is not considered unwind safe by default. /// /// // panic::catch_unwind(|| { /// // variable += 3; @@ -239,7 +239,7 @@ impl UnwindSafe for AssertUnwindSafe {} impl UnwindSafe for AssertRecoverSafe {} // not covered via the Shared impl above b/c the inner contents use -// Cell/AtomicUsize, but the usage here is recover safe so we can lift the +// Cell/AtomicUsize, but the usage here is unwind safe so we can lift the // impl up one level to Arc/Rc itself #[stable(feature = "catch_unwind", since = "1.9.0")] impl UnwindSafe for Rc {} @@ -352,9 +352,9 @@ impl R> FnOnce<()> for AssertRecoverSafe { /// that all captured variables are safe to cross this boundary. The purpose of /// this bound is to encode the concept of [exception safety][rfc] in the type /// system. Most usage of this function should not need to worry about this -/// bound as programs are naturally panic safe without `unsafe` code. If it +/// bound as programs are naturally unwind safe without `unsafe` code. If it /// becomes a problem the associated `AssertUnwindSafe` wrapper type in this -/// module can be used to quickly assert that the usage here is indeed exception +/// module can be used to quickly assert that the usage here is indeed unwind /// safe. /// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md @@ -395,7 +395,7 @@ pub fn recover R + UnwindSafe, R>(f: F) -> Result { catch_unwind(f) } -/// Triggers a panic without invoking the panic handler. +/// Triggers a panic without invoking the panic hook. /// /// This is designed to be used in conjunction with `catch_unwind` to, for /// example, carry a panic across a layer of C code. diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index b85d4b330a6e3..d73e9542d2125 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -27,7 +27,7 @@ use fmt; use intrinsics; use mem; use raw; -use sync::StaticRwLock; +use sys_common::rwlock::RWLock; use sync::atomic::{AtomicBool, Ordering}; use sys::stdio::Stderr; use sys_common::backtrace; @@ -69,16 +69,17 @@ enum Hook { Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)), } -static HOOK_LOCK: StaticRwLock = StaticRwLock::new(); +static HOOK_LOCK: RWLock = RWLock::new(); static mut HOOK: Hook = Hook::Default; static FIRST_PANIC: AtomicBool = AtomicBool::new(true); /// Registers a custom panic hook, replacing any that was previously registered. /// -/// The panic hook is invoked when a thread panics, but before it begins -/// unwinding the stack. The default hook prints a message to standard error -/// and generates a backtrace if requested, but this behavior can be customized -/// with the `set_hook` and `take_hook` functions. +/// The panic hook is invoked when a thread panics, but before the panic runtime +/// is invoked. As such, the hook will run with both the aborting and unwinding +/// runtimes. The default hook prints a message to standard error and generates +/// a backtrace if requested, but this behavior can be customized with the +/// `set_hook` and `take_hook` functions. /// /// The hook is provided with a `PanicInfo` struct which contains information /// about the origin of the panic, including the payload passed to `panic!` and @@ -89,17 +90,17 @@ static FIRST_PANIC: AtomicBool = AtomicBool::new(true); /// # Panics /// /// Panics if called from a panicking thread. -#[unstable(feature = "panic_handler", issue = "30449")] +#[stable(feature = "panic_hooks", since = "1.10.0")] pub fn set_hook(hook: Box) { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } unsafe { - let lock = HOOK_LOCK.write(); + HOOK_LOCK.write(); let old_hook = HOOK; HOOK = Hook::Custom(Box::into_raw(hook)); - drop(lock); + HOOK_LOCK.write_unlock(); if let Hook::Custom(ptr) = old_hook { Box::from_raw(ptr); @@ -114,17 +115,17 @@ pub fn set_hook(hook: Box) { /// # Panics /// /// Panics if called from a panicking thread. -#[unstable(feature = "panic_handler", issue = "30449")] +#[stable(feature = "panic_hooks", since = "1.10.0")] pub fn take_hook() -> Box { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } unsafe { - let lock = HOOK_LOCK.write(); + HOOK_LOCK.write(); let hook = HOOK; HOOK = Hook::Default; - drop(lock); + HOOK_LOCK.write_unlock(); match hook { Hook::Default => Box::new(default_hook), @@ -134,7 +135,7 @@ pub fn take_hook() -> Box { } /// A struct providing information about a panic. -#[unstable(feature = "panic_handler", issue = "30449")] +#[stable(feature = "panic_hooks", since = "1.10.0")] pub struct PanicInfo<'a> { payload: &'a (Any + Send), location: Location<'a>, @@ -144,7 +145,7 @@ impl<'a> PanicInfo<'a> { /// Returns the payload associated with the panic. /// /// This will commonly, but not always, be a `&'static str` or `String`. - #[unstable(feature = "panic_handler", issue = "30449")] + #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn payload(&self) -> &(Any + Send) { self.payload } @@ -154,14 +155,14 @@ impl<'a> PanicInfo<'a> { /// /// This method will currently always return `Some`, but this may change /// in future versions. - #[unstable(feature = "panic_handler", issue = "30449")] + #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&Location> { Some(&self.location) } } /// A struct containing information about the location of a panic. -#[unstable(feature = "panic_handler", issue = "30449")] +#[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { file: &'a str, line: u32, @@ -169,13 +170,13 @@ pub struct Location<'a> { impl<'a> Location<'a> { /// Returns the name of the source file from which the panic originated. - #[unstable(feature = "panic_handler", issue = "30449")] + #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn file(&self) -> &str { self.file } /// Returns the line number from which the panic originated. - #[unstable(feature = "panic_handler", issue = "30449")] + #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn line(&self) -> u32 { self.line } @@ -364,11 +365,12 @@ fn rust_panic_with_hook(msg: Box, line: line, }, }; - let _lock = HOOK_LOCK.read(); + HOOK_LOCK.read(); match HOOK { Hook::Default => default_hook(&info), Hook::Custom(ptr) => (*ptr)(&info), } + HOOK_LOCK.read_unlock(); } if panics > 0 { diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 57932f0379683..bf4b119a0b666 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -72,6 +72,7 @@ impl WaitTimeoutResult { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct Condvar { inner: Box } /// Statically allocated condition variables. @@ -91,6 +92,11 @@ pub struct Condvar { inner: Box } #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Condvar::new` in a static should \ + suffice")] pub struct StaticCondvar { inner: sys::Condvar, mutex: AtomicUsize, @@ -100,8 +106,15 @@ pub struct StaticCondvar { #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Condvar::new` in a static should \ + suffice")] +#[allow(deprecated)] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar::new(); +#[allow(deprecated)] impl Condvar { /// Creates a new condition variable which is ready to be waited on and /// notified. @@ -228,12 +241,22 @@ impl Default for Condvar { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl Drop for Condvar { fn drop(&mut self) { unsafe { self.inner.inner.destroy() } } } +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Condvar::new` in a static should \ + suffice")] +#[unstable(feature = "static_condvar", + reason = "may be merged with Condvar in the future", + issue = "27717")] +#[allow(deprecated)] impl StaticCondvar { /// Creates a new condition variable #[unstable(feature = "static_condvar", @@ -392,6 +415,7 @@ impl StaticCondvar { } #[cfg(test)] +#[allow(deprecated)] mod tests { use prelude::v1::*; diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 21008ee3989a7..56eb7340c890c 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -25,10 +25,13 @@ pub use core::sync::atomic; #[stable(feature = "rust1", since = "1.0.0")] pub use self::barrier::{Barrier, BarrierWaitResult}; #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use self::condvar::{Condvar, StaticCondvar, WaitTimeoutResult, CONDVAR_INIT}; #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use self::mutex::MUTEX_INIT; #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::once::{Once, OnceState, ONCE_INIT}; @@ -37,6 +40,7 @@ pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResul #[stable(feature = "rust1", since = "1.0.0")] pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard}; #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT}; pub mod mpsc; diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 90cc79dad66bb..15e69628c7a5d 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -113,6 +113,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// *guard += 1; /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct Mutex { // Note that this static mutex is in a *box*, not inlined into the struct // itself. Once a native mutex has been used once, its address can never @@ -156,6 +157,11 @@ unsafe impl Sync for Mutex { } #[unstable(feature = "static_mutex", reason = "may be merged with Mutex in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Mutex::new` in a static should \ + suffice")] pub struct StaticMutex { lock: sys::Mutex, poison: poison::Flag, @@ -168,6 +174,7 @@ pub struct StaticMutex { /// `Deref` and `DerefMut` implementations #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct MutexGuard<'a, T: ?Sized + 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). @@ -184,8 +191,15 @@ impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {} #[unstable(feature = "static_mutex", reason = "may be merged with Mutex in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Mutex::new` in a static should \ + suffice")] +#[allow(deprecated)] pub const MUTEX_INIT: StaticMutex = StaticMutex::new(); +#[allow(deprecated)] impl Mutex { /// Creates a new mutex in an unlocked state ready for use. #[stable(feature = "rust1", since = "1.0.0")] @@ -197,6 +211,7 @@ impl Mutex { } } +#[allow(deprecated)] impl Mutex { /// Acquires a mutex, blocking the current thread until it is able to do so. /// @@ -307,6 +322,7 @@ impl Mutex { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl Drop for Mutex { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { @@ -346,6 +362,12 @@ static DUMMY: Dummy = Dummy(UnsafeCell::new(())); #[unstable(feature = "static_mutex", reason = "may be merged with Mutex in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `Mutex::new` in a static should \ + suffice")] +#[allow(deprecated)] impl StaticMutex { /// Creates a new mutex in an unlocked state ready for use. pub const fn new() -> StaticMutex { @@ -391,8 +413,8 @@ impl StaticMutex { } } +#[allow(deprecated)] impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { - unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell) -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { @@ -418,6 +440,7 @@ impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { @@ -428,15 +451,18 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } +#[allow(deprecated)] pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.lock } +#[allow(deprecated)] pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.__lock.poison } #[cfg(test)] +#[allow(deprecated)] mod tests { use prelude::v1::*; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index cfb8ee16cb069..e1e764bd255cb 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -66,6 +66,7 @@ use sys_common::rwlock as sys; /// } // write lock is dropped here /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct RwLock { inner: Box, data: UnsafeCell, @@ -104,6 +105,11 @@ unsafe impl Sync for RwLock {} #[unstable(feature = "static_rwlock", reason = "may be merged with RwLock in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `RwLock::new` in a static should \ + suffice")] pub struct StaticRwLock { lock: sys::RWLock, poison: poison::Flag, @@ -113,12 +119,19 @@ pub struct StaticRwLock { #[unstable(feature = "static_rwlock", reason = "may be merged with RwLock in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `RwLock::new` in a static should \ + suffice")] +#[allow(deprecated)] pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new(); /// RAII structure used to release the shared read access of a lock when /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { __lock: &'a StaticRwLock, __data: &'a T, @@ -131,6 +144,7 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {} /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { __lock: &'a StaticRwLock, __data: &'a mut T, @@ -140,6 +154,7 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {} +#[allow(deprecated)] impl RwLock { /// Creates a new instance of an `RwLock` which is unlocked. /// @@ -156,6 +171,7 @@ impl RwLock { } } +#[allow(deprecated)] impl RwLock { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. @@ -325,6 +341,7 @@ impl RwLock { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl Drop for RwLock { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { @@ -360,6 +377,12 @@ static DUMMY: Dummy = Dummy(UnsafeCell::new(())); #[unstable(feature = "static_rwlock", reason = "may be merged with RwLock in the future", issue = "27717")] +#[rustc_deprecated(since = "1.10.0", + reason = "the lazy-static crate suffices for static sync \ + primitives and eventually this type shouldn't \ + be necessary as `RwLock::new` in a static should \ + suffice")] +#[allow(deprecated)] impl StaticRwLock { /// Creates a new rwlock. pub const fn new() -> StaticRwLock { @@ -434,6 +457,7 @@ impl StaticRwLock { } } +#[allow(deprecated)] impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { @@ -482,6 +506,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { } } +#[allow(deprecated)] impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell) -> LockResult> { @@ -562,10 +587,12 @@ impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> { - fn deref_mut(&mut self) -> &mut T { self.__data + fn deref_mut(&mut self) -> &mut T { + self.__data } } +#[allow(deprecated)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> { fn drop(&mut self) { @@ -573,6 +600,7 @@ impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> { } } +#[allow(deprecated)] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { fn drop(&mut self) { @@ -582,6 +610,7 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { } #[cfg(test)] +#[allow(deprecated)] mod tests { #![allow(deprecated)] // rand diff --git a/src/libstd/sys/common/args.rs b/src/libstd/sys/common/args.rs index 5841754066451..e877391fb8b56 100644 --- a/src/libstd/sys/common/args.rs +++ b/src/libstd/sys/common/args.rs @@ -48,32 +48,36 @@ mod imp { use mem; use ffi::CStr; - use sync::StaticMutex; + use sys_common::mutex::Mutex; static mut GLOBAL_ARGS_PTR: usize = 0; - static LOCK: StaticMutex = StaticMutex::new(); + static LOCK: Mutex = Mutex::new(); pub unsafe fn init(argc: isize, argv: *const *const u8) { let args = (0..argc).map(|i| { CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec() }).collect(); - let _guard = LOCK.lock(); + LOCK.lock(); let ptr = get_global_ptr(); assert!((*ptr).is_none()); (*ptr) = Some(box args); + LOCK.unlock(); } pub unsafe fn cleanup() { - let _guard = LOCK.lock(); + LOCK.lock(); *get_global_ptr() = None; + LOCK.unlock(); } pub fn clone() -> Option>> { - let _guard = LOCK.lock(); unsafe { + LOCK.lock(); let ptr = get_global_ptr(); - (*ptr).as_ref().map(|s| (**s).clone()) + let ret = (*ptr).as_ref().map(|s| (**s).clone()); + LOCK.unlock(); + return ret } } diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index b7a6b7650d540..1df511a8818c4 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -10,7 +10,6 @@ use env; use fmt; -use intrinsics; use io::prelude::*; use sync::atomic::{self, Ordering}; use sys::stdio::Stderr; @@ -34,9 +33,32 @@ pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } +// On Unix-like platforms, libc::abort will unregister signal handlers +// including the SIGABRT handler, preventing the abort from being blocked, and +// fclose streams, with the side effect of flushing them so libc bufferred +// output will be printed. Additionally the shell will generally print a more +// understandable error message like "Abort trap" rather than "Illegal +// instruction" that intrinsics::abort would cause, as intrinsics::abort is +// implemented as an illegal instruction. +#[cfg(unix)] +unsafe fn abort_internal() -> ! { + use libc; + libc::abort() +} + +// On Windows, we want to avoid using libc, and there isn't a direct +// equivalent of libc::abort. The __failfast intrinsic may be a reasonable +// substitute, but desireability of using it over the abort instrinsic is +// debateable; see https://github.com/rust-lang/rust/pull/31519 for details. +#[cfg(not(unix))] +unsafe fn abort_internal() -> ! { + use intrinsics; + intrinsics::abort() +} + pub fn abort(args: fmt::Arguments) -> ! { dumb_print(format_args!("fatal runtime error: {}\n", args)); - unsafe { intrinsics::abort(); } + unsafe { abort_internal(); } } #[allow(dead_code)] // stack overflow detection not enabled on all platforms diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs index de93d3d4e509f..ca2e70b5003a1 100644 --- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs +++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs @@ -18,12 +18,11 @@ /// simple to use it should be used only on iOS devices as the only viable /// option. -use io; use io::prelude::*; +use io; use libc; use mem; -use result::Result::Ok; -use sync::StaticMutex; +use sys::mutex::Mutex; use super::super::printing::print; @@ -37,18 +36,21 @@ pub fn write(w: &mut Write) -> io::Result<()> { // while it doesn't requires lock for work as everything is // local, it still displays much nicer backtraces when a // couple of threads panic simultaneously - static LOCK: StaticMutex = StaticMutex::new(); - let _g = LOCK.lock(); + static LOCK: Mutex = Mutex::new(); + unsafe { + LOCK.lock(); - writeln!(w, "stack backtrace:")?; - // 100 lines should be enough - const SIZE: usize = 100; - let mut buf: [*mut libc::c_void; SIZE] = unsafe { mem::zeroed() }; - let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize}; + writeln!(w, "stack backtrace:")?; + // 100 lines should be enough + const SIZE: usize = 100; + let mut buf: [*mut libc::c_void; SIZE] = mem::zeroed(); + let cnt = backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize; - // skipping the first one as it is write itself - for i in 1..cnt { - print(w, i as isize, buf[i], buf[i])? + // skipping the first one as it is write itself + for i in 1..cnt { + print(w, i as isize, buf[i], buf[i])? + } + LOCK.unlock(); } Ok(()) } diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs index 5f7ad6918cdd2..c1b45620ab04a 100644 --- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs +++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs @@ -12,7 +12,7 @@ use io; use io::prelude::*; use libc; use mem; -use sync::StaticMutex; +use sys_common::mutex::Mutex; use super::super::printing::print; use unwind as uw; @@ -31,24 +31,28 @@ pub fn write(w: &mut Write) -> io::Result<()> { // is semi-reasonable in terms of printing anyway, and we know that all // I/O done here is blocking I/O, not green I/O, so we don't have to // worry about this being a native vs green mutex. - static LOCK: StaticMutex = StaticMutex::new(); - let _g = LOCK.lock(); + static LOCK: Mutex = Mutex::new(); + unsafe { + LOCK.lock(); - writeln!(w, "stack backtrace:")?; + writeln!(w, "stack backtrace:")?; - let mut cx = Context { writer: w, last_error: None, idx: 0 }; - return match unsafe { - uw::_Unwind_Backtrace(trace_fn, - &mut cx as *mut Context as *mut libc::c_void) - } { - uw::_URC_NO_REASON => { - match cx.last_error { - Some(err) => Err(err), - None => Ok(()) + let mut cx = Context { writer: w, last_error: None, idx: 0 }; + let ret = match { + uw::_Unwind_Backtrace(trace_fn, + &mut cx as *mut Context as *mut libc::c_void) + } { + uw::_URC_NO_REASON => { + match cx.last_error { + Some(err) => Err(err), + None => Ok(()) + } } - } - _ => Ok(()), - }; + _ => Ok(()), + }; + LOCK.unlock(); + return ret + } extern fn trace_fn(ctx: *mut uw::_Unwind_Context, arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index a1528458860f6..bb90a977433e0 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -88,9 +88,7 @@ pub trait OpenOptionsExt { /// } /// let file = options.open("foo.txt"); /// ``` - #[unstable(feature = "expand_open_options", - reason = "recently added", - issue = "30014")] + #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: i32) -> &mut Self; } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index a74f7ea13b415..b5287cce4843c 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![unstable(feature = "unix_socket", reason = "newly added", issue = "32312")] + +#![stable(feature = "unix_socket", since = "1.10.0")] //! Unix-specific networking functionality @@ -75,6 +76,7 @@ enum AddressKind<'a> { /// An address associated with a Unix socket. #[derive(Clone)] +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { addr: libc::sockaddr_un, len: libc::socklen_t, @@ -109,6 +111,7 @@ impl SocketAddr { } /// Returns true iff the address is unnamed. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { true @@ -118,6 +121,7 @@ impl SocketAddr { } /// Returns the contents of this address if it is a `pathname` address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { Some(path) @@ -141,6 +145,7 @@ impl SocketAddr { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.address() { @@ -168,8 +173,6 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::os::unix::net::UnixStream; /// use std::io::prelude::*; /// @@ -179,8 +182,10 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// stream.read_to_string(&mut response).unwrap(); /// println!("{}", response); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixStream"); @@ -197,6 +202,7 @@ impl fmt::Debug for UnixStream { impl UnixStream { /// Connects to the socket named by `path`. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { unsafe { @@ -213,6 +219,7 @@ impl UnixStream { /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; Ok((UnixStream(i1), UnixStream(i2))) @@ -224,16 +231,19 @@ impl UnixStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propogated to the other /// stream. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } /// Returns the socket address of the local half of this connection. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Returns the socket address of the remote half of this connection. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } @@ -243,6 +253,7 @@ impl UnixStream { /// If the provided value is `None`, then `read` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -252,26 +263,31 @@ impl UnixStream { /// If the provided value is `None`, then `write` calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() } @@ -281,11 +297,13 @@ impl UnixStream { /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value /// (see the documentation of `Shutdown`). + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl io::Read for UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { io::Read::read(&mut &*self, buf) @@ -296,6 +314,7 @@ impl io::Read for UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> io::Read for &'a UnixStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -306,6 +325,7 @@ impl<'a> io::Read for &'a UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl io::Write for UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { io::Write::write(&mut &*self, buf) @@ -316,6 +336,7 @@ impl io::Write for UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -326,18 +347,21 @@ impl<'a> io::Write for &'a UnixStream { } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixStream { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixStream { unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { UnixStream(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixStream { fn into_raw_fd(self) -> RawFd { self.0.into_inner() @@ -349,8 +373,6 @@ impl IntoRawFd for UnixStream { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -377,8 +399,10 @@ impl IntoRawFd for UnixStream { /// // close the listener socket /// drop(listener); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixListener(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixListener { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixListener"); @@ -392,6 +416,7 @@ impl fmt::Debug for UnixListener { impl UnixListener { /// Creates a new `UnixListener` bound to the specified socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { unsafe { @@ -412,6 +437,7 @@ impl UnixListener { /// This function will block the calling thread until a new Unix connection /// is established. When established, the corersponding `UnixStream` and /// the remote peer's address will be returned. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; let mut len = mem::size_of_val(&storage) as libc::socklen_t; @@ -425,21 +451,25 @@ impl UnixListener { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } /// Returns the local socket address of this listener. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() } @@ -448,29 +478,34 @@ impl UnixListener { /// /// The iterator will never return `None` and will also not yield the /// peer's `SocketAddr` structure. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixListener { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixListener { unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { UnixListener(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixListener { fn into_raw_fd(self) -> RawFd { self.0.into_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> IntoIterator for &'a UnixListener { type Item = io::Result; type IntoIter = Incoming<'a>; @@ -484,10 +519,12 @@ impl<'a> IntoIterator for &'a UnixListener { /// /// It will never return `None`. #[derive(Debug)] +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct Incoming<'a> { listener: &'a UnixListener, } +#[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; @@ -505,8 +542,6 @@ impl<'a> Iterator for Incoming<'a> { /// # Examples /// /// ```rust,no_run -/// #![feature(unix_socket)] -/// /// use std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap(); @@ -515,8 +550,10 @@ impl<'a> Iterator for Incoming<'a> { /// let (count, address) = socket.recv_from(&mut buf).unwrap(); /// println!("socket {:?} sent {:?}", address, &buf[..count]); /// ``` +#[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixDatagram(Socket); +#[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixDatagram { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("UnixDatagram"); @@ -533,6 +570,7 @@ impl fmt::Debug for UnixDatagram { impl UnixDatagram { /// Creates a Unix datagram socket bound to the given path. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { unsafe { @@ -548,6 +586,7 @@ impl UnixDatagram { } /// Creates a Unix Datagram socket which is not bound to any address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn unbound() -> io::Result { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; Ok(UnixDatagram(inner)) @@ -556,6 +595,7 @@ impl UnixDatagram { /// Create an unnamed pair of connected sockets. /// /// Returns two `UnixDatagrams`s which are connected to each other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; Ok((UnixDatagram(i1), UnixDatagram(i2))) @@ -565,6 +605,7 @@ impl UnixDatagram { /// /// The `send` method may be used to send data to the specified address. /// `recv` and `recv_from` will only receive data from that address. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(&self, path: P) -> io::Result<()> { fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { unsafe { @@ -583,11 +624,13 @@ impl UnixDatagram { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixDatagram) } /// Returns the address of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } @@ -595,6 +638,7 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// /// The `connect` method will connect the socket to a peer. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } @@ -603,6 +647,7 @@ impl UnixDatagram { /// /// On success, returns the number of bytes read and the address from /// whence the data came. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; let addr = SocketAddr::new(|addr, len| { @@ -629,6 +674,7 @@ impl UnixDatagram { /// Receives data from the socket. /// /// On success, returns the number of bytes read. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv(&self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } @@ -636,6 +682,7 @@ impl UnixDatagram { /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send_to>(&self, buf: &[u8], path: P) -> io::Result { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { unsafe { @@ -659,6 +706,7 @@ impl UnixDatagram { /// will return an error if the socket has not already been connected. /// /// On success, returns the number of bytes written. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -668,6 +716,7 @@ impl UnixDatagram { /// If the provided value is `None`, then `recv` and `recv_from` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) } @@ -677,26 +726,31 @@ impl UnixDatagram { /// If the provided value is `None`, then `send` and `send_to` calls will /// block indefinitely. It is an error to pass the zero `Duration` to this /// method. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() } @@ -706,23 +760,27 @@ impl UnixDatagram { /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value /// (see the documentation of `Shutdown`). + #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl AsRawFd for UnixDatagram { fn as_raw_fd(&self) -> RawFd { *self.0.as_inner() } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl FromRawFd for UnixDatagram { unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { UnixDatagram(Socket::from_inner(fd)) } } +#[stable(feature = "unix_socket", since = "1.10.0")] impl IntoRawFd for UnixDatagram { fn into_raw_fd(self) -> RawFd { self.0.into_inner() diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0969a59ea4338..7f23ae53fcd1a 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -100,31 +100,6 @@ impl FileAttr { } } -#[cfg(any(target_os = "ios", target_os = "macos"))] -// FIXME: update SystemTime to store a timespec and don't lose precision -impl FileAttr { - pub fn modified(&self) -> io::Result { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_mtime, - tv_usec: (self.stat.st_mtime_nsec / 1000) as libc::suseconds_t, - })) - } - - pub fn accessed(&self) -> io::Result { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_atime, - tv_usec: (self.stat.st_atime_nsec / 1000) as libc::suseconds_t, - })) - } - - pub fn created(&self) -> io::Result { - Ok(SystemTime::from(libc::timeval { - tv_sec: self.stat.st_birthtime, - tv_usec: (self.stat.st_birthtime_nsec / 1000) as libc::suseconds_t, - })) - } -} - #[cfg(target_os = "netbsd")] impl FileAttr { pub fn modified(&self) -> io::Result { @@ -149,7 +124,7 @@ impl FileAttr { } } -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))] +#[cfg(not(target_os = "netbsd"))] impl FileAttr { pub fn modified(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { @@ -167,7 +142,9 @@ impl FileAttr { #[cfg(any(target_os = "bitrig", target_os = "freebsd", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "macos", + target_os = "ios"))] pub fn created(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_birthtime as libc::time_t, @@ -177,7 +154,9 @@ impl FileAttr { #[cfg(not(any(target_os = "bitrig", target_os = "freebsd", - target_os = "openbsd")))] + target_os = "openbsd", + target_os = "macos", + target_os = "ios")))] pub fn created(&self) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "creation time is not available on this platform \ diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 94ebbd70ae83d..21ce6b19ceb13 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -27,13 +27,13 @@ use path::{self, PathBuf}; use ptr; use slice; use str; -use sync::StaticMutex; +use sys_common::mutex::Mutex; use sys::cvt; use sys::fd; use vec; const TMPBUF_SZ: usize = 128; -static ENV_LOCK: StaticMutex = StaticMutex::new(); +static ENV_LOCK: Mutex = Mutex::new(); /// Returns the platform-specific value of errno #[cfg(not(target_os = "dragonfly"))] @@ -434,10 +434,11 @@ pub unsafe fn environ() -> *mut *const *const c_char { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - let _g = ENV_LOCK.lock(); - return unsafe { + unsafe { + ENV_LOCK.lock(); let mut environ = *environ(); if environ == ptr::null() { + ENV_LOCK.unlock(); panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error()); } @@ -448,8 +449,13 @@ pub fn env() -> Env { } environ = environ.offset(1); } - Env { iter: result.into_iter(), _dont_send_or_sync_me: ptr::null_mut() } - }; + let ret = Env { + iter: result.into_iter(), + _dont_send_or_sync_me: ptr::null_mut(), + }; + ENV_LOCK.unlock(); + return ret + } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { // Strategy (copied from glibc): Variable name and value are separated @@ -471,32 +477,40 @@ pub fn getenv(k: &OsStr) -> io::Result> { // environment variables with a nul byte can't be set, so their value is // always None as well let k = CString::new(k.as_bytes())?; - let _g = ENV_LOCK.lock(); - Ok(unsafe { + unsafe { + ENV_LOCK.lock(); let s = libc::getenv(k.as_ptr()) as *const _; - if s.is_null() { + let ret = if s.is_null() { None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) - } - }) + }; + ENV_LOCK.unlock(); + return Ok(ret) + } } pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let k = CString::new(k.as_bytes())?; let v = CString::new(v.as_bytes())?; - let _g = ENV_LOCK.lock(); - cvt(unsafe { - libc::setenv(k.as_ptr(), v.as_ptr(), 1) - }).map(|_| ()) + + unsafe { + ENV_LOCK.lock(); + let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()); + ENV_LOCK.unlock(); + return ret + } } pub fn unsetenv(n: &OsStr) -> io::Result<()> { let nbuf = CString::new(n.as_bytes())?; - let _g = ENV_LOCK.lock(); - cvt(unsafe { - libc::unsetenv(nbuf.as_ptr()) - }).map(|_| ()) + + unsafe { + ENV_LOCK.lock(); + let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ()); + ENV_LOCK.unlock(); + return ret + } } pub fn page_size() -> usize { diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index cc7abe25e35e5..68eebba9e7b90 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -8,37 +8,129 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cmp::Ordering; +use time::Duration; +use libc; + pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; const NSEC_PER_SEC: u64 = 1_000_000_000; +#[derive(Copy, Clone)] +struct Timespec { + t: libc::timespec, +} + +impl Timespec { + fn sub_timespec(&self, other: &Timespec) -> Result { + if self >= other { + Ok(if self.t.tv_nsec >= other.t.tv_nsec { + Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, + (self.t.tv_nsec - other.t.tv_nsec) as u32) + } else { + Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, + self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - + other.t.tv_nsec as u32) + }) + } else { + match other.sub_timespec(self) { + Ok(d) => Err(d), + Err(d) => Ok(d), + } + } + } + + fn add_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); + let mut secs = secs.expect("overflow when adding duration to time"); + + // Nano calculations can't overflow because nanos are <1B which fit + // in a u32. + let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; + if nsec >= NSEC_PER_SEC as u32 { + nsec -= NSEC_PER_SEC as u32; + secs = secs.checked_add(1).expect("overflow when adding \ + duration to time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as libc::c_long, + }, + } + } + + fn sub_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); + let mut secs = secs.expect("overflow when subtracting duration \ + from time"); + + // Similar to above, nanos can't overflow. + let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; + if nsec < 0 { + nsec += NSEC_PER_SEC as i32; + secs = secs.checked_sub(1).expect("overflow when subtracting \ + duration from time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as libc::c_long, + }, + } + } +} + +impl PartialEq for Timespec { + fn eq(&self, other: &Timespec) -> bool { + self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec + } +} + +impl Eq for Timespec {} + +impl PartialOrd for Timespec { + fn partial_cmp(&self, other: &Timespec) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Timespec { + fn cmp(&self, other: &Timespec) -> Ordering { + let me = (self.t.tv_sec, self.t.tv_nsec); + let other = (other.t.tv_sec, other.t.tv_nsec); + me.cmp(&other) + } +} + #[cfg(any(target_os = "macos", target_os = "ios"))] mod inner { - use cmp::Ordering; use fmt; use libc; - use super::NSEC_PER_SEC; use sync::Once; use sys::cvt; use sys_common::mul_div_u64; use time::Duration; - const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000; + use super::NSEC_PER_SEC; + use super::Timespec; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Instant { t: u64 } - #[derive(Copy, Clone)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct SystemTime { - t: libc::timeval, + t: Timespec, } pub const UNIX_EPOCH: SystemTime = SystemTime { - t: libc::timeval { - tv_sec: 0, - tv_usec: 0, + t: Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, + }, }, }; @@ -72,113 +164,50 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { - let mut s = SystemTime { - t: libc::timeval { - tv_sec: 0, - tv_usec: 0, - }, + let mut s = libc::timeval { + tv_sec: 0, + tv_usec: 0, }; cvt(unsafe { - libc::gettimeofday(&mut s.t, 0 as *mut _) + libc::gettimeofday(&mut s, 0 as *mut _) }).unwrap(); - return s + return SystemTime::from(s) } pub fn sub_time(&self, other: &SystemTime) -> Result { - if self >= other { - Ok(if self.t.tv_usec >= other.t.tv_usec { - Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, - ((self.t.tv_usec - - other.t.tv_usec) as u32) * 1000) - } else { - Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, - (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) - - other.t.tv_usec as u32) * 1000) - }) - } else { - match other.sub_time(self) { - Ok(d) => Err(d), - Err(d) => Ok(d), - } - } + self.t.sub_timespec(&other.t) } pub fn add_duration(&self, other: &Duration) -> SystemTime { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); - - // Nano calculations can't overflow because nanos are <1B which fit - // in a u32. - let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32; - if usec >= USEC_PER_SEC as u32 { - usec -= USEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); - } - SystemTime { - t: libc::timeval { - tv_sec: secs as libc::time_t, - tv_usec: usec as libc::suseconds_t, - }, - } + SystemTime { t: self.t.add_duration(other) } } pub fn sub_duration(&self, other: &Duration) -> SystemTime { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); - - // Similar to above, nanos can't overflow. - let mut usec = self.t.tv_usec as i32 - - (other.subsec_nanos() / 1000) as i32; - if usec < 0 { - usec += USEC_PER_SEC as i32; - secs = secs.checked_sub(1).expect("overflow when subtracting \ - duration from time"); - } - SystemTime { - t: libc::timeval { - tv_sec: secs as libc::time_t, - tv_usec: usec as libc::suseconds_t, - }, - } + SystemTime { t: self.t.sub_duration(other) } } } impl From for SystemTime { fn from(t: libc::timeval) -> SystemTime { - SystemTime { t: t } - } - } - - impl PartialEq for SystemTime { - fn eq(&self, other: &SystemTime) -> bool { - self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec - } - } - - impl Eq for SystemTime {} - - impl PartialOrd for SystemTime { - fn partial_cmp(&self, other: &SystemTime) -> Option { - Some(self.cmp(other)) + SystemTime::from(libc::timespec { + tv_sec: t.tv_sec, + tv_nsec: (t.tv_usec * 1000) as libc::c_long, + }) } } - impl Ord for SystemTime { - fn cmp(&self, other: &SystemTime) -> Ordering { - let me = (self.t.tv_sec, self.t.tv_usec); - let other = (other.t.tv_sec, other.t.tv_usec); - me.cmp(&other) + impl From for SystemTime { + fn from(t: libc::timespec) -> SystemTime { + SystemTime { t: Timespec { t: t } } } } impl fmt::Debug for SystemTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SystemTime") - .field("tv_sec", &self.t.tv_sec) - .field("tv_usec", &self.t.tv_usec) + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) .finish() } } @@ -209,17 +238,12 @@ mod inner { #[cfg(not(any(target_os = "macos", target_os = "ios")))] mod inner { - use cmp::Ordering; use fmt; use libc; - use super::NSEC_PER_SEC; use sys::cvt; use time::Duration; - #[derive(Copy, Clone)] - struct Timespec { - t: libc::timespec, - } + use super::Timespec; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Instant { @@ -242,7 +266,7 @@ mod inner { impl Instant { pub fn now() -> Instant { - Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) } + Instant { t: now(libc::CLOCK_MONOTONIC) } } pub fn sub_instant(&self, other: &Instant) -> Duration { @@ -271,7 +295,7 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { - SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } + SystemTime { t: now(libc::CLOCK_REALTIME) } } pub fn sub_time(&self, other: &SystemTime) @@ -308,98 +332,16 @@ mod inner { #[cfg(target_os = "dragonfly")] pub type clock_t = libc::c_ulong; - impl Timespec { - pub fn now(clock: clock_t) -> Timespec { - let mut t = Timespec { - t: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - } - }; - cvt(unsafe { - libc::clock_gettime(clock, &mut t.t) - }).unwrap(); - t - } - - fn sub_timespec(&self, other: &Timespec) -> Result { - if self >= other { - Ok(if self.t.tv_nsec >= other.t.tv_nsec { - Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, - (self.t.tv_nsec - other.t.tv_nsec) as u32) - } else { - Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, - self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - - other.t.tv_nsec as u32) - }) - } else { - match other.sub_timespec(self) { - Ok(d) => Err(d), - Err(d) => Ok(d), - } - } - } - - fn add_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); - let mut secs = secs.expect("overflow when adding duration to time"); - - // Nano calculations can't overflow because nanos are <1B which fit - // in a u32. - let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; - if nsec >= NSEC_PER_SEC as u32 { - nsec -= NSEC_PER_SEC as u32; - secs = secs.checked_add(1).expect("overflow when adding \ - duration to time"); - } - Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, - }, - } - } - - fn sub_duration(&self, other: &Duration) -> Timespec { - let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); - let mut secs = secs.expect("overflow when subtracting duration \ - from time"); - - // Similar to above, nanos can't overflow. - let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; - if nsec < 0 { - nsec += NSEC_PER_SEC as i32; - secs = secs.checked_sub(1).expect("overflow when subtracting \ - duration from time"); - } - Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, - tv_nsec: nsec as libc::c_long, - }, + fn now(clock: clock_t) -> Timespec { + let mut t = Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, } - } - } - - impl PartialEq for Timespec { - fn eq(&self, other: &Timespec) -> bool { - self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec - } - } - - impl Eq for Timespec {} - - impl PartialOrd for Timespec { - fn partial_cmp(&self, other: &Timespec) -> Option { - Some(self.cmp(other)) - } - } - - impl Ord for Timespec { - fn cmp(&self, other: &Timespec) -> Ordering { - let me = (self.t.tv_sec, self.t.tv_nsec); - let other = (other.t.tv_sec, other.t.tv_nsec); - me.cmp(&other) - } + }; + cvt(unsafe { + libc::clock_gettime(clock, &mut t.t) + }).unwrap(); + t } } diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index d378a6853f3c7..4388a0bdff2cf 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -19,9 +19,7 @@ use sys; use sys_common::{AsInnerMut, AsInner}; /// Windows-specific extensions to `OpenOptions` -#[unstable(feature = "open_options_ext", - reason = "may require more thought/methods", - issue = "27720")] +#[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile` /// with the specified value. @@ -34,7 +32,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// #![feature(open_options_ext)] /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; /// @@ -42,6 +39,7 @@ pub trait OpenOptionsExt { /// // to call `stat()` on the file /// let file = OpenOptions::new().access_mode(0).open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn access_mode(&mut self, access: u32) -> &mut Self; /// Overrides the `dwShareMode` argument to the call to `CreateFile` with @@ -55,7 +53,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// #![feature(open_options_ext)] /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; /// @@ -65,6 +62,7 @@ pub trait OpenOptionsExt { /// .share_mode(0) /// .open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn share_mode(&mut self, val: u32) -> &mut Self; /// Sets extra flags for the `dwFileFlags` argument to the call to @@ -88,9 +86,7 @@ pub trait OpenOptionsExt { /// } /// let file = options.open("foo.txt"); /// ``` - #[unstable(feature = "expand_open_options", - reason = "recently added", - issue = "30014")] + #[stable(feature = "open_options_ext", since = "1.10.0")] fn custom_flags(&mut self, flags: u32) -> &mut Self; /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to @@ -111,7 +107,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```rust,ignore - /// #![feature(open_options_ext)] /// extern crate winapi; /// use std::fs::OpenOptions; /// use std::os::windows::fs::OpenOptionsExt; @@ -120,17 +115,17 @@ pub trait OpenOptionsExt { /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN) /// .open("foo.txt"); /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] fn attributes(&mut self, val: u32) -> &mut Self; /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to /// the specified value (or combines it with `custom_flags` and `attributes` /// to set the `dwFlagsAndAttributes` for `CreateFile`). + #[stable(feature = "open_options_ext", since = "1.10.0")] fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions; } -#[unstable(feature = "open_options_ext", - reason = "may require more thought/methods", - issue = "27720")] +#[stable(feature = "open_options_ext", since = "1.10.0")] impl OpenOptionsExt for OpenOptions { fn access_mode(&mut self, access: u32) -> &mut OpenOptions { self.as_inner_mut().access_mode(access); self diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index a0ad866c69d41..3ca75cf364376 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -24,7 +24,7 @@ use mem; use os::windows::ffi::OsStrExt; use path::Path; use ptr; -use sync::StaticMutex; +use sys::mutex::Mutex; use sys::c; use sys::fs::{OpenOptions, File}; use sys::handle::Handle; @@ -75,6 +75,10 @@ pub struct StdioPipes { pub stderr: Option, } +struct DropGuard<'a> { + lock: &'a Mutex, +} + impl Command { pub fn new(program: &OsStr) -> Command { Command { @@ -173,8 +177,8 @@ impl Command { // // For more information, msdn also has an article about this race: // http://support.microsoft.com/kb/315939 - static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); - let _lock = CREATE_PROCESS_LOCK.lock(); + static CREATE_PROCESS_LOCK: Mutex = Mutex::new(); + let _guard = DropGuard::new(&CREATE_PROCESS_LOCK); let mut pipes = StdioPipes { stdin: None, @@ -224,6 +228,23 @@ impl fmt::Debug for Command { } } +impl<'a> DropGuard<'a> { + fn new(lock: &'a Mutex) -> DropGuard<'a> { + unsafe { + lock.lock(); + DropGuard { lock: lock } + } + } +} + +impl<'a> Drop for DropGuard<'a> { + fn drop(&mut self) { + unsafe { + self.lock.unlock(); + } + } +} + impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d9409d3bbd921..c8ded115db864 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -15,7 +15,7 @@ pub use self::UnsafeSource::*; pub use self::ViewPath_::*; pub use self::PathParameters::*; -use attr::ThinAttributes; +use attr::{ThinAttributes, HasAttrs}; use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId}; use abi::Abi; use errors; @@ -567,7 +567,7 @@ impl Pat { PatKind::Struct(_, ref fields, _) => { fields.iter().all(|field| field.node.pat.walk(it)) } - PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => { + PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { s.iter().all(|p| p.walk(it)) } PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { @@ -582,7 +582,6 @@ impl Pat { PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::Ident(_, _, _) | - PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(_, _) | PatKind::Mac(_) => { @@ -631,9 +630,10 @@ pub enum PatKind { /// The `bool` is `true` in the presence of a `..`. Struct(Path, Vec>, bool), - /// A tuple struct/variant pattern `Variant(x, y, z)`. - /// "None" means a `Variant(..)` pattern where we don't bind the fields to names. - TupleStruct(Path, Option>>), + /// A tuple struct/variant pattern `Variant(x, y, .., z)`. + /// If the `..` pattern fragment is present, then `Option` denotes its position. + /// 0 <= position <= subpats.len() + TupleStruct(Path, Vec>, Option), /// A path pattern. /// Such pattern can be resolved to a unit struct/variant or a constant. @@ -645,8 +645,10 @@ pub enum PatKind { /// PatKind::Path, and the resolver will have to sort that out. QPath(QSelf, Path), - /// A tuple pattern `(a, b)` - Tup(Vec>), + /// A tuple pattern `(a, b)`. + /// If the `..` pattern fragment is present, then `Option` denotes its position. + /// 0 <= position <= subpats.len() + Tuple(Vec>, Option), /// A `box` pattern Box(P), /// A reference pattern, e.g. `&mut (a, b)` @@ -829,13 +831,7 @@ impl StmtKind { } pub fn attrs(&self) -> &[Attribute] { - match *self { - StmtKind::Decl(ref d, _) => d.attrs(), - StmtKind::Expr(ref e, _) | - StmtKind::Semi(ref e, _) => e.attrs(), - StmtKind::Mac(_, _, Some(ref b)) => b, - StmtKind::Mac(_, _, None) => &[], - } + HasAttrs::attrs(self) } } @@ -868,10 +864,7 @@ pub struct Local { impl Local { pub fn attrs(&self) -> &[Attribute] { - match self.attrs { - Some(ref b) => b, - None => &[], - } + HasAttrs::attrs(self) } } @@ -887,10 +880,7 @@ pub enum DeclKind { impl Decl { pub fn attrs(&self) -> &[Attribute] { - match self.node { - DeclKind::Local(ref l) => l.attrs(), - DeclKind::Item(ref i) => i.attrs(), - } + HasAttrs::attrs(self) } } @@ -935,10 +925,7 @@ pub struct Expr { impl Expr { pub fn attrs(&self) -> &[Attribute] { - match self.attrs { - Some(ref b) => b, - None => &[], - } + HasAttrs::attrs(self) } } @@ -1007,23 +994,23 @@ pub enum ExprKind { /// A while loop, with an optional label /// /// `'label: while expr { block }` - While(P, P, Option), + While(P, P, Option), /// A while-let loop, with an optional label /// /// `'label: while let pat = expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - WhileLet(P, P, P, Option), + WhileLet(P, P, P, Option), /// A for loop, with an optional label /// /// `'label: for pat in expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - ForLoop(P, P, P, Option), + ForLoop(P, P, P, Option), /// Conditionless loop (can be exited with break, continue, or return) /// /// `'label: loop { block }` - Loop(P, Option), + Loop(P, Option), /// A `match` block. Match(P, Vec), /// A closure (for example, `move |a, b, c| {a + b + c}`) @@ -1387,7 +1374,6 @@ pub struct MethodSig { pub abi: Abi, pub decl: P, pub generics: Generics, - pub explicit_self: ExplicitSelf, } /// Represents an item declaration within a trait declaration, @@ -1638,6 +1624,8 @@ pub enum TyKind { /// TyKind::Infer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, + /// Inferred type of a `self` or `&self` argument in a method. + ImplicitSelf, // A macro in the type position. Mac(Mac), } @@ -1677,81 +1665,65 @@ pub struct Arg { pub id: NodeId, } -/// Represents the kind of 'self' associated with a method. -/// String representation of `Ident` here is always "self", but hygiene contexts may differ. +/// Alternative representation for `Arg`s describing `self` parameter of methods. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum SelfKind { - /// No self - Static, /// `self`, `mut self` - Value(Ident), + Value(Mutability), /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability, Ident), + Region(Option, Mutability), /// `self: TYPE`, `mut self: TYPE` - Explicit(P, Ident), + Explicit(P, Mutability), } pub type ExplicitSelf = Spanned; impl Arg { - #[unstable(feature = "rustc_private", issue = "27812")] - #[rustc_deprecated(since = "1.10.0", reason = "use `from_self` instead")] - pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg { - let path = Spanned{span:span,node:self_ident}; - Arg { - // HACK(eddyb) fake type for the self argument. - ty: P(Ty { - id: DUMMY_NODE_ID, - node: TyKind::Infer, - span: DUMMY_SP, - }), - pat: P(Pat { - id: DUMMY_NODE_ID, - node: PatKind::Ident(BindingMode::ByValue(mutability), path, None), - span: span - }), - id: DUMMY_NODE_ID - } - } - pub fn to_self(&self) -> Option { - if let PatKind::Ident(_, ident, _) = self.pat.node { + if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { if ident.node.name == keywords::SelfValue.name() { return match self.ty.node { - TyKind::Infer => Some(respan(self.pat.span, SelfKind::Value(ident.node))), - TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::Infer => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl, ident.node))) + TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), + TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::ImplicitSelf => { + Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi), - SelfKind::Explicit(self.ty.clone(), ident.node))), + SelfKind::Explicit(self.ty.clone(), mutbl))), } } } None } - pub fn from_self(eself: ExplicitSelf, ident_sp: Span, mutbl: Mutability) -> Arg { - let pat = |ident, span| P(Pat { - id: DUMMY_NODE_ID, - node: PatKind::Ident(BindingMode::ByValue(mutbl), respan(ident_sp, ident), None), - span: span, - }); + pub fn is_self(&self) -> bool { + if let PatKind::Ident(_, ident, _) = self.pat.node { + ident.node.name == keywords::SelfValue.name() + } else { + false + } + } + + pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg { let infer_ty = P(Ty { id: DUMMY_NODE_ID, - node: TyKind::Infer, + node: TyKind::ImplicitSelf, span: DUMMY_SP, }); - let arg = |ident, ty, span| Arg { - pat: pat(ident, span), + let arg = |mutbl, ty, span| Arg { + pat: P(Pat { + id: DUMMY_NODE_ID, + node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), + span: span, + }), ty: ty, id: DUMMY_NODE_ID, }; match eself.node { - SelfKind::Static => panic!("bug: `Arg::from_self` is called \ - with `SelfKind::Static` argument"), - SelfKind::Explicit(ty, ident) => arg(ident, ty, mk_sp(eself.span.lo, ident_sp.hi)), - SelfKind::Value(ident) => arg(ident, infer_ty, eself.span), - SelfKind::Region(lt, mutbl, ident) => arg(ident, P(Ty { + SelfKind::Explicit(ty, mutbl) => { + arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi)) + } + SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span), + SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }), span: DUMMY_SP, @@ -1768,6 +1740,15 @@ pub struct FnDecl { pub variadic: bool } +impl FnDecl { + pub fn get_self(&self) -> Option { + self.inputs.get(0).and_then(Arg::to_self) + } + pub fn has_self(&self) -> bool { + self.inputs.get(0).map(Arg::is_self).unwrap_or(false) + } +} + #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Unsafety { Unsafe, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 8761ca3717895..c3c3deea1877f 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -884,82 +884,109 @@ impl AttributesExt for Vec { } } +pub trait HasAttrs: Sized { + fn attrs(&self) -> &[ast::Attribute]; + fn map_attrs) -> Vec>(self, f: F) -> Self; +} + /// A cheap way to add Attributes to an AST node. pub trait WithAttrs { // FIXME: Could be extended to anything IntoIter fn with_attrs(self, attrs: ThinAttributes) -> Self; } -impl WithAttrs for P { +impl WithAttrs for T { fn with_attrs(self, attrs: ThinAttributes) -> Self { - self.map(|mut e| { - e.attrs.update(|a| a.append(attrs)); - e + self.map_attrs(|mut orig_attrs| { + orig_attrs.extend(attrs.into_attr_vec()); + orig_attrs }) } } -impl WithAttrs for P { - fn with_attrs(self, attrs: ThinAttributes) -> Self { - self.map(|Item { ident, attrs: mut ats, id, node, vis, span }| { - ats.extend(attrs.into_attr_vec()); - Item { - ident: ident, - attrs: ats, - id: id, - node: node, - vis: vis, - span: span, - } - }) +impl HasAttrs for Vec { + fn attrs(&self) -> &[Attribute] { + &self + } + fn map_attrs) -> Vec>(self, f: F) -> Self { + f(self) } } -impl WithAttrs for P { - fn with_attrs(self, attrs: ThinAttributes) -> Self { - self.map(|Local { pat, ty, init, id, span, attrs: mut ats }| { - ats.update(|a| a.append(attrs)); - Local { - pat: pat, - ty: ty, - init: init, - id: id, - span: span, - attrs: ats, - } - }) +impl HasAttrs for ThinAttributes { + fn attrs(&self) -> &[Attribute] { + self.as_attr_slice() + } + fn map_attrs) -> Vec>(self, f: F) -> Self { + self.map_thin_attrs(f) } } -impl WithAttrs for P { - fn with_attrs(self, attrs: ThinAttributes) -> Self { - self.map(|Spanned { span, node }| { - Spanned { - span: span, - node: match node { - DeclKind::Local(local) => DeclKind::Local(local.with_attrs(attrs)), - DeclKind::Item(item) => DeclKind::Item(item.with_attrs(attrs)), - } - } - }) +impl HasAttrs for P { + fn attrs(&self) -> &[Attribute] { + (**self).attrs() + } + fn map_attrs) -> Vec>(self, f: F) -> Self { + self.map(|t| t.map_attrs(f)) } } -impl WithAttrs for P { - fn with_attrs(self, attrs: ThinAttributes) -> Self { - self.map(|Spanned { span, node }| { - Spanned { - span: span, - node: match node { - StmtKind::Decl(decl, id) => StmtKind::Decl(decl.with_attrs(attrs), id), - StmtKind::Expr(expr, id) => StmtKind::Expr(expr.with_attrs(attrs), id), - StmtKind::Semi(expr, id) => StmtKind::Semi(expr.with_attrs(attrs), id), - StmtKind::Mac(mac, style, mut ats) => { - ats.update(|a| a.append(attrs)); - StmtKind::Mac(mac, style, ats) - } - }, - } - }) +impl HasAttrs for DeclKind { + fn attrs(&self) -> &[Attribute] { + match *self { + DeclKind::Local(ref local) => local.attrs(), + DeclKind::Item(ref item) => item.attrs(), + } + } + + fn map_attrs) -> Vec>(self, f: F) -> Self { + match self { + DeclKind::Local(local) => DeclKind::Local(local.map_attrs(f)), + DeclKind::Item(item) => DeclKind::Item(item.map_attrs(f)), + } } } + +impl HasAttrs for StmtKind { + fn attrs(&self) -> &[Attribute] { + match *self { + StmtKind::Decl(ref decl, _) => decl.attrs(), + StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => expr.attrs(), + StmtKind::Mac(_, _, ref attrs) => attrs.attrs(), + } + } + + fn map_attrs) -> Vec>(self, f: F) -> Self { + match self { + StmtKind::Decl(decl, id) => StmtKind::Decl(decl.map_attrs(f), id), + StmtKind::Expr(expr, id) => StmtKind::Expr(expr.map_attrs(f), id), + StmtKind::Semi(expr, id) => StmtKind::Semi(expr.map_attrs(f), id), + StmtKind::Mac(mac, style, attrs) => + StmtKind::Mac(mac, style, attrs.map_attrs(f)), + } + } +} + +macro_rules! derive_has_attrs_from_field { + ($($ty:path),*) => { derive_has_attrs_from_field!($($ty: .attrs),*); }; + ($($ty:path : $(.$field:ident)*),*) => { $( + impl HasAttrs for $ty { + fn attrs(&self) -> &[Attribute] { + self $(.$field)* .attrs() + } + + fn map_attrs(mut self, f: F) -> Self + where F: FnOnce(Vec) -> Vec, + { + self $(.$field)* = self $(.$field)* .map_attrs(f); + self + } + } + )* } +} + +derive_has_attrs_from_field! { + Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm +} + +derive_has_attrs_from_field! { Decl: .node, Stmt: .node, ast::Variant: .node.attrs } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index ca8708fdc8326..d391cd0be7b12 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -1191,13 +1191,13 @@ impl CodeMap { } } - pub fn get_filemap(&self, filename: &str) -> Rc { + pub fn get_filemap(&self, filename: &str) -> Option> { for fm in self.files.borrow().iter() { if filename == fm.name { - return fm.clone(); + return Some(fm.clone()); } } - panic!("asking for {} which we don't know about", filename); + None } /// For a global BytePos compute the local offset within the containing FileMap @@ -1258,31 +1258,6 @@ impl CodeMap { return a; } - /// Check if the backtrace `subtrace` contains `suptrace` as a prefix. - pub fn more_specific_trace(&self, - mut subtrace: ExpnId, - suptrace: ExpnId) - -> bool { - loop { - if subtrace == suptrace { - return true; - } - - let stop = self.with_expn_info(subtrace, |opt_expn_info| { - if let Some(expn_info) = opt_expn_info { - subtrace = expn_info.call_site.expn_id; - false - } else { - true - } - }); - - if stop { - return false; - } - } - } - pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId { let mut expansions = self.expansions.borrow_mut(); expansions.push(expn_info); diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 4554a280e5f19..14035d8d116a3 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -8,326 +8,76 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use attr::AttrMetaMethods; +use attr::{AttrMetaMethods, HasAttrs}; use errors::Handler; use feature_gate::GatedCfgAttr; use fold::Folder; use {ast, fold, attr}; -use visit; use codemap::{Spanned, respan}; use ptr::P; use util::small_vector::SmallVector; -/// A folder that strips out items that do not belong in the current -/// configuration. -struct Context<'a, F> where F: FnMut(&[ast::Attribute]) -> bool { - in_cfg: F, - diagnostic: &'a Handler, -} +pub trait CfgFolder: fold::Folder { + // Check if a node with the given attributes is in this configuration. + fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool; -// Support conditional compilation by transforming the AST, stripping out -// any items that do not belong in the current configuration -pub fn strip_unconfigured_items(diagnostic: &Handler, krate: ast::Crate, - feature_gated_cfgs: &mut Vec) - -> ast::Crate -{ - // Need to do this check here because cfg runs before feature_gates - check_for_gated_stmt_expr_attributes(&krate, feature_gated_cfgs); - - let krate = process_cfg_attr(diagnostic, krate, feature_gated_cfgs); - let config = krate.config.clone(); - strip_items(diagnostic, - krate, - |attrs| { - let mut diag = CfgDiagReal { - diag: diagnostic, - feature_gated_cfgs: feature_gated_cfgs, - }; - in_cfg(&config, attrs, &mut diag) - }) -} + // Update a node before checking if it is in this configuration (used to implement `cfg_attr`). + fn process_attrs(&mut self, node: T) -> T { node } -impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) -> bool { - fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod { - fold_foreign_mod(self, foreign_mod) - } - fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind { - fold_item_kind(self, item) - } - fn fold_expr(&mut self, expr: P) -> P { - // If an expr is valid to cfg away it will have been removed by the - // outer stmt or expression folder before descending in here. - // Anything else is always required, and thus has to error out - // in case of a cfg attr. - // - // NB: This is intentionally not part of the fold_expr() function - // in order for fold_opt_expr() to be able to avoid this check - if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { - self.diagnostic.span_err(attr.span, - "removing an expression is not supported in this position"); - } - fold_expr(self, expr) - } - fn fold_opt_expr(&mut self, expr: P) -> Option> { - fold_opt_expr(self, expr) - } - fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { - fold_stmt(self, stmt) - } - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } - fn fold_item(&mut self, item: P) -> SmallVector> { - fold_item(self, item) - } -} + // Visit attributes on expression and statements (but not attributes on items in blocks). + fn visit_stmt_or_expr_attrs(&mut self, _attrs: &[ast::Attribute]) {} -pub fn strip_items<'a, F>(diagnostic: &'a Handler, - krate: ast::Crate, in_cfg: F) -> ast::Crate where - F: FnMut(&[ast::Attribute]) -> bool, -{ - let mut ctxt = Context { - in_cfg: in_cfg, - diagnostic: diagnostic, - }; - ctxt.fold_crate(krate) -} + // Visit unremovable (non-optional) expressions -- c.f. `fold_expr` vs `fold_opt_expr`. + fn visit_unremovable_expr(&mut self, _expr: &ast::Expr) {} -fn filter_foreign_item(cx: &mut Context, - item: ast::ForeignItem) - -> Option where - F: FnMut(&[ast::Attribute]) -> bool -{ - if foreign_item_in_cfg(cx, &item) { - Some(item) - } else { - None + fn configure(&mut self, node: T) -> Option { + let node = self.process_attrs(node); + if self.in_cfg(node.attrs()) { Some(node) } else { None } } } -fn fold_foreign_mod(cx: &mut Context, - ast::ForeignMod {abi, items}: ast::ForeignMod) - -> ast::ForeignMod where - F: FnMut(&[ast::Attribute]) -> bool -{ - ast::ForeignMod { - abi: abi, - items: items.into_iter() - .filter_map(|a| filter_foreign_item(cx, a)) - .collect() - } -} - -fn fold_item(cx: &mut Context, item: P) -> SmallVector> where - F: FnMut(&[ast::Attribute]) -> bool -{ - if item_in_cfg(cx, &item) { - SmallVector::one(item.map(|i| cx.fold_item_simple(i))) - } else { - SmallVector::zero() - } -} - -fn fold_item_kind(cx: &mut Context, item: ast::ItemKind) -> ast::ItemKind where - F: FnMut(&[ast::Attribute]) -> bool -{ - let item = match item { - ast::ItemKind::Impl(u, o, a, b, c, impl_items) => { - let impl_items = impl_items.into_iter() - .filter(|ii| (cx.in_cfg)(&ii.attrs)) - .collect(); - ast::ItemKind::Impl(u, o, a, b, c, impl_items) - } - ast::ItemKind::Trait(u, a, b, methods) => { - let methods = methods.into_iter() - .filter(|ti| (cx.in_cfg)(&ti.attrs)) - .collect(); - ast::ItemKind::Trait(u, a, b, methods) - } - ast::ItemKind::Struct(def, generics) => { - ast::ItemKind::Struct(fold_struct(cx, def), generics) - } - ast::ItemKind::Enum(def, generics) => { - let variants = def.variants.into_iter().filter_map(|v| { - if !(cx.in_cfg)(&v.node.attrs) { - None - } else { - Some(Spanned { - node: ast::Variant_ { - name: v.node.name, - attrs: v.node.attrs, - data: fold_struct(cx, v.node.data), - disr_expr: v.node.disr_expr, - }, - span: v.span - }) - } - }); - ast::ItemKind::Enum(ast::EnumDef { - variants: variants.collect(), - }, generics) - } - item => item, - }; - - fold::noop_fold_item_kind(item, cx) +/// A folder that strips out items that do not belong in the current +/// configuration. +pub struct StripUnconfigured<'a> { + diag: CfgDiagReal<'a, 'a>, + config: &'a ast::CrateConfig, } -fn fold_struct(cx: &mut Context, vdata: ast::VariantData) -> ast::VariantData where - F: FnMut(&[ast::Attribute]) -> bool -{ - match vdata { - ast::VariantData::Struct(fields, id) => { - ast::VariantData::Struct(fields.into_iter().filter(|m| { - (cx.in_cfg)(&m.attrs) - }).collect(), id) - } - ast::VariantData::Tuple(fields, id) => { - ast::VariantData::Tuple(fields.into_iter().filter(|m| { - (cx.in_cfg)(&m.attrs) - }).collect(), id) +impl<'a> StripUnconfigured<'a> { + pub fn new(config: &'a ast::CrateConfig, + diagnostic: &'a Handler, + feature_gated_cfgs: &'a mut Vec) + -> Self { + StripUnconfigured { + config: config, + diag: CfgDiagReal { diag: diagnostic, feature_gated_cfgs: feature_gated_cfgs }, } - ast::VariantData::Unit(id) => ast::VariantData::Unit(id) - } -} - -fn fold_opt_expr(cx: &mut Context, expr: P) -> Option> - where F: FnMut(&[ast::Attribute]) -> bool -{ - if expr_in_cfg(cx, &expr) { - Some(fold_expr(cx, expr)) - } else { - None - } -} - -fn fold_expr(cx: &mut Context, expr: P) -> P where - F: FnMut(&[ast::Attribute]) -> bool -{ - expr.map(|ast::Expr {id, span, node, attrs}| { - fold::noop_fold_expr(ast::Expr { - id: id, - node: match node { - ast::ExprKind::Match(m, arms) => { - ast::ExprKind::Match(m, arms.into_iter() - .filter(|a| (cx.in_cfg)(&a.attrs)) - .collect()) - } - _ => node - }, - span: span, - attrs: attrs, - }, cx) - }) -} - -fn fold_stmt(cx: &mut Context, stmt: ast::Stmt) -> SmallVector - where F: FnMut(&[ast::Attribute]) -> bool -{ - if stmt_in_cfg(cx, &stmt) { - fold::noop_fold_stmt(stmt, cx) - } else { - SmallVector::zero() } -} - -fn stmt_in_cfg(cx: &mut Context, stmt: &ast::Stmt) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - (cx.in_cfg)(stmt.node.attrs()) -} - -fn expr_in_cfg(cx: &mut Context, expr: &ast::Expr) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - (cx.in_cfg)(expr.attrs()) -} - -fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - return (cx.in_cfg)(&item.attrs); -} - -fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - return (cx.in_cfg)(&item.attrs); -} - -fn is_cfg(attr: &ast::Attribute) -> bool { - attr.check_name("cfg") -} - -// Determine if an item should be translated in the current crate -// configuration based on the item's attributes -fn in_cfg(cfg: &[P], - attrs: &[ast::Attribute], - diag: &mut T) -> bool { - attrs.iter().all(|attr| { - let mis = match attr.node.value.node { - ast::MetaItemKind::List(_, ref mis) if is_cfg(&attr) => mis, - _ => return true - }; - - if mis.len() != 1 { - diag.emit_error(|diagnostic| { - diagnostic.span_err(attr.span, "expected 1 cfg-pattern"); - }); - return true; - } - - attr::cfg_matches(cfg, &mis[0], diag) - }) -} -struct CfgAttrFolder<'a, T> { - diag: T, - config: &'a ast::CrateConfig, -} - -// Process `#[cfg_attr]`. -fn process_cfg_attr(diagnostic: &Handler, krate: ast::Crate, - feature_gated_cfgs: &mut Vec) -> ast::Crate { - let mut fld = CfgAttrFolder { - diag: CfgDiagReal { - diag: diagnostic, - feature_gated_cfgs: feature_gated_cfgs, - }, - config: &krate.config.clone(), - }; - fld.fold_crate(krate) -} - -impl<'a, T: CfgDiag> fold::Folder for CfgAttrFolder<'a, T> { - fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option { if !attr.check_name("cfg_attr") { - return fold::noop_fold_attribute(attr, self); + return Some(attr); } let attr_list = match attr.meta_item_list() { Some(attr_list) => attr_list, None => { - self.diag.emit_error(|diag| { - diag.span_err(attr.span, - "expected `#[cfg_attr(, )]`"); - }); + let msg = "expected `#[cfg_attr(, )]`"; + self.diag.diag.span_err(attr.span, msg); return None; } }; let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) { (2, Some(cfg), Some(mi)) => (cfg, mi), _ => { - self.diag.emit_error(|diag| { - diag.span_err(attr.span, - "expected `#[cfg_attr(, )]`"); - }); + let msg = "expected `#[cfg_attr(, )]`"; + self.diag.diag.span_err(attr.span, msg); return None; } }; - if attr::cfg_matches(&self.config[..], &cfg, &mut self.diag) { + if attr::cfg_matches(self.config, &cfg, &mut self.diag) { Some(respan(mi.span, ast::Attribute_ { id: attr::mk_attr_id(), style: attr.node.style, @@ -338,127 +88,187 @@ impl<'a, T: CfgDiag> fold::Folder for CfgAttrFolder<'a, T> { None } } - - // Need the ability to run pre-expansion. - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } } -fn check_for_gated_stmt_expr_attributes(krate: &ast::Crate, - discovered: &mut Vec) { - let mut v = StmtExprAttrFeatureVisitor { - config: &krate.config, - discovered: discovered, - }; - visit::walk_crate(&mut v, krate); -} - -/// To cover this feature, we need to discover all attributes -/// so we need to run before cfg. -struct StmtExprAttrFeatureVisitor<'a, 'b> { - config: &'a ast::CrateConfig, - discovered: &'b mut Vec, -} - -// Runs the cfg_attr and cfg folders locally in "silent" mode -// to discover attribute use on stmts or expressions ahead of time -impl<'v, 'a, 'b> visit::Visitor<'v> for StmtExprAttrFeatureVisitor<'a, 'b> { - fn visit_stmt(&mut self, s: &'v ast::Stmt) { - // check if there even are any attributes on this node - let stmt_attrs = s.node.attrs(); - if stmt_attrs.len() > 0 { - // attributes on items are fine - if let ast::StmtKind::Decl(ref decl, _) = s.node { - if let ast::DeclKind::Item(_) = decl.node { - visit::walk_stmt(self, s); - return; - } - } - - // flag the offending attributes - for attr in stmt_attrs { - self.discovered.push(GatedCfgAttr::GatedAttr(attr.span)); +impl<'a> CfgFolder for StripUnconfigured<'a> { + // Determine if an item should be translated in the current crate + // configuration based on the item's attributes + fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { + attrs.iter().all(|attr| { + let mis = match attr.node.value.node { + ast::MetaItemKind::List(_, ref mis) if is_cfg(&attr) => mis, + _ => return true + }; + + if mis.len() != 1 { + self.diag.emit_error(|diagnostic| { + diagnostic.span_err(attr.span, "expected 1 cfg-pattern"); + }); + return true; } - // if the node does not end up being cfg-d away, walk down - if node_survives_cfg(stmt_attrs, self.config) { - visit::walk_stmt(self, s); - } - } else { - visit::walk_stmt(self, s); - } + attr::cfg_matches(self.config, &mis[0], &mut self.diag) + }) } - fn visit_expr(&mut self, ex: &'v ast::Expr) { - // check if there even are any attributes on this node - let expr_attrs = ex.attrs(); - if expr_attrs.len() > 0 { - - // flag the offending attributes - for attr in expr_attrs { - self.discovered.push(GatedCfgAttr::GatedAttr(attr.span)); - } + fn process_attrs(&mut self, node: T) -> T { + node.map_attrs(|attrs| { + attrs.into_iter().filter_map(|attr| self.process_cfg_attr(attr)).collect() + }) + } - // if the node does not end up being cfg-d away, walk down - if node_survives_cfg(expr_attrs, self.config) { - visit::walk_expr(self, ex); - } - } else { - visit::walk_expr(self, ex); + fn visit_stmt_or_expr_attrs(&mut self, attrs: &[ast::Attribute]) { + // flag the offending attributes + for attr in attrs.iter() { + self.diag.feature_gated_cfgs.push(GatedCfgAttr::GatedAttr(attr.span)); } } - fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { - if node_survives_cfg(&i.attrs, self.config) { - visit::walk_foreign_item(self, i); + fn visit_unremovable_expr(&mut self, expr: &ast::Expr) { + if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { + let msg = "removing an expression is not supported in this position"; + self.diag.diag.span_err(attr.span, msg); } } +} + +// Support conditional compilation by transforming the AST, stripping out +// any items that do not belong in the current configuration +pub fn strip_unconfigured_items(diagnostic: &Handler, krate: ast::Crate, + feature_gated_cfgs: &mut Vec) + -> ast::Crate +{ + let config = &krate.config.clone(); + StripUnconfigured::new(config, diagnostic, feature_gated_cfgs).fold_crate(krate) +} - fn visit_item(&mut self, i: &'v ast::Item) { - if node_survives_cfg(&i.attrs, self.config) { - visit::walk_item(self, i); +impl fold::Folder for T { + fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod { + ast::ForeignMod { + abi: foreign_mod.abi, + items: foreign_mod.items.into_iter().filter_map(|item| { + self.configure(item).map(|item| fold::noop_fold_foreign_item(item, self)) + }).collect(), } } - fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { - if node_survives_cfg(&ii.attrs, self.config) { - visit::walk_impl_item(self, ii); - } + fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind { + let fold_struct = |this: &mut Self, vdata| match vdata { + ast::VariantData::Struct(fields, id) => { + let fields = fields.into_iter().filter_map(|field| this.configure(field)); + ast::VariantData::Struct(fields.collect(), id) + } + ast::VariantData::Tuple(fields, id) => { + let fields = fields.into_iter().filter_map(|field| this.configure(field)); + ast::VariantData::Tuple(fields.collect(), id) + } + ast::VariantData::Unit(id) => ast::VariantData::Unit(id) + }; + + let item = match item { + ast::ItemKind::Impl(u, o, a, b, c, items) => { + let items = items.into_iter().filter_map(|item| self.configure(item)).collect(); + ast::ItemKind::Impl(u, o, a, b, c, items) + } + ast::ItemKind::Trait(u, a, b, items) => { + let items = items.into_iter().filter_map(|item| self.configure(item)).collect(); + ast::ItemKind::Trait(u, a, b, items) + } + ast::ItemKind::Struct(def, generics) => { + ast::ItemKind::Struct(fold_struct(self, def), generics) + } + ast::ItemKind::Enum(def, generics) => { + let variants = def.variants.into_iter().filter_map(|v| { + self.configure(v).map(|v| { + Spanned { + node: ast::Variant_ { + name: v.node.name, + attrs: v.node.attrs, + data: fold_struct(self, v.node.data), + disr_expr: v.node.disr_expr, + }, + span: v.span + } + }) + }); + ast::ItemKind::Enum(ast::EnumDef { + variants: variants.collect(), + }, generics) + } + item => item, + }; + + fold::noop_fold_item_kind(item, self) } - fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { - if node_survives_cfg(&ti.attrs, self.config) { - visit::walk_trait_item(self, ti); - } + fn fold_expr(&mut self, expr: P) -> P { + self.visit_stmt_or_expr_attrs(expr.attrs()); + // If an expr is valid to cfg away it will have been removed by the + // outer stmt or expression folder before descending in here. + // Anything else is always required, and thus has to error out + // in case of a cfg attr. + // + // NB: This is intentionally not part of the fold_expr() function + // in order for fold_opt_expr() to be able to avoid this check + self.visit_unremovable_expr(&expr); + let expr = self.process_attrs(expr); + fold_expr(self, expr) } - fn visit_struct_field(&mut self, s: &'v ast::StructField) { - if node_survives_cfg(&s.attrs, self.config) { - visit::walk_struct_field(self, s); - } + fn fold_opt_expr(&mut self, expr: P) -> Option> { + self.configure(expr).map(|expr| fold_expr(self, expr)) } - fn visit_variant(&mut self, v: &'v ast::Variant, - g: &'v ast::Generics, item_id: ast::NodeId) { - if node_survives_cfg(&v.node.attrs, self.config) { - visit::walk_variant(self, v, g, item_id); + fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { + let is_item = match stmt.node { + ast::StmtKind::Decl(ref decl, _) => match decl.node { + ast::DeclKind::Item(_) => true, + _ => false, + }, + _ => false, + }; + + // avoid calling `visit_stmt_or_expr_attrs` on items + if !is_item { + self.visit_stmt_or_expr_attrs(stmt.attrs()); } + + self.configure(stmt).map(|stmt| fold::noop_fold_stmt(stmt, self)) + .unwrap_or(SmallVector::zero()) } - fn visit_arm(&mut self, a: &'v ast::Arm) { - if node_survives_cfg(&a.attrs, self.config) { - visit::walk_arm(self, a); - } + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } - // This visitor runs pre expansion, so we need to prevent - // the default panic here - fn visit_mac(&mut self, mac: &'v ast::Mac) { - visit::walk_mac(self, mac) + fn fold_item(&mut self, item: P) -> SmallVector> { + self.configure(item).map(|item| SmallVector::one(item.map(|i| self.fold_item_simple(i)))) + .unwrap_or(SmallVector::zero()) } } +fn fold_expr(folder: &mut F, expr: P) -> P { + expr.map(|ast::Expr {id, span, node, attrs}| { + fold::noop_fold_expr(ast::Expr { + id: id, + node: match node { + ast::ExprKind::Match(m, arms) => { + ast::ExprKind::Match(m, arms.into_iter() + .filter_map(|a| folder.configure(a)) + .collect()) + } + _ => node + }, + span: span, + attrs: attrs, + }, folder) + }) +} + +fn is_cfg(attr: &ast::Attribute) -> bool { + attr.check_name("cfg") +} + pub trait CfgDiag { fn emit_error(&mut self, f: F) where F: FnMut(&Handler); fn flag_gated(&mut self, f: F) where F: FnMut(&mut Vec); @@ -477,41 +287,3 @@ impl<'a, 'b> CfgDiag for CfgDiagReal<'a, 'b> { f(self.feature_gated_cfgs) } } - -struct CfgDiagSilent { - error: bool, -} - -impl CfgDiag for CfgDiagSilent { - fn emit_error(&mut self, _: F) where F: FnMut(&Handler) { - self.error = true; - } - fn flag_gated(&mut self, _: F) where F: FnMut(&mut Vec) {} -} - -fn node_survives_cfg(attrs: &[ast::Attribute], - config: &ast::CrateConfig) -> bool { - let mut survives_cfg = true; - - for attr in attrs { - let mut fld = CfgAttrFolder { - diag: CfgDiagSilent { error: false }, - config: config, - }; - let attr = fld.fold_attribute(attr.clone()); - - // In case of error we can just return true, - // since the actual cfg folders will end compilation anyway. - - if fld.diag.error { return true; } - - survives_cfg &= attr.map(|attr| { - let mut diag = CfgDiagSilent { error: false }; - let r = in_cfg(config, &[attr], &mut diag); - if diag.error { return true; } - r - }).unwrap_or(true) - } - - survives_cfg -} diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index 7c9985d7d2331..6b15aa4f92c57 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -682,6 +682,7 @@ mod test { println!("r#\"\n{}\"#", str); assert_eq!(str, &r#" --> dummy.txt:11:1 + |> 11 |> e-lä-vän |> ^ "#[1..]); @@ -746,6 +747,7 @@ mod test { let expect_start = &r#" --> dummy.txt:1:6 + |> 1 |> _____aaaaaa____bbbbbb__cccccdd_ |> ^^^^^^ ^^^^^^ ^^^^^^^ "#[1..]; @@ -818,6 +820,7 @@ mod test { let expect0 = &r#" --> dummy.txt:5:1 + |> 5 |> ccccc |> ^ ... @@ -830,6 +833,7 @@ mod test { let expect = &r#" --> dummy.txt:1:1 + |> 1 |> aaaaa |> ^ ... diff --git a/src/libsyntax/errors/snippet/mod.rs b/src/libsyntax/errors/snippet/mod.rs index 188e676e7dff6..2a43a14ddf873 100644 --- a/src/libsyntax/errors/snippet/mod.rs +++ b/src/libsyntax/errors/snippet/mod.rs @@ -478,6 +478,13 @@ impl FileInfo { }], kind: RenderedLineKind::PrimaryFileName, }); + output.push(RenderedLine { + text: vec![StyledString { + text: "".to_string(), + style: Style::FileNameStyle, + }], + kind: RenderedLineKind::Annotations, + }); } None => { output.push(RenderedLine { @@ -487,6 +494,13 @@ impl FileInfo { }], kind: RenderedLineKind::OtherFileName, }); + output.push(RenderedLine { + text: vec![StyledString { + text: "".to_string(), + style: Style::FileNameStyle, + }], + kind: RenderedLineKind::Annotations, + }); } } } diff --git a/src/libsyntax/errors/snippet/test.rs b/src/libsyntax/errors/snippet/test.rs index 62ce3fa9dd5e9..51fe4572dbc63 100644 --- a/src/libsyntax/errors/snippet/test.rs +++ b/src/libsyntax/errors/snippet/test.rs @@ -98,6 +98,7 @@ fn foo() { let text = make_string(&lines); assert_eq!(&text[..], &" --> foo.rs:3:2 + |> 3 |> \tbar; |> \t^^^ "[1..]); @@ -130,6 +131,7 @@ fn foo() { println!("text=\n{}", text); assert_eq!(&text[..], &r#" ::: foo.rs + |> 3 |> vec.push(vec.pop().unwrap()); |> --- --- - previous borrow ends here |> | | @@ -199,12 +201,14 @@ fn bar() { // Note that the `|>` remain aligned across both files: assert_eq!(&text[..], &r#" --> foo.rs:3:14 + |> 3 |> vec.push(vec.pop().unwrap()); |> --- ^^^ - c |> | | |> | b |> a ::: bar.rs + |> 17 |> vec.push(); |> --- - f |> | @@ -249,6 +253,7 @@ fn foo() { println!("text=\n{}", text); assert_eq!(&text[..], &r#" ::: foo.rs + |> 3 |> let name = find_id(&data, 22).unwrap(); |> ---- immutable borrow begins here ... @@ -288,6 +293,7 @@ fn foo() { println!("text=r#\"\n{}\".trim_left()", text); assert_eq!(&text[..], &r#" ::: foo.rs + |> 3 |> vec.push(vec.pop().unwrap()); |> -------- ------ D |> || @@ -324,6 +330,7 @@ fn foo() { println!("text=r#\"\n{}\".trim_left()", text); assert_eq!(&text[..], &r#" ::: foo.rs + |> 3 |> vec.push(vec.pop().unwrap()); |> --- --- - previous borrow ends here |> | | @@ -362,6 +369,7 @@ fn foo() { println!("text=r#\"\n{}\".trim_left()", text); assert_eq!(&text[..], &r#" ::: foo.rs + |> 4 |> let mut vec2 = vec; |> --- `vec` moved here because it has type `collections::vec::Vec` ... @@ -398,6 +406,7 @@ fn foo() { println!("text=&r#\"\n{}\n\"#[1..]", text); assert_eq!(text, &r#" ::: foo.rs + |> 3 |> let mut vec = vec![0, 1, 2]; |> --- --- 4 |> let mut vec2 = vec; @@ -429,6 +438,7 @@ impl SomeTrait for () { println!("r#\"\n{}\"", text); assert_eq!(text, &r#" ::: foo.rs + |> 3 |> fn foo(x: u32) { |> - "#[1..]); @@ -458,6 +468,7 @@ fn span_overlap_label() { println!("r#\"\n{}\"", text); assert_eq!(text, &r#" ::: foo.rs + |> 2 |> fn foo(x: u32) { |> -------------- |> | | @@ -492,6 +503,7 @@ fn span_overlap_label2() { println!("r#\"\n{}\"", text); assert_eq!(text, &r#" ::: foo.rs + |> 2 |> fn foo(x: u32) { |> -------------- |> | | @@ -537,6 +549,7 @@ fn span_overlap_label3() { println!("r#\"\n{}\"", text); assert_eq!(text, &r#" ::: foo.rs + |> 3 |> let closure = || { |> - foo 4 |> inner @@ -577,6 +590,7 @@ fn main() { println!("r#\"\n{}\"", text); assert_eq!(text, &r#" --> foo.rs:11:2 + |> 11 |> } |> - "#[1..]); diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 7958162986cfc..3a1cdae9bfbd0 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -832,7 +832,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let pat = if subpats.is_empty() { PatKind::Path(path) } else { - PatKind::TupleStruct(path, Some(subpats)) + PatKind::TupleStruct(path, subpats, None) }; self.pat(span, pat) } @@ -842,7 +842,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat(span, pat) } fn pat_tuple(&self, span: Span, pats: Vec>) -> P { - self.pat(span, PatKind::Tup(pats)) + self.pat(span, PatKind::Tuple(pats, None)) } fn pat_some(&self, span: Span, pat: P) -> P { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f243706eecb80..c3202dbdbb49e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -9,16 +9,17 @@ // except according to those terms. use ast::{Block, Crate, DeclKind, PatKind}; -use ast::{Local, Ident, Mac_, Name}; +use ast::{Local, Ident, Mac_, Name, SpannedIdent}; use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind}; use ast::TokenTree; use ast; use ext::mtwt; use ext::build::AstBuilder; use attr; -use attr::{AttrMetaMethods, WithAttrs}; +use attr::{AttrMetaMethods, WithAttrs, ThinAttributesExt}; use codemap; -use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; +use codemap::{Span, Spanned, ExpnInfo, ExpnId, NameAndSpan, MacroBang, MacroAttribute}; +use config::StripUnconfigured; use ext::base::*; use feature_gate::{self, Features}; use fold; @@ -33,73 +34,78 @@ use visit::Visitor; use std_inject; use std::collections::HashSet; -use std::env; -// this function is called to detect use of feature-gated or invalid attributes -// on macro invoations since they will not be detected after macro expansion -fn check_attributes(attrs: &[ast::Attribute], fld: &MacroExpander) { - for attr in attrs.iter() { - feature_gate::check_attribute(&attr, &fld.cx.parse_sess.span_diagnostic, - &fld.cx.parse_sess.codemap(), - &fld.cx.ecfg.features.unwrap()); - } -} - -pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { - let expr_span = e.span; - return e.and_then(|ast::Expr {id, node, span, attrs}| match node { - - // expr_mac should really be expr_ext or something; it's the - // entry-point for all syntax extensions. - ast::ExprKind::Mac(mac) => { - if let Some(ref attrs) = attrs { - check_attributes(attrs, fld); - } +// A trait for AST nodes and AST node lists into which macro invocations may expand. +trait MacroGenerable: Sized { + // Expand the given MacResult using its appropriate `make_*` method. + fn make_with<'a>(result: Box) -> Option; - // Assert that we drop any macro attributes on the floor here - drop(attrs); + // Fold this node or list of nodes using the given folder. + fn fold_with(self, folder: &mut F) -> Self; - let expanded_expr = match expand_mac_invoc(mac, span, - |r| r.make_expr(), - mark_expr, fld) { - Some(expr) => expr, - None => { - return DummyResult::raw_expr(span); - } - }; + // Return a placeholder expansion to allow compilation to continue after an erroring expansion. + fn dummy(span: Span) -> Self; - // Keep going, outside-in. - let fully_expanded = fld.fold_expr(expanded_expr); - fld.cx.bt_pop(); + // The user-friendly name of the node type (e.g. "expression", "item", etc.) for diagnostics. + fn kind_name() -> &'static str; +} - fully_expanded +macro_rules! impl_macro_generable { + ($($ty:ty: $kind_name:expr, .$make:ident, $(.$fold:ident)* $(lift .$fold_elt:ident)*, + |$span:ident| $dummy:expr;)*) => { $( + impl MacroGenerable for $ty { + fn kind_name() -> &'static str { $kind_name } + fn make_with<'a>(result: Box) -> Option { result.$make() } + fn fold_with(self, folder: &mut F) -> Self { + $( folder.$fold(self) )* + $( self.into_iter().flat_map(|item| folder. $fold_elt (item)).collect() )* + } + fn dummy($span: Span) -> Self { $dummy } } + )* } +} - ast::ExprKind::InPlace(placer, value_expr) => { - // Ensure feature-gate is enabled - if !fld.cx.ecfg.features.unwrap().placement_in_syntax { - feature_gate::emit_feature_err( - &fld.cx.parse_sess.span_diagnostic, "placement_in_syntax", expr_span, - feature_gate::GateIssue::Language, feature_gate::EXPLAIN_PLACEMENT_IN - ); - } +impl_macro_generable! { + P: "expression", .make_expr, .fold_expr, |span| DummyResult::raw_expr(span); + P: "pattern", .make_pat, .fold_pat, |span| P(DummyResult::raw_pat(span)); + P: "type", .make_ty, .fold_ty, |span| DummyResult::raw_ty(span); + SmallVector: + "impl item", .make_impl_items, lift .fold_impl_item, |_span| SmallVector::zero(); + SmallVector>: + "item", .make_items, lift .fold_item, |_span| SmallVector::zero(); + SmallVector: + "statement", .make_stmts, lift .fold_stmt, |_span| SmallVector::zero(); +} - let placer = fld.fold_expr(placer); - let value_expr = fld.fold_expr(value_expr); - fld.cx.expr(span, ast::ExprKind::InPlace(placer, value_expr)) - .with_attrs(fold_thin_attrs(attrs, fld)) +impl MacroGenerable for Option> { + fn kind_name() -> &'static str { "expression" } + fn dummy(_span: Span) -> Self { None } + fn make_with<'a>(result: Box) -> Option { + result.make_expr().map(Some) + } + fn fold_with(self, folder: &mut F) -> Self { + self.and_then(|expr| folder.fold_opt_expr(expr)) + } +} + +pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P { + match expr.node { + // expr_mac should really be expr_ext or something; it's the + // entry-point for all syntax extensions. + ast::ExprKind::Mac(mac) => { + expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, fld) } ast::ExprKind::While(cond, body, opt_ident) => { let cond = fld.fold_expr(cond); let (body, opt_ident) = expand_loop_block(body, opt_ident, fld); - fld.cx.expr(span, ast::ExprKind::While(cond, body, opt_ident)) - .with_attrs(fold_thin_attrs(attrs, fld)) + fld.cx.expr(expr.span, ast::ExprKind::While(cond, body, opt_ident)) + .with_attrs(fold_thin_attrs(expr.attrs, fld)) } - ast::ExprKind::WhileLet(pat, expr, body, opt_ident) => { + ast::ExprKind::WhileLet(pat, cond, body, opt_ident) => { let pat = fld.fold_pat(pat); - let expr = fld.fold_expr(expr); + let cond = fld.fold_expr(cond); // Hygienic renaming of the body. let ((body, opt_ident), mut rewritten_pats) = @@ -111,14 +117,14 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { }); assert!(rewritten_pats.len() == 1); - let wl = ast::ExprKind::WhileLet(rewritten_pats.remove(0), expr, body, opt_ident); - fld.cx.expr(span, wl).with_attrs(fold_thin_attrs(attrs, fld)) + let wl = ast::ExprKind::WhileLet(rewritten_pats.remove(0), cond, body, opt_ident); + fld.cx.expr(expr.span, wl).with_attrs(fold_thin_attrs(expr.attrs, fld)) } ast::ExprKind::Loop(loop_block, opt_ident) => { let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld); - fld.cx.expr(span, ast::ExprKind::Loop(loop_block, opt_ident)) - .with_attrs(fold_thin_attrs(attrs, fld)) + fld.cx.expr(expr.span, ast::ExprKind::Loop(loop_block, opt_ident)) + .with_attrs(fold_thin_attrs(expr.attrs, fld)) } ast::ExprKind::ForLoop(pat, head, body, opt_ident) => { @@ -136,7 +142,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { let head = fld.fold_expr(head); let fl = ast::ExprKind::ForLoop(rewritten_pats.remove(0), head, body, opt_ident); - fld.cx.expr(span, fl).with_attrs(fold_thin_attrs(attrs, fld)) + fld.cx.expr(expr.span, fl).with_attrs(fold_thin_attrs(expr.attrs, fld)) } ast::ExprKind::IfLet(pat, sub_expr, body, else_opt) => { @@ -155,7 +161,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt)); let sub_expr = fld.fold_expr(sub_expr); let il = ast::ExprKind::IfLet(rewritten_pats.remove(0), sub_expr, body, else_opt); - fld.cx.expr(span, il).with_attrs(fold_thin_attrs(attrs, fld)) + fld.cx.expr(expr.span, il).with_attrs(fold_thin_attrs(expr.attrs, fld)) } ast::ExprKind::Closure(capture_clause, fn_decl, block, fn_decl_span) => { @@ -164,76 +170,72 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { let new_node = ast::ExprKind::Closure(capture_clause, rewritten_fn_decl, rewritten_block, - fld.new_span(fn_decl_span)); - P(ast::Expr{ id:id, + fn_decl_span); + P(ast::Expr{ id: expr.id, node: new_node, - span: fld.new_span(span), - attrs: fold_thin_attrs(attrs, fld) }) + span: expr.span, + attrs: fold_thin_attrs(expr.attrs, fld) }) } - _ => { - P(noop_fold_expr(ast::Expr { - id: id, - node: node, - span: span, - attrs: attrs - }, fld)) - } - }); + _ => P(noop_fold_expr(expr, fld)), + } } -/// Expand a (not-ident-style) macro invocation. Returns the result -/// of expansion and the mark which must be applied to the result. -/// Our current interface doesn't allow us to apply the mark to the -/// result until after calling make_expr, make_items, etc. -fn expand_mac_invoc(mac: ast::Mac, - span: codemap::Span, - parse_thunk: F, - mark_thunk: G, - fld: &mut MacroExpander) - -> Option where - F: for<'a> FnOnce(Box) -> Option, - G: FnOnce(T, Mrk) -> T, +/// Expand a macro invocation. Returns the result of expansion. +fn expand_mac_invoc(mac: ast::Mac, ident: Option, attrs: Vec, span: Span, + fld: &mut MacroExpander) -> T + where T: MacroGenerable, { - // it would almost certainly be cleaner to pass the whole - // macro invocation in, rather than pulling it apart and - // marking the tts and the ctxt separately. This also goes - // for the other three macro invocation chunks of code - // in this file. - - let Mac_ { path: pth, tts, .. } = mac.node; - if pth.segments.len() > 1 { - fld.cx.span_err(pth.span, - "expected macro name without module \ - separators"); - // let compilation continue - return None; - } - let extname = pth.segments[0].identifier.name; - match fld.cx.syntax_env.find(extname) { - None => { - let mut err = fld.cx.struct_span_err( - pth.span, - &format!("macro undefined: '{}!'", - &extname)); + // It would almost certainly be cleaner to pass the whole macro invocation in, + // rather than pulling it apart and marking the tts and the ctxt separately. + let Mac_ { path, tts, .. } = mac.node; + let mark = fresh_mark(); + + fn mac_result<'a>(path: &ast::Path, ident: Option, tts: Vec, mark: Mrk, + attrs: Vec, call_site: Span, fld: &'a mut MacroExpander) + -> Option> { + // Detect use of feature-gated or invalid attributes on macro invoations + // since they will not be detected after macro expansion. + for attr in attrs.iter() { + feature_gate::check_attribute(&attr, &fld.cx.parse_sess.span_diagnostic, + &fld.cx.parse_sess.codemap(), + &fld.cx.ecfg.features.unwrap()); + } + + if path.segments.len() > 1 { + fld.cx.span_err(path.span, "expected macro name without module separators"); + return None; + } + + let extname = path.segments[0].identifier.name; + let extension = if let Some(extension) = fld.cx.syntax_env.find(extname) { + extension + } else { + let mut err = fld.cx.struct_span_err(path.span, + &format!("macro undefined: '{}!'", &extname)); fld.cx.suggest_macro_name(&extname.as_str(), &mut err); err.emit(); + return None; + }; - // let compilation continue - None - } - Some(rc) => match *rc { + let ident = ident.unwrap_or(keywords::Invalid.ident()); + match *extension { NormalTT(ref expandfun, exp_span, allow_internal_unstable) => { + if ident.name != keywords::Invalid.name() { + let msg = + format!("macro {}! expects no ident argument, given '{}'", extname, ident); + fld.cx.span_err(path.span, &msg); + return None; + } + fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroBang(extname), - span: exp_span, - allow_internal_unstable: allow_internal_unstable, - }, - }); - let fm = fresh_mark(); - let marked_before = mark_tts(&tts[..], fm); + call_site: call_site, + callee: NameAndSpan { + format: MacroBang(extname), + span: exp_span, + allow_internal_unstable: allow_internal_unstable, + }, + }); // The span that we pass to the expanders we want to // be the root of the call stack. That's the most @@ -241,34 +243,93 @@ fn expand_mac_invoc(mac: ast::Mac, // the macro. let mac_span = fld.cx.original_span(); - let opt_parsed = { - let expanded = expandfun.expand(fld.cx, - mac_span, - &marked_before[..]); - parse_thunk(expanded) + let marked_tts = mark_tts(&tts[..], mark); + Some(expandfun.expand(fld.cx, mac_span, &marked_tts)) + } + + IdentTT(ref expander, tt_span, allow_internal_unstable) => { + if ident.name == keywords::Invalid.name() { + fld.cx.span_err(path.span, + &format!("macro {}! expects an ident argument", extname)); + return None; }; - let parsed = match opt_parsed { - Some(e) => e, - None => { - fld.cx.span_err( - pth.span, - &format!("non-expression macro in expression position: {}", - extname - )); - return None; + + fld.cx.bt_push(ExpnInfo { + call_site: call_site, + callee: NameAndSpan { + format: MacroBang(extname), + span: tt_span, + allow_internal_unstable: allow_internal_unstable, } + }); + + let marked_tts = mark_tts(&tts, mark); + Some(expander.expand(fld.cx, call_site, ident, marked_tts)) + } + + MacroRulesTT => { + if ident.name == keywords::Invalid.name() { + fld.cx.span_err(path.span, + &format!("macro {}! expects an ident argument", extname)); + return None; }; - Some(mark_thunk(parsed,fm)) + + fld.cx.bt_push(ExpnInfo { + call_site: call_site, + callee: NameAndSpan { + format: MacroBang(extname), + span: None, + // `macro_rules!` doesn't directly allow unstable + // (this is orthogonal to whether the macro it creates allows it) + allow_internal_unstable: false, + } + }); + + // DON'T mark before expansion. + fld.cx.insert_macro(ast::MacroDef { + ident: ident, + id: ast::DUMMY_NODE_ID, + span: call_site, + imported_from: None, + use_locally: true, + body: tts, + export: attr::contains_name(&attrs, "macro_export"), + allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"), + attrs: attrs, + }); + + // macro_rules! has a side effect but expands to nothing. + fld.cx.bt_pop(); + None } - _ => { - fld.cx.span_err( - pth.span, - &format!("'{}' is not a tt-style macro", - extname)); + + MultiDecorator(..) | MultiModifier(..) => { + fld.cx.span_err(path.span, + &format!("`{}` can only be used in attributes", extname)); None } } } + + let opt_expanded = T::make_with(match mac_result(&path, ident, tts, mark, attrs, span, fld) { + Some(result) => result, + None => return T::dummy(span), + }); + + let expanded = if let Some(expanded) = opt_expanded { + expanded + } else { + let msg = format!("non-{kind} macro in {kind} position: {name}", + name = path.segments[0].identifier.name, kind = T::kind_name()); + fld.cx.span_err(path.span, &msg); + return T::dummy(span); + }; + + let marked = expanded.fold_with(&mut Marker { mark: mark, expn_id: Some(fld.cx.backtrace()) }); + let configured = marked.fold_with(&mut fld.strip_unconfigured()); + let fully_expanded = configured.fold_with(fld); + fld.cx.bt_pop(); + fully_expanded } /// Rename loop label and expand its loop body @@ -277,12 +338,12 @@ fn expand_mac_invoc(mac: ast::Mac, /// body is in a block enclosed by loop head so the renaming of loop label /// must be propagated to the enclosed context. fn expand_loop_block(loop_block: P, - opt_ident: Option, - fld: &mut MacroExpander) -> (P, Option) { + opt_ident: Option, + fld: &mut MacroExpander) -> (P, Option) { match opt_ident { Some(label) => { - let new_label = fresh_name(label); - let rename = (label, new_label); + let new_label = fresh_name(label.node); + let rename = (label.node, new_label); // The rename *must not* be added to the pending list of current // syntax context otherwise an unrelated `break` or `continue` in @@ -290,7 +351,7 @@ fn expand_loop_block(loop_block: P, // and be renamed incorrectly. let mut rename_list = vec!(rename); let mut rename_fld = IdentRenamer{renames: &mut rename_list}; - let renamed_ident = rename_fld.fold_ident(label); + let renamed_ident = rename_fld.fold_ident(label.node); // The rename *must* be added to the enclosed syntax context for // `break` or `continue` to pick up because by definition they are @@ -300,7 +361,7 @@ fn expand_loop_block(loop_block: P, let expanded_block = expand_block_elts(loop_block, fld); fld.cx.syntax_env.pop_frame(); - (expanded_block, Some(renamed_ident)) + (expanded_block, Some(Spanned { node: renamed_ident, span: label.span })) } None => (fld.fold_block(loop_block), opt_ident) } @@ -367,141 +428,6 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool false } -// Support for item-position macro invocations, exactly the same -// logic as for expression-position macro invocations. -pub fn expand_item_mac(it: P, - fld: &mut MacroExpander) -> SmallVector> { - let (extname, path_span, tts, span, attrs, ident) = it.and_then(|it| match it.node { - ItemKind::Mac(codemap::Spanned { node: Mac_ { path, tts, .. }, .. }) => - (path.segments[0].identifier.name, path.span, tts, it.span, it.attrs, it.ident), - _ => fld.cx.span_bug(it.span, "invalid item macro invocation") - }); - - check_attributes(&attrs, fld); - - let fm = fresh_mark(); - let items = { - let expanded = match fld.cx.syntax_env.find(extname) { - None => { - fld.cx.span_err(path_span, - &format!("macro undefined: '{}!'", - extname)); - // let compilation continue - return SmallVector::zero(); - } - - Some(rc) => match *rc { - NormalTT(ref expander, tt_span, allow_internal_unstable) => { - if ident.name != keywords::Invalid.name() { - fld.cx - .span_err(path_span, - &format!("macro {}! expects no ident argument, given '{}'", - extname, - ident)); - return SmallVector::zero(); - } - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroBang(extname), - span: tt_span, - allow_internal_unstable: allow_internal_unstable, - } - }); - // mark before expansion: - let marked_before = mark_tts(&tts[..], fm); - expander.expand(fld.cx, span, &marked_before[..]) - } - IdentTT(ref expander, tt_span, allow_internal_unstable) => { - if ident.name == keywords::Invalid.name() { - fld.cx.span_err(path_span, - &format!("macro {}! expects an ident argument", - extname)); - return SmallVector::zero(); - } - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroBang(extname), - span: tt_span, - allow_internal_unstable: allow_internal_unstable, - } - }); - // mark before expansion: - let marked_tts = mark_tts(&tts[..], fm); - expander.expand(fld.cx, span, ident, marked_tts) - } - MacroRulesTT => { - if ident.name == keywords::Invalid.name() { - fld.cx.span_err(path_span, "macro_rules! expects an ident argument"); - return SmallVector::zero(); - } - - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroBang(extname), - span: None, - // `macro_rules!` doesn't directly allow - // unstable (this is orthogonal to whether - // the macro it creates allows it) - allow_internal_unstable: false, - } - }); - // DON'T mark before expansion. - - let allow_internal_unstable = attr::contains_name(&attrs, - "allow_internal_unstable"); - - let export = attr::contains_name(&attrs, "macro_export"); - let def = ast::MacroDef { - ident: ident, - attrs: attrs, - id: ast::DUMMY_NODE_ID, - span: span, - imported_from: None, - export: export, - use_locally: true, - allow_internal_unstable: allow_internal_unstable, - body: tts, - }; - fld.cx.insert_macro(def); - - // macro_rules! has a side effect but expands to nothing. - fld.cx.bt_pop(); - return SmallVector::zero(); - } - _ => { - fld.cx.span_err(span, - &format!("{}! is not legal in item position", - extname)); - return SmallVector::zero(); - } - } - }; - - expanded.make_items() - }; - - let items = match items { - Some(items) => { - items.into_iter() - .map(|i| mark_item(i, fm)) - .flat_map(|i| fld.fold_item(i).into_iter()) - .collect() - } - None => { - fld.cx.span_err(path_span, - &format!("non-item macro in item position: {}", - extname)); - return SmallVector::zero(); - } - }; - - fld.cx.bt_pop(); - items -} - /// Expand a stmt fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector { // perform all pending renames @@ -516,30 +442,8 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector { _ => return expand_non_macro_stmt(stmt, fld) }; - if let Some(ref attrs) = attrs { - check_attributes(attrs, fld); - } - - // Assert that we drop any macro attributes on the floor here - drop(attrs); - - let maybe_new_items = - expand_mac_invoc(mac.unwrap(), stmt.span, - |r| r.make_stmts(), - |stmts, mark| stmts.move_map(|m| mark_stmt(m, mark)), - fld); - - let mut fully_expanded = match maybe_new_items { - Some(stmts) => { - // Keep going, outside-in. - let new_items = stmts.into_iter().flat_map(|s| { - fld.fold_stmt(s).into_iter() - }).collect(); - fld.cx.bt_pop(); - new_items - } - None => SmallVector::zero() - }; + let mut fully_expanded: SmallVector = + expand_mac_invoc(mac.unwrap(), None, attrs.into_attr_vec(), stmt.span, fld); // If this is a macro invocation with a semicolon, then apply that // semicolon to the final statement produced by expansion. @@ -754,76 +658,10 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { PatKind::Mac(_) => {} _ => return noop_fold_pat(p, fld) } - p.map(|ast::Pat {node, span, ..}| { - let (pth, tts) = match node { - PatKind::Mac(mac) => (mac.node.path, mac.node.tts), + p.and_then(|ast::Pat {node, span, ..}| { + match node { + PatKind::Mac(mac) => expand_mac_invoc(mac, None, Vec::new(), span, fld), _ => unreachable!() - }; - if pth.segments.len() > 1 { - fld.cx.span_err(pth.span, "expected macro name without module separators"); - return DummyResult::raw_pat(span); - } - let extname = pth.segments[0].identifier.name; - let marked_after = match fld.cx.syntax_env.find(extname) { - None => { - fld.cx.span_err(pth.span, - &format!("macro undefined: '{}!'", - extname)); - // let compilation continue - return DummyResult::raw_pat(span); - } - - Some(rc) => match *rc { - NormalTT(ref expander, tt_span, allow_internal_unstable) => { - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroBang(extname), - span: tt_span, - allow_internal_unstable: allow_internal_unstable, - } - }); - - let fm = fresh_mark(); - let marked_before = mark_tts(&tts[..], fm); - let mac_span = fld.cx.original_span(); - let pat = expander.expand(fld.cx, - mac_span, - &marked_before[..]).make_pat(); - let expanded = match pat { - Some(e) => e, - None => { - fld.cx.span_err( - pth.span, - &format!( - "non-pattern macro in pattern position: {}", - extname - ) - ); - return DummyResult::raw_pat(span); - } - }; - - // mark after: - mark_pat(expanded,fm) - } - _ => { - fld.cx.span_err(span, - &format!("{}! is not legal in pattern position", - extname)); - return DummyResult::raw_pat(span); - } - } - }; - - let fully_expanded = - fld.fold_pat(marked_after).node.clone(); - fld.cx.bt_pop(); - - ast::Pat { - id: ast::DUMMY_NODE_ID, - node: fully_expanded, - span: span } }) } @@ -865,12 +703,12 @@ impl<'a> Folder for PatIdentRenamer<'a> { mtwt::apply_renames(self.renames, ident.ctxt)); let new_node = PatKind::Ident(binding_mode, - Spanned{span: self.new_span(sp), node: new_ident}, + Spanned{span: sp, node: new_ident}, sub.map(|p| self.fold_pat(p))); ast::Pat { id: id, node: new_node, - span: self.new_span(span) + span: span, } }, _ => unreachable!() @@ -893,7 +731,13 @@ fn expand_annotatable(a: Annotatable, let mut new_items: SmallVector = match a { Annotatable::Item(it) => match it.node { ast::ItemKind::Mac(..) => { - expand_item_mac(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect() + let new_items: SmallVector> = it.and_then(|it| match it.node { + ItemKind::Mac(mac) => + expand_mac_invoc(mac, Some(it.ident), it.attrs, it.span, fld), + _ => unreachable!(), + }); + + new_items.into_iter().map(|i| Annotatable::Item(i)).collect() } ast::ItemKind::Mod(_) | ast::ItemKind::ForeignMod(_) => { let valid_ident = @@ -934,7 +778,7 @@ fn expand_annotatable(a: Annotatable, } _ => unreachable!() }, - span: fld.new_span(ti.span) + span: ti.span, }) } _ => fold::noop_fold_trait_item(it.unwrap(), fld) @@ -1074,28 +918,10 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander) } _ => unreachable!() }, - span: fld.new_span(ii.span) + span: ii.span, }), ast::ImplItemKind::Macro(mac) => { - check_attributes(&ii.attrs, fld); - - let maybe_new_items = - expand_mac_invoc(mac, ii.span, - |r| r.make_impl_items(), - |meths, mark| meths.move_map(|m| mark_impl_item(m, mark)), - fld); - - match maybe_new_items { - Some(impl_items) => { - // expand again if necessary - let new_items = impl_items.into_iter().flat_map(|ii| { - expand_impl_item(ii, fld).into_iter() - }).collect(); - fld.cx.bt_pop(); - new_items - } - None => SmallVector::zero() - } + expand_mac_invoc(mac, None, ii.attrs, ii.span, fld) } _ => fold::noop_fold_impl_item(ii, fld) } @@ -1128,7 +954,6 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P, (ast::MethodSig { generics: fld.fold_generics(sig.generics), abi: sig.abi, - explicit_self: fld.fold_explicit_self(sig.explicit_self), unsafety: sig.unsafety, constness: sig.constness, decl: rewritten_fn_decl @@ -1139,25 +964,7 @@ pub fn expand_type(t: P, fld: &mut MacroExpander) -> P { let t = match t.node.clone() { ast::TyKind::Mac(mac) => { if fld.cx.ecfg.features.unwrap().type_macros { - let expanded_ty = match expand_mac_invoc(mac, t.span, - |r| r.make_ty(), - mark_ty, - fld) { - Some(ty) => ty, - None => { - return DummyResult::raw_ty(t.span); - } - }; - - // Keep going, outside-in. - let fully_expanded = fld.fold_ty(expanded_ty); - fld.cx.bt_pop(); - - fully_expanded.map(|t| ast::Ty { - id: ast::DUMMY_NODE_ID, - node: t.node, - span: t.span, - }) + expand_mac_invoc(mac, None, Vec::new(), t.span, fld) } else { feature_gate::emit_feature_err( &fld.cx.parse_sess.span_diagnostic, @@ -1184,6 +991,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { pub fn new(cx: &'a mut ExtCtxt<'b>) -> MacroExpander<'a, 'b> { MacroExpander { cx: cx } } + + fn strip_unconfigured(&mut self) -> StripUnconfigured { + StripUnconfigured::new(&self.cx.cfg, + &self.cx.parse_sess.span_diagnostic, + self.cx.feature_gated_cfgs) + } } impl<'a, 'b> Folder for MacroExpander<'a, 'b> { @@ -1193,7 +1006,15 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } fn fold_expr(&mut self, expr: P) -> P { - expand_expr(expr, self) + expr.and_then(|expr| expand_expr(expr, self)) + } + + fn fold_opt_expr(&mut self, expr: P) -> Option> { + expr.and_then(|expr| match expr.node { + ast::ExprKind::Mac(mac) => + expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, self), + _ => Some(expand_expr(expr, self)), + }) } fn fold_pat(&mut self, pat: P) -> P { @@ -1256,10 +1077,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { fn fold_ty(&mut self, ty: P) -> P { expand_type(ty, self) } - - fn new_span(&mut self, span: Span) -> Span { - new_span(self.cx, span) - } } impl<'a, 'b> MacroExpander<'a, 'b> { @@ -1277,45 +1094,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } -fn new_span(cx: &ExtCtxt, sp: Span) -> Span { - debug!("new_span(sp={:?})", sp); - - if cx.codemap().more_specific_trace(sp.expn_id, cx.backtrace()) { - // If the span we are looking at has a backtrace that has more - // detail than our current backtrace, then we keep that - // backtrace. Honestly, I have no idea if this makes sense, - // because I have no idea why we are stripping the backtrace - // below. But the reason I made this change is because, in - // deriving, we were generating attributes with a specific - // backtrace, which was essential for `#[structural_match]` to - // be properly supported, but these backtraces were being - // stripped and replaced with a null backtrace. Sort of - // unclear why this is the case. --nmatsakis - debug!("new_span: keeping trace from {:?} because it is more specific", - sp.expn_id); - sp - } else { - // This discards information in the case of macro-defining macros. - // - // The comment above was originally added in - // b7ec2488ff2f29681fe28691d20fd2c260a9e454 in Feb 2012. I - // *THINK* the reason we are doing this is because we want to - // replace the backtrace of the macro contents with the - // backtrace that contains the macro use. But it's pretty - // unclear to me. --nmatsakis - let sp1 = Span { - lo: sp.lo, - hi: sp.hi, - expn_id: cx.backtrace(), - }; - debug!("new_span({:?}) = {:?}", sp, sp1); - if sp.expn_id.into_u32() == 0 && env::var_os("NDM").is_some() { - panic!("NDM"); - } - sp1 - } -} - pub struct ExpansionConfig<'feat> { pub crate_name: String, pub features: Option<&'feat Features>, @@ -1402,8 +1180,9 @@ pub fn expand_crate(mut cx: ExtCtxt, // the ones defined here include: // Marker - add a mark to a context -// A Marker adds the given mark to the syntax context -struct Marker { mark: Mrk } +// A Marker adds the given mark to the syntax context and +// sets spans' `expn_id` to the given expn_id (unless it is `None`). +struct Marker { mark: Mrk, expn_id: Option } impl Folder for Marker { fn fold_ident(&mut self, id: Ident) -> Ident { @@ -1416,46 +1195,21 @@ impl Folder for Marker { tts: self.fold_tts(&node.tts), ctxt: mtwt::apply_mark(self.mark, node.ctxt), }, - span: span, + span: self.new_span(span), } } + + fn new_span(&mut self, mut span: Span) -> Span { + if let Some(expn_id) = self.expn_id { + span.expn_id = expn_id; + } + span + } } // apply a given mark to the given token trees. Used prior to expansion of a macro. fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec { - noop_fold_tts(tts, &mut Marker{mark:m}) -} - -// apply a given mark to the given expr. Used following the expansion of a macro. -fn mark_expr(expr: P, m: Mrk) -> P { - Marker{mark:m}.fold_expr(expr) -} - -// apply a given mark to the given pattern. Used following the expansion of a macro. -fn mark_pat(pat: P, m: Mrk) -> P { - Marker{mark:m}.fold_pat(pat) -} - -// apply a given mark to the given stmt. Used following the expansion of a macro. -fn mark_stmt(stmt: ast::Stmt, m: Mrk) -> ast::Stmt { - Marker{mark:m}.fold_stmt(stmt) - .expect_one("marking a stmt didn't return exactly one stmt") -} - -// apply a given mark to the given item. Used following the expansion of a macro. -fn mark_item(expr: P, m: Mrk) -> P { - Marker{mark:m}.fold_item(expr) - .expect_one("marking an item didn't return exactly one item") -} - -// apply a given mark to the given item. Used following the expansion of a macro. -fn mark_impl_item(ii: ast::ImplItem, m: Mrk) -> ast::ImplItem { - Marker{mark:m}.fold_impl_item(ii) - .expect_one("marking an impl item didn't return exactly one impl item") -} - -fn mark_ty(ty: P, m: Mrk) -> P { - Marker { mark: m }.fold_ty(ty) + noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None}) } /// Check that there are no macro invocations left in the AST: diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 89ecf02ee4c92..ca5eb8f8003bb 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -549,13 +549,8 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { token::NtPath(Box::new(panictry!(p.parse_path(PathStyle::Type)))) }, "meta" => token::NtMeta(panictry!(p.parse_meta_item())), - _ => { - p.span_fatal_help(sp, - &format!("invalid fragment specifier `{}`", name), - "valid fragment specifiers are `ident`, `block`, \ - `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \ - and `item`").emit(); - panic!(FatalError); - } + // this is not supposed to happen, since it has been checked + // when compiling the macro. + _ => p.span_bug(sp, "invalid fragment specifier") } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 41d3991aee809..3522c8863cf52 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -291,17 +291,16 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, let lhses = match **argument_map.get(&lhs_nm.name).unwrap() { MatchedSeq(ref s, _) => { s.iter().map(|m| match **m { - MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), + MatchedNonterminal(NtTT(ref tt)) => { + valid &= check_lhs_nt_follows(cx, tt); + (**tt).clone() + } _ => cx.span_bug(def.span, "wrong-structured lhs") }).collect() } _ => cx.span_bug(def.span, "wrong-structured lhs") }; - for lhs in &lhses { - check_lhs_nt_follows(cx, lhs, def.span); - } - let rhses = match **argument_map.get(&rhs_nm.name).unwrap() { MatchedSeq(ref s, _) => { s.iter().map(|m| match **m { @@ -330,19 +329,19 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, // why is this here? because of https://github.com/rust-lang/rust/issues/27774 fn ref_slice(s: &A) -> &[A] { use std::slice::from_raw_parts; unsafe { from_raw_parts(s, 1) } } -fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree, sp: Span) { +fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. match lhs { - &TokenTree::Delimited(_, ref tts) => { - check_matcher(cx, &tts.tts); - }, - tt @ &TokenTree::Sequence(..) => { - check_matcher(cx, ref_slice(tt)); - }, - _ => cx.span_err(sp, "invalid macro matcher; matchers must be contained \ - in balanced delimiters or a repetition indicator") - }; + &TokenTree::Delimited(_, ref tts) => check_matcher(cx, &tts.tts), + tt @ &TokenTree::Sequence(..) => check_matcher(cx, ref_slice(tt)), + _ => { + cx.span_err(lhs.get_span(), + "invalid macro matcher; matchers must be contained \ + in balanced delimiters or a repetition indicator"); + false + } + } // we don't abort on errors on rejection, the driver will do that for us // after parsing/expansion. we can report every error in every macro this way. } @@ -364,20 +363,25 @@ struct OnFail { action: OnFailAction, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] enum OnFailAction { Warn, Error, DoNothing } impl OnFail { fn warn() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::Warn } } fn error() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::Error } } fn do_nothing() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::DoNothing } } - fn react(&mut self, cx: &mut ExtCtxt, sp: Span, msg: &str) { + fn react(&mut self, cx: &mut ExtCtxt, sp: Span, msg: &str, help: Option<&str>) { match self.action { OnFailAction::DoNothing => {} - OnFailAction::Error => cx.span_err(sp, msg), + OnFailAction::Error => { + let mut err = cx.struct_span_err(sp, msg); + if let Some(msg) = help { err.span_help(sp, msg); } + err.emit(); + } OnFailAction::Warn => { - cx.struct_span_warn(sp, msg) - .span_note(sp, "The above warning will be a hard error in the next release.") + let mut warn = cx.struct_span_warn(sp, msg); + if let Some(msg) = help { warn.span_help(sp, msg); } + warn.span_note(sp, "The above warning will be a hard error in the next release.") .emit(); } }; @@ -385,7 +389,7 @@ impl OnFail { } } -fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree]) { +fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree]) -> bool { // Issue 30450: when we are through a warning cycle, we can just // error on all failure conditions (and remove check_matcher_old). @@ -400,6 +404,9 @@ fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree]) { OnFail::warn() }; check_matcher_new(cx, matcher, &mut on_fail); + // matcher is valid if the new pass didn't see any error, + // or if errors were considered warnings + on_fail.action != OnFailAction::Error || !on_fail.saw_failure } // returns the last token that was checked, for TokenTree::Sequence. @@ -435,11 +442,11 @@ fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fai // sequence, which may itself be a sequence, // and so on). on_fail.react(cx, sp, - &format!("`${0}:{1}` is followed by a \ - sequence repetition, which is not \ - allowed for `{1}` fragments", - name, frag_spec) - ); + &format!("`${0}:{1}` is followed by a \ + sequence repetition, which is not \ + allowed for `{1}` fragments", + name, frag_spec), + None); Eof }, // die next iteration @@ -456,8 +463,10 @@ fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fai // If T' is in the set FOLLOW(NT), continue. Else, reject. match (&next_token, is_in_follow(cx, &next_token, &frag_spec.name.as_str())) { - (_, Err(msg)) => { - on_fail.react(cx, sp, &msg); + (_, Err((msg, _))) => { + // no need for help message, those messages + // are never emitted anyway... + on_fail.react(cx, sp, &msg, None); continue } (&Eof, _) => return Some((sp, tok.clone())), @@ -466,7 +475,7 @@ fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fai on_fail.react(cx, sp, &format!("`${0}:{1}` is followed by `{2}`, which \ is not allowed for `{1}` fragments", name, frag_spec, - token_to_string(next))); + token_to_string(next)), None); continue }, } @@ -494,7 +503,8 @@ fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fai delim.close_token(), Some(_) => { on_fail.react(cx, sp, "sequence repetition followed by \ - another sequence repetition, which is not allowed"); + another sequence repetition, which is not allowed", + None); Eof }, None => Eof @@ -514,7 +524,7 @@ fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fai Some(&&TokenTree::Delimited(_, ref delim)) => delim.close_token(), Some(_) => { on_fail.react(cx, sp, "sequence repetition followed by another \ - sequence repetition, which is not allowed"); + sequence repetition, which is not allowed", None); Eof }, None => Eof @@ -810,7 +820,11 @@ fn check_matcher_core(cx: &mut ExtCtxt, TokenTree::Token(sp, ref tok) => { let can_be_followed_by_any; if let Err(bad_frag) = has_legal_fragment_specifier(tok) { - on_fail.react(cx, sp, &format!("invalid fragment specifier `{}`", bad_frag)); + on_fail.react(cx, sp, + &format!("invalid fragment specifier `{}`", bad_frag), + Some("valid fragment specifiers are `ident`, `block`, \ + `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \ + and `item`")); // (This eliminates false positives and duplicates // from error messages.) can_be_followed_by_any = true; @@ -884,8 +898,8 @@ fn check_matcher_core(cx: &mut ExtCtxt, if let MatchNt(ref name, ref frag_spec) = *t { for &(sp, ref next_token) in &suffix_first.tokens { match is_in_follow(cx, next_token, &frag_spec.name.as_str()) { - Err(msg) => { - on_fail.react(cx, sp, &msg); + Err((msg, help)) => { + on_fail.react(cx, sp, &msg, Some(help)); // don't bother reporting every source of // conflict for a particular element of `last`. continue 'each_last; @@ -907,7 +921,9 @@ fn check_matcher_core(cx: &mut ExtCtxt, name=name, frag=frag_spec, next=token_to_string(next_token), - may_be=may_be)); + may_be=may_be), + None + ); } } } @@ -978,7 +994,7 @@ fn can_be_followed_by_any(frag: &str) -> bool { /// break macros that were relying on that binary operator as a /// separator. // when changing this do not forget to update doc/book/macros.md! -fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result { +fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result { if let &CloseDelim(_) = tok { // closing a token tree can never be matched by any fragment; // iow, we always require that `(` and `)` match, etc. @@ -1027,7 +1043,10 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result { // harmless Ok(true) }, - _ => Err(format!("invalid fragment specifier `{}`", frag)) + _ => Err((format!("invalid fragment specifier `{}`", frag), + "valid fragment specifiers are `ident`, `block`, \ + `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \ + and `item`")) } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index acef98f2afc1b..5687099b27ced 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -274,7 +274,10 @@ declare_features! ( (active, drop_types_in_const, "1.9.0", Some(33156)), // Allows cfg(target_has_atomic = "..."). - (active, cfg_target_has_atomic, "1.9.0", Some(32976)) + (active, cfg_target_has_atomic, "1.9.0", Some(32976)), + + // Allows `..` in tuple (struct) patterns + (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)) ); declare_features! ( @@ -315,7 +318,6 @@ declare_features! ( // Allows `#[deprecated]` attribute (accepted, deprecated, "1.9.0", Some(29935)) ); - // (changing above list without updating src/doc/reference.md makes @cmr sad) #[derive(PartialEq, Copy, Clone, Debug)] @@ -997,6 +999,9 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { ast::ExprKind::Try(..) => { gate_feature_post!(&self, question_mark, e.span, "the `?` operator is not stable"); } + ast::ExprKind::InPlace(..) => { + gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN); + } _ => {} } visit::walk_expr(self, e); @@ -1021,6 +1026,24 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { pattern.span, "box pattern syntax is experimental"); } + PatKind::Tuple(_, ddpos) + if ddpos.is_some() => { + gate_feature_post!(&self, dotdot_in_tuple_patterns, + pattern.span, + "`..` in tuple patterns is experimental"); + } + PatKind::TupleStruct(_, ref fields, ddpos) + if ddpos.is_some() && !fields.is_empty() => { + gate_feature_post!(&self, dotdot_in_tuple_patterns, + pattern.span, + "`..` in tuple struct patterns is experimental"); + } + PatKind::TupleStruct(_, ref fields, ddpos) + if ddpos.is_none() && fields.is_empty() => { + self.context.span_handler.struct_span_err(pattern.span, + "nullary enum variants are written with \ + no trailing `( )`").emit(); + } _ => {} } visit::walk_pat(self, pattern) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2c325080c0c26..edf418e33325b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -179,14 +179,6 @@ pub trait Folder : Sized { // fold::noop_fold_mac(_mac, self) } - fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf { - noop_fold_explicit_self(es, self) - } - - fn fold_explicit_self_kind(&mut self, es: SelfKind) -> SelfKind { - noop_fold_explicit_self_kind(es, self) - } - fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { noop_fold_lifetime(l, self) } @@ -383,7 +375,7 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { t.map(|Ty {id, node, span}| Ty { id: fld.new_id(id), node: match node { - TyKind::Infer => node, + TyKind::Infer | TyKind::ImplicitSelf => node, TyKind::Vec(ty) => TyKind::Vec(fld.fold_ty(ty)), TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)), TyKind::Rptr(region, mt) => { @@ -523,28 +515,6 @@ pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Option(es: SelfKind, fld: &mut T) - -> SelfKind { - match es { - SelfKind::Static | SelfKind::Value(_) => es, - SelfKind::Region(lifetime, m, ident) => { - SelfKind::Region(fld.fold_opt_lifetime(lifetime), m, ident) - } - SelfKind::Explicit(typ, ident) => { - SelfKind::Explicit(fld.fold_ty(typ), ident) - } - } -} - -pub fn noop_fold_explicit_self(Spanned {span, node}: ExplicitSelf, fld: &mut T) - -> ExplicitSelf { - Spanned { - node: fld.fold_explicit_self_kind(node), - span: fld.new_span(span) - } -} - - pub fn noop_fold_mac(Spanned {node, span}: Mac, fld: &mut T) -> Mac { Spanned { node: Mac_ { @@ -1096,7 +1066,6 @@ pub fn noop_fold_method_sig(sig: MethodSig, folder: &mut T) -> Method MethodSig { generics: folder.fold_generics(sig.generics), abi: sig.abi, - explicit_self: folder.fold_explicit_self(sig.explicit_self), unsafety: sig.unsafety, constness: sig.constness, decl: folder.fold_fn_decl(sig.decl) @@ -1115,9 +1084,9 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { sub.map(|x| folder.fold_pat(x))) } PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), - PatKind::TupleStruct(pth, pats) => { + PatKind::TupleStruct(pth, pats, ddpos) => { PatKind::TupleStruct(folder.fold_path(pth), - pats.map(|pats| pats.move_map(|x| folder.fold_pat(x)))) + pats.move_map(|x| folder.fold_pat(x)), ddpos) } PatKind::Path(pth) => { PatKind::Path(folder.fold_path(pth)) @@ -1138,7 +1107,9 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { }); PatKind::Struct(pth, fs, etc) } - PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))), + PatKind::Tuple(elts, ddpos) => { + PatKind::Tuple(elts.move_map(|x| folder.fold_pat(x)), ddpos) + } PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), PatKind::Range(e1, e2) => { @@ -1212,23 +1183,27 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::While(cond, body, opt_ident) => { ExprKind::While(folder.fold_expr(cond), folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) + opt_ident.map(|label| respan(folder.new_span(label.span), + folder.fold_ident(label.node)))) } ExprKind::WhileLet(pat, expr, body, opt_ident) => { ExprKind::WhileLet(folder.fold_pat(pat), folder.fold_expr(expr), folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) + opt_ident.map(|label| respan(folder.new_span(label.span), + folder.fold_ident(label.node)))) } ExprKind::ForLoop(pat, iter, body, opt_ident) => { ExprKind::ForLoop(folder.fold_pat(pat), folder.fold_expr(iter), folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) + opt_ident.map(|label| respan(folder.new_span(label.span), + folder.fold_ident(label.node)))) } ExprKind::Loop(body, opt_ident) => { ExprKind::Loop(folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) + opt_ident.map(|label| respan(folder.new_span(label.span), + folder.fold_ident(label.node)))) } ExprKind::Match(expr, arms) => { ExprKind::Match(folder.fold_expr(expr), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fc62cee92fdbc..22cc20b8f8c44 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -17,7 +17,7 @@ use ast::Block; use ast::{BlockCheckMode, CaptureBy}; use ast::{Constness, Crate, CrateConfig}; use ast::{Decl, DeclKind, Defaultness}; -use ast::{EMPTY_CTXT, EnumDef, ExplicitSelf}; +use ast::{EMPTY_CTXT, EnumDef}; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; @@ -954,25 +954,6 @@ impl<'a> Parser<'a> { Ok(result) } - /// Parse a sequence parameter of enum variant. For consistency purposes, - /// these should not be empty. - pub fn parse_enum_variant_seq(&mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: F) - -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let result = self.parse_unspanned_seq(bra, ket, sep, f)?; - if result.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - "nullary enum variants are written with no trailing `( )`"); - } - Ok(result) - } - // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. pub fn parse_seq(&mut self, @@ -1310,7 +1291,7 @@ impl<'a> Parser<'a> { let ident = p.parse_ident()?; let mut generics = p.parse_generics()?; - let (explicit_self, d) = p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{ + let d = p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{ // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a // definition... @@ -1324,7 +1305,6 @@ impl<'a> Parser<'a> { decl: d, generics: generics, abi: abi, - explicit_self: explicit_self, }; let body = match p.token { @@ -2283,18 +2263,19 @@ impl<'a> Parser<'a> { return self.parse_while_expr(None, lo, attrs); } if self.token.is_lifetime() { - let lifetime = self.get_lifetime(); + let label = Spanned { node: self.get_lifetime(), + span: self.span }; let lo = self.span.lo; self.bump(); self.expect(&token::Colon)?; if self.eat_keyword(keywords::While) { - return self.parse_while_expr(Some(lifetime), lo, attrs) + return self.parse_while_expr(Some(label), lo, attrs) } if self.eat_keyword(keywords::For) { - return self.parse_for_expr(Some(lifetime), lo, attrs) + return self.parse_for_expr(Some(label), lo, attrs) } if self.eat_keyword(keywords::Loop) { - return self.parse_loop_expr(Some(lifetime), lo, attrs) + return self.parse_loop_expr(Some(label), lo, attrs) } return Err(self.fatal("expected `while`, `for`, or `loop` after a label")) } @@ -2702,7 +2683,10 @@ impl<'a> Parser<'a> { return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))); } else { sp = mk_sp(sp.lo, self.span.hi); - self.parse_ident()? + self.parse_ident().unwrap_or_else(|mut e| { + e.emit(); + keywords::Invalid.ident() + }) } } token::SubstNt(name) => { @@ -2807,14 +2791,14 @@ impl<'a> Parser<'a> { let span = Span { hi: close_span.hi, ..pre_span }; match self.token { - // Correct delmiter. + // Correct delimiter. token::CloseDelim(d) if d == delim => { self.open_braces.pop().unwrap(); // Parse the close delimiter. self.bump(); } - // Incorect delimiter. + // Incorrect delimiter. token::CloseDelim(other) => { let token_str = self.this_token_to_string(); let mut err = self.diagnostic().struct_span_err(self.span, @@ -2829,9 +2813,9 @@ impl<'a> Parser<'a> { self.open_braces.pop().unwrap(); - // If the incorrect delimter matches an earlier opening + // If the incorrect delimiter matches an earlier opening // delimiter, then don't consume it (it can be used to - // close the earlier one)Otherwise, consume it. + // close the earlier one). Otherwise, consume it. // E.g., we try to recover from: // fn foo() { // bar(baz( @@ -2845,7 +2829,7 @@ impl<'a> Parser<'a> { // and an error emitted then. Thus we don't pop from // self.open_braces here. }, - _ => unreachable!(), + _ => {} } Ok(TokenTree::Delimited(span, Rc::new(Delimited { @@ -2859,7 +2843,7 @@ impl<'a> Parser<'a> { // invariants: the current token is not a left-delimiter, // not an EOF, and not the desired right-delimiter (if // it were, parse_seq_to_before_end would have prevented - // reaching this point. + // reaching this point). maybe_whole!(deref self, NtTT); match self.token { token::CloseDelim(_) => { @@ -3264,7 +3248,7 @@ impl<'a> Parser<'a> { } /// Parse a 'for' .. 'in' expression ('for' token already eaten) - pub fn parse_for_expr(&mut self, opt_ident: Option, + pub fn parse_for_expr(&mut self, opt_ident: Option, span_lo: BytePos, attrs: ThinAttributes) -> PResult<'a, P> { // Parse: `for in ` @@ -3283,7 +3267,7 @@ impl<'a> Parser<'a> { } /// Parse a 'while' or 'while let' expression ('while' token already eaten) - pub fn parse_while_expr(&mut self, opt_ident: Option, + pub fn parse_while_expr(&mut self, opt_ident: Option, span_lo: BytePos, attrs: ThinAttributes) -> PResult<'a, P> { if self.token.is_keyword(keywords::Let) { @@ -3298,7 +3282,7 @@ impl<'a> Parser<'a> { } /// Parse a 'while let' expression ('while' token already eaten) - pub fn parse_while_let_expr(&mut self, opt_ident: Option, + pub fn parse_while_let_expr(&mut self, opt_ident: Option, span_lo: BytePos, attrs: ThinAttributes) -> PResult<'a, P> { self.expect_keyword(keywords::Let)?; @@ -3312,7 +3296,7 @@ impl<'a> Parser<'a> { } // parse `loop {...}`, `loop` token already eaten - pub fn parse_loop_expr(&mut self, opt_ident: Option, + pub fn parse_loop_expr(&mut self, opt_ident: Option, span_lo: BytePos, attrs: ThinAttributes) -> PResult<'a, P> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; @@ -3433,21 +3417,33 @@ impl<'a> Parser<'a> { }; } - fn parse_pat_tuple_elements(&mut self) -> PResult<'a, Vec>> { + fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool) + -> PResult<'a, (Vec>, Option)> { let mut fields = vec![]; - if !self.check(&token::CloseDelim(token::Paren)) { - fields.push(self.parse_pat()?); - if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) { - while self.eat(&token::Comma) && - !self.check(&token::CloseDelim(token::Paren)) { + let mut ddpos = None; + + while !self.check(&token::CloseDelim(token::Paren)) { + if ddpos.is_none() && self.eat(&token::DotDot) { + ddpos = Some(fields.len()); + if self.eat(&token::Comma) { + // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. fields.push(self.parse_pat()?); } + } else if ddpos.is_some() && self.eat(&token::DotDot) { + // Emit a friendly error, ignore `..` and continue parsing + self.span_err(self.last_span, "`..` can only be used once per \ + tuple or tuple struct pattern"); + } else { + fields.push(self.parse_pat()?); } - if fields.len() == 1 { + + if !self.check(&token::CloseDelim(token::Paren)) || + (unary_needs_comma && fields.len() == 1 && ddpos.is_none()) { self.expect(&token::Comma)?; } } - Ok(fields) + + Ok((fields, ddpos)) } fn parse_pat_vec_elements( @@ -3626,9 +3622,9 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => { // Parse (pat,pat,pat,...) as tuple pattern self.bump(); - let fields = self.parse_pat_tuple_elements()?; + let (fields, ddpos) = self.parse_pat_tuple_elements(true)?; self.expect(&token::CloseDelim(token::Paren))?; - pat = PatKind::Tup(fields); + pat = PatKind::Tuple(fields, ddpos); } token::OpenDelim(token::Bracket) => { // Parse [pat,pat,...] as slice pattern @@ -3713,20 +3709,10 @@ impl<'a> Parser<'a> { return Err(self.fatal("unexpected `(` after qualified path")); } // Parse tuple struct or enum pattern - if self.look_ahead(1, |t| *t == token::DotDot) { - // This is a "top constructor only" pat - self.bump(); - self.bump(); - self.expect(&token::CloseDelim(token::Paren))?; - pat = PatKind::TupleStruct(path, None); - } else { - let args = self.parse_enum_variant_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| p.parse_pat())?; - pat = PatKind::TupleStruct(path, Some(args)); - } + self.bump(); + let (fields, ddpos) = self.parse_pat_tuple_elements(false)?; + self.expect(&token::CloseDelim(token::Paren))?; + pat = PatKind::TupleStruct(path, fields, ddpos) } _ => { pat = match qself { @@ -4616,25 +4602,19 @@ impl<'a> Parser<'a> { })) } - /// Parse the parameter list and result type of a function that may have a `self` parameter. - fn parse_fn_decl_with_self(&mut self, - parse_arg_fn: F) - -> PResult<'a, (ExplicitSelf, P)> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, - { + /// Returns the parsed optional self argument and whether a self shortcut was used. + fn parse_self_arg(&mut self) -> PResult<'a, Option> { let expect_ident = |this: &mut Self| match this.token { - token::Ident(ident) => { this.bump(); ident } // Preserve hygienic context. + // Preserve hygienic context. + token::Ident(ident) => { this.bump(); codemap::respan(this.last_span, ident) } _ => unreachable!() }; - self.expect(&token::OpenDelim(token::Paren))?; - // Parse optional self parameter of a method. // Only a limited set of initial token sequences is considered self parameters, anything // else is parsed as a normal function parameter list, so some lookahead is required. let eself_lo = self.span.lo; - let mut eself_mutbl = Mutability::Immutable; - let (eself, eself_ident_sp) = match self.token { + let (eself, eself_ident) = match self.token { token::BinOp(token::And) => { // &self // &mut self @@ -4643,30 +4623,26 @@ impl<'a> Parser<'a> { // ¬_self if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); - (SelfKind::Region(None, Mutability::Immutable, expect_ident(self)), - self.last_span) + (SelfKind::Region(None, Mutability::Immutable), expect_ident(self)) } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); self.bump(); - (SelfKind::Region(None, Mutability::Mutable, expect_ident(self)), - self.last_span) + (SelfKind::Region(None, Mutability::Mutable), expect_ident(self)) } else if self.look_ahead(1, |t| t.is_lifetime()) && self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); let lt = self.parse_lifetime()?; - (SelfKind::Region(Some(lt), Mutability::Immutable, expect_ident(self)), - self.last_span) + (SelfKind::Region(Some(lt), Mutability::Immutable), expect_ident(self)) } else if self.look_ahead(1, |t| t.is_lifetime()) && self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) && self.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); let lt = self.parse_lifetime()?; self.bump(); - (SelfKind::Region(Some(lt), Mutability::Mutable, expect_ident(self)), - self.last_span) + (SelfKind::Region(Some(lt), Mutability::Mutable), expect_ident(self)) } else { - (SelfKind::Static, codemap::DUMMY_SP) + return Ok(None); } } token::BinOp(token::Star) => { @@ -4678,15 +4654,15 @@ impl<'a> Parser<'a> { if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); self.span_err(self.span, "cannot pass `self` by raw pointer"); - (SelfKind::Value(expect_ident(self)), self.last_span) + (SelfKind::Value(Mutability::Immutable), expect_ident(self)) } else if self.look_ahead(1, |t| t.is_mutability()) && self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { self.bump(); self.bump(); self.span_err(self.span, "cannot pass `self` by raw pointer"); - (SelfKind::Value(expect_ident(self)), self.last_span) + (SelfKind::Value(Mutability::Immutable), expect_ident(self)) } else { - (SelfKind::Static, codemap::DUMMY_SP) + return Ok(None); } } token::Ident(..) => { @@ -4694,64 +4670,69 @@ impl<'a> Parser<'a> { // self // self: TYPE let eself_ident = expect_ident(self); - let eself_ident_sp = self.last_span; if self.eat(&token::Colon) { - (SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp) + let ty = self.parse_ty_sum()?; + (SelfKind::Explicit(ty, Mutability::Immutable), eself_ident) } else { - (SelfKind::Value(eself_ident), eself_ident_sp) + (SelfKind::Value(Mutability::Immutable), eself_ident) } } else if self.token.is_keyword(keywords::Mut) && self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { // mut self // mut self: TYPE - eself_mutbl = Mutability::Mutable; self.bump(); let eself_ident = expect_ident(self); - let eself_ident_sp = self.last_span; if self.eat(&token::Colon) { - (SelfKind::Explicit(self.parse_ty_sum()?, eself_ident), eself_ident_sp) + let ty = self.parse_ty_sum()?; + (SelfKind::Explicit(ty, Mutability::Mutable), eself_ident) } else { - (SelfKind::Value(eself_ident), eself_ident_sp) + (SelfKind::Value(Mutability::Mutable), eself_ident) } } else { - (SelfKind::Static, codemap::DUMMY_SP) + return Ok(None); } } - _ => (SelfKind::Static, codemap::DUMMY_SP) + _ => return Ok(None), }; - let mut eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself); + + let eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself); + Ok(Some(Arg::from_self(eself, eself_ident))) + } + + /// Parse the parameter list and result type of a function that may have a `self` parameter. + fn parse_fn_decl_with_self(&mut self, parse_arg_fn: F) -> PResult<'a, P> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, + { + self.expect(&token::OpenDelim(token::Paren))?; + + // Parse optional self argument + let self_arg = self.parse_self_arg()?; // Parse the rest of the function parameter list. let sep = SeqSep::trailing_allowed(token::Comma); - let fn_inputs = match eself.node { - SelfKind::Static => { - eself.span = codemap::DUMMY_SP; - self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) - } - SelfKind::Value(..) | SelfKind::Region(..) | SelfKind::Explicit(..) => { - if self.check(&token::CloseDelim(token::Paren)) { - vec![Arg::from_self(eself.clone(), eself_ident_sp, eself_mutbl)] - } else if self.check(&token::Comma) { - self.bump(); - let mut fn_inputs = vec![Arg::from_self(eself.clone(), eself_ident_sp, - eself_mutbl)]; - fn_inputs.append(&mut self.parse_seq_to_before_end( - &token::CloseDelim(token::Paren), sep, parse_arg_fn) - ); - fn_inputs - } else { - return self.unexpected(); - } + let fn_inputs = if let Some(self_arg) = self_arg { + if self.check(&token::CloseDelim(token::Paren)) { + vec![self_arg] + } else if self.eat(&token::Comma) { + let mut fn_inputs = vec![self_arg]; + fn_inputs.append(&mut self.parse_seq_to_before_end( + &token::CloseDelim(token::Paren), sep, parse_arg_fn) + ); + fn_inputs + } else { + return self.unexpected(); } + } else { + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) }; // Parse closing paren and return type. self.expect(&token::CloseDelim(token::Paren))?; - Ok((eself, P(FnDecl { + Ok(P(FnDecl { inputs: fn_inputs, output: self.parse_ret_ty()?, variadic: false - }))) + })) } // parse the |arg, arg| header on a lambda @@ -4944,15 +4925,12 @@ impl<'a> Parser<'a> { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { - p.parse_arg() - })?; + let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; generics.where_clause = self.parse_where_clause()?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig { generics: generics, abi: abi, - explicit_self: explicit_self, unsafety: unsafety, constness: constness, decl: decl diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ebb4927d69c0b..5b9ec924de953 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -12,7 +12,7 @@ pub use self::AnnNode::*; use abi::{self, Abi}; use ast::{self, TokenTree, BlockCheckMode, PatKind}; -use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; +use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Attribute; use attr::ThinAttributesExt; use util::parser::AssocOp; @@ -382,13 +382,12 @@ pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, constness: ast::Constness, name: ast::Ident, - opt_explicit_self: Option<&ast::SelfKind>, generics: &ast::Generics) -> String { to_string(|s| { s.head("")?; s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name), - generics, opt_explicit_self, &ast::Visibility::Inherited)?; + generics, &ast::Visibility::Inherited)?; s.end()?; // Close the head box s.end() // Close the outer box }) @@ -416,10 +415,6 @@ pub fn lit_to_string(l: &ast::Lit) -> String { to_string(|s| s.print_literal(l)) } -pub fn explicit_self_to_string(explicit_self: &ast::SelfKind) -> String { - to_string(|s| s.print_explicit_self(explicit_self, ast::Mutability::Immutable).map(|_| {})) -} - pub fn variant_to_string(var: &ast::Variant) -> String { to_string(|s| s.print_variant(var)) } @@ -1005,8 +1000,7 @@ impl<'a> State<'a> { f.unsafety, &f.decl, None, - &generics, - None)?; + &generics)?; } ast::TyKind::Path(None, ref path) => { self.print_path(path, false, 0)?; @@ -1036,6 +1030,9 @@ impl<'a> State<'a> { ast::TyKind::Infer => { word(&mut self.s, "_")?; } + ast::TyKind::ImplicitSelf => { + unreachable!(); + } ast::TyKind::Mac(ref m) => { self.print_mac(m, token::Paren)?; } @@ -1054,7 +1051,7 @@ impl<'a> State<'a> { self.print_fn(decl, ast::Unsafety::Normal, ast::Constness::NotConst, Abi::Rust, Some(item.ident), - generics, None, &item.vis)?; + generics, &item.vis)?; self.end()?; // end head-ibox word(&mut self.s, ";")?; self.end() // end the outer fn box @@ -1182,7 +1179,6 @@ impl<'a> State<'a> { abi, Some(item.ident), typarams, - None, &item.vis )?; word(&mut self.s, " ")?; @@ -1522,7 +1518,6 @@ impl<'a> State<'a> { m.abi, Some(ident), &m.generics, - None, vis) } @@ -2021,7 +2016,7 @@ impl<'a> State<'a> { } ast::ExprKind::While(ref test, ref blk, opt_ident) => { if let Some(ident) = opt_ident { - self.print_ident(ident)?; + self.print_ident(ident.node)?; self.word_space(":")?; } self.head("while")?; @@ -2031,7 +2026,7 @@ impl<'a> State<'a> { } ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => { if let Some(ident) = opt_ident { - self.print_ident(ident)?; + self.print_ident(ident.node)?; self.word_space(":")?; } self.head("while let")?; @@ -2044,7 +2039,7 @@ impl<'a> State<'a> { } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => { if let Some(ident) = opt_ident { - self.print_ident(ident)?; + self.print_ident(ident.node)?; self.word_space(":")?; } self.head("for")?; @@ -2057,7 +2052,7 @@ impl<'a> State<'a> { } ast::ExprKind::Loop(ref blk, opt_ident) => { if let Some(ident) = opt_ident { - self.print_ident(ident)?; + self.print_ident(ident.node)?; self.word_space(":")?; } self.head("loop")?; @@ -2472,17 +2467,23 @@ impl<'a> State<'a> { None => () } } - PatKind::TupleStruct(ref path, ref args_) => { + PatKind::TupleStruct(ref path, ref elts, ddpos) => { self.print_path(path, true, 0)?; - match *args_ { - None => word(&mut self.s, "(..)")?, - Some(ref args) => { - self.popen()?; - self.commasep(Inconsistent, &args[..], - |s, p| s.print_pat(&p))?; - self.pclose()?; + self.popen()?; + if let Some(ddpos) = ddpos { + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?; + if ddpos != 0 { + self.word_space(",")?; + } + word(&mut self.s, "..")?; + if ddpos != elts.len() { + word(&mut self.s, ",")?; + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; } + } else { + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; } + self.pclose()?; } PatKind::Path(ref path) => { self.print_path(path, true, 0)?; @@ -2513,13 +2514,23 @@ impl<'a> State<'a> { space(&mut self.s)?; word(&mut self.s, "}")?; } - PatKind::Tup(ref elts) => { + PatKind::Tuple(ref elts, ddpos) => { self.popen()?; - self.commasep(Inconsistent, - &elts[..], - |s, p| s.print_pat(&p))?; - if elts.len() == 1 { - word(&mut self.s, ",")?; + if let Some(ddpos) = ddpos { + self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?; + if ddpos != 0 { + self.word_space(",")?; + } + word(&mut self.s, "..")?; + if ddpos != elts.len() { + word(&mut self.s, ",")?; + self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?; + } + } else { + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; + if elts.len() == 1 { + word(&mut self.s, ",")?; + } } self.pclose()?; } @@ -2610,29 +2621,25 @@ impl<'a> State<'a> { self.end() // close enclosing cbox } - // Returns whether it printed anything - fn print_explicit_self(&mut self, - explicit_self: &ast::SelfKind, - mutbl: ast::Mutability) -> io::Result { - self.print_mutability(mutbl)?; - match *explicit_self { - ast::SelfKind::Static => { return Ok(false); } - ast::SelfKind::Value(_) => { - word(&mut self.s, "self")?; + fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> { + match explicit_self.node { + SelfKind::Value(m) => { + self.print_mutability(m)?; + word(&mut self.s, "self") } - ast::SelfKind::Region(ref lt, m, _) => { + SelfKind::Region(ref lt, m) => { word(&mut self.s, "&")?; self.print_opt_lifetime(lt)?; self.print_mutability(m)?; - word(&mut self.s, "self")?; + word(&mut self.s, "self") } - ast::SelfKind::Explicit(ref typ, _) => { + SelfKind::Explicit(ref typ, m) => { + self.print_mutability(m)?; word(&mut self.s, "self")?; self.word_space(":")?; - self.print_type(&typ)?; + self.print_type(&typ) } } - return Ok(true); } pub fn print_fn(&mut self, @@ -2642,7 +2649,6 @@ impl<'a> State<'a> { abi: abi::Abi, name: Option, generics: &ast::Generics, - opt_explicit_self: Option<&ast::SelfKind>, vis: &ast::Visibility) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -2651,21 +2657,14 @@ impl<'a> State<'a> { self.print_ident(name)?; } self.print_generics(generics)?; - self.print_fn_args_and_ret(decl, opt_explicit_self)?; + self.print_fn_args_and_ret(decl)?; self.print_where_clause(&generics.where_clause) } - pub fn print_fn_args(&mut self, decl: &ast::FnDecl, - _: Option<&ast::SelfKind>, - is_closure: bool) -> io::Result<()> { - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, is_closure)) - } - - pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl, - opt_explicit_self: Option<&ast::SelfKind>) + pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl) -> io::Result<()> { self.popen()?; - self.print_fn_args(decl, opt_explicit_self, false)?; + self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; if decl.variadic { word(&mut self.s, ", ...")?; } @@ -2679,7 +2678,7 @@ impl<'a> State<'a> { decl: &ast::FnDecl) -> io::Result<()> { word(&mut self.s, "|")?; - self.print_fn_args(decl, None, true)?; + self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; word(&mut self.s, "|")?; if let ast::FunctionRetTy::Default(..) = decl.output { @@ -2929,17 +2928,14 @@ impl<'a> State<'a> { match input.ty.node { ast::TyKind::Infer if is_closure => self.print_pat(&input.pat)?, _ => { - let (mutbl, invalid) = match input.pat.node { - PatKind::Ident(ast::BindingMode::ByValue(mutbl), ident, _) | - PatKind::Ident(ast::BindingMode::ByRef(mutbl), ident, _) => { - (mutbl, ident.node.name == keywords::Invalid.name()) - } - _ => (ast::Mutability::Immutable, false) - }; - if let Some(eself) = input.to_self() { - self.print_explicit_self(&eself.node, mutbl)?; + self.print_explicit_self(&eself)?; } else { + let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node { + ident.node.name == keywords::Invalid.name() + } else { + false + }; if !invalid { self.print_pat(&input.pat)?; word(&mut self.s, ":")?; @@ -2980,8 +2976,7 @@ impl<'a> State<'a> { unsafety: ast::Unsafety, decl: &ast::FnDecl, name: Option, - generics: &ast::Generics, - opt_explicit_self: Option<&ast::SelfKind>) + generics: &ast::Generics) -> io::Result<()> { self.ibox(INDENT_UNIT)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { @@ -3002,7 +2997,6 @@ impl<'a> State<'a> { abi, name, &generics, - opt_explicit_self, &ast::Visibility::Inherited)?; self.end() } @@ -3126,8 +3120,7 @@ mod tests { let generics = ast::Generics::default(); assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, ast::Constness::NotConst, - abba_ident, - None, &generics), + abba_ident, &generics), "fn abba()"); } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 8eeb61e0de46c..6fbbed2ee9842 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -59,7 +59,6 @@ struct TestCtxt<'a> { testfns: Vec, reexport_test_harness_main: Option, is_test_crate: bool, - config: ast::CrateConfig, // top-level re-export submodule, filled out after folding is finished toplevel_reexport: Option, @@ -68,14 +67,9 @@ struct TestCtxt<'a> { // Traverse the crate, collecting all the test functions, eliding any // existing main functions, and synthesizing a main test harness pub fn modify_for_testing(sess: &ParseSess, - cfg: &ast::CrateConfig, + should_test: bool, krate: ast::Crate, span_diagnostic: &errors::Handler) -> ast::Crate { - // We generate the test harness when building in the 'test' - // configuration, either with the '--test' or '--cfg test' - // command line options. - let should_test = attr::contains_name(&krate.config, "test"); - // Check for #[reexport_test_harness_main = "some_name"] which // creates a `use some_name = __test::main;`. This needs to be // unconditional, so that the attribute is still marked as used in @@ -85,9 +79,9 @@ pub fn modify_for_testing(sess: &ParseSess, "reexport_test_harness_main"); if should_test { - generate_test_harness(sess, reexport_test_harness_main, krate, cfg, span_diagnostic) + generate_test_harness(sess, reexport_test_harness_main, krate, span_diagnostic) } else { - strip_test_functions(span_diagnostic, krate) + strip_test_functions(krate) } } @@ -271,7 +265,6 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec, fn generate_test_harness(sess: &ParseSess, reexport_test_harness_main: Option, krate: ast::Crate, - cfg: &ast::CrateConfig, sd: &errors::Handler) -> ast::Crate { // Remove the entry points let mut cleaner = EntryPointCleaner { depth: 0 }; @@ -281,14 +274,13 @@ fn generate_test_harness(sess: &ParseSess, let mut cx: TestCtxt = TestCtxt { sess: sess, span_diagnostic: sd, - ext_cx: ExtCtxt::new(sess, cfg.clone(), + ext_cx: ExtCtxt::new(sess, vec![], ExpansionConfig::default("test".to_string()), &mut feature_gated_cfgs), path: Vec::new(), testfns: Vec::new(), reexport_test_harness_main: reexport_test_harness_main, is_test_crate: is_test_crate(&krate), - config: krate.config.clone(), toplevel_reexport: None, }; cx.ext_cx.crate_root = Some("std"); @@ -312,14 +304,17 @@ fn generate_test_harness(sess: &ParseSess, return res; } -fn strip_test_functions(diagnostic: &errors::Handler, krate: ast::Crate) - -> ast::Crate { +fn strip_test_functions(krate: ast::Crate) -> ast::Crate { // When not compiling with --test we should not compile the // #[test] functions - config::strip_items(diagnostic, krate, |attrs| { - !attr::contains_name(&attrs[..], "test") && - !attr::contains_name(&attrs[..], "bench") - }) + struct StripTests; + impl config::CfgFolder for StripTests { + fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { + !attr::contains_name(attrs, "test") && !attr::contains_name(attrs, "bench") + } + } + + StripTests.fold_crate(krate) } /// Craft a span that will be ignored by the stability lint's diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index e692ec4452cdd..919dd84b11799 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -129,10 +129,6 @@ impl<'v> Visitor<'v> for NodeCounter { self.count += 1; walk_lifetime_def(self, lifetime) } - fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { - self.count += 1; - walk_explicit_self(self, es) - } fn visit_mac(&mut self, _mac: &'v Mac) { self.count += 1; walk_mac(self, _mac) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f50a480e5e55a..a1d8e056b0257 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -26,7 +26,7 @@ use abi::Abi; use ast::*; use attr::ThinAttributesExt; -use codemap::Span; +use codemap::{Span, Spanned}; #[derive(Copy, Clone, PartialEq, Eq)] pub enum FnKind<'a> { @@ -99,9 +99,6 @@ pub trait Visitor<'v> : Sized { fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { walk_lifetime_def(self, lifetime) } - fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { - walk_explicit_self(self, es) - } fn visit_mac(&mut self, _mac: &'v Mac) { panic!("visit_mac disabled by default"); // NB: see note about macros above. @@ -149,17 +146,24 @@ macro_rules! walk_list { } pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option) { - for name in opt_name { + if let Some(name) = opt_name { visitor.visit_name(span, name); } } pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option) { - for ident in opt_ident { + if let Some(ident) = opt_ident { visitor.visit_ident(span, ident); } } +pub fn walk_opt_sp_ident<'v, V: Visitor<'v>>(visitor: &mut V, + opt_sp_ident: &Option>) { + if let Some(ref sp_ident) = *opt_sp_ident { + visitor.visit_ident(sp_ident.span, sp_ident.node); + } +} + pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) { visitor.visit_name(span, ident.name); } @@ -196,24 +200,6 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); } -pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, - explicit_self: &'v ExplicitSelf) { - match explicit_self.node { - SelfKind::Static => {}, - SelfKind::Value(ident) => { - visitor.visit_ident(explicit_self.span, ident) - } - SelfKind::Region(ref opt_lifetime, _, ident) => { - visitor.visit_ident(explicit_self.span, ident); - walk_list!(visitor, visit_lifetime, opt_lifetime); - } - SelfKind::Explicit(ref typ, ident) => { - visitor.visit_ident(explicit_self.span, ident); - visitor.visit_ty(typ) - } - } -} - pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef, _modifier: &'v TraitBoundModifier) @@ -247,12 +233,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_path(path, item.id); } ViewPathList(ref prefix, ref list) => { - if !list.is_empty() { - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } else { - visitor.visit_path(prefix, item.id); + visitor.visit_path(prefix, item.id); + for item in list { + visitor.visit_path_list_item(prefix, item) } } } @@ -369,7 +352,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyKind::Typeof(ref expression) => { visitor.visit_expr(expression) } - TyKind::Infer => {} + TyKind::Infer | TyKind::ImplicitSelf => {} TyKind::Mac(ref mac) => { visitor.visit_mac(mac) } @@ -382,12 +365,8 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, prefix: &'v Path, +pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, _prefix: &'v Path, item: &'v PathListItem) { - for segment in &prefix.segments { - visitor.visit_path_segment(prefix.span, segment); - } - walk_opt_ident(visitor, item.span, item.node.name()); walk_opt_ident(visitor, item.span, item.node.rename()); } @@ -423,11 +402,9 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { match pattern.node { - PatKind::TupleStruct(ref path, ref opt_children) => { + PatKind::TupleStruct(ref path, ref children, _) => { visitor.visit_path(path, pattern.id); - if let Some(ref children) = *opt_children { - walk_list!(visitor, visit_pat, children); - } + walk_list!(visitor, visit_pat, children); } PatKind::Path(ref path) => { visitor.visit_path(path, pattern.id); @@ -443,7 +420,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_pat(&field.node.pat) } } - PatKind::Tup(ref tuple_elements) => { + PatKind::Tuple(ref tuple_elements, _) => { walk_list!(visitor, visit_pat, tuple_elements); } PatKind::Box(ref subpattern) | @@ -553,7 +530,6 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, } FnKind::Method(_, ref sig, _) => { visitor.visit_generics(&sig.generics); - visitor.visit_explicit_self(&sig.explicit_self); } FnKind::Closure => {} } @@ -578,7 +554,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai walk_list!(visitor, visit_expr, default); } TraitItemKind::Method(ref sig, None) => { - visitor.visit_explicit_self(&sig.explicit_self); visitor.visit_generics(&sig.generics); walk_fn_decl(visitor, &sig.decl); } @@ -712,10 +687,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::While(ref subexpression, ref block, opt_ident) => { + ExprKind::While(ref subexpression, ref block, ref opt_sp_ident) => { visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) + walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { visitor.visit_pat(pattern); @@ -723,21 +698,21 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::WhileLet(ref pattern, ref subexpression, ref block, opt_ident) => { + ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => { visitor.visit_pat(pattern); visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) + walk_opt_sp_ident(visitor, opt_sp_ident); } - ExprKind::ForLoop(ref pattern, ref subexpression, ref block, opt_ident) => { + ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => { visitor.visit_pat(pattern); visitor.visit_expr(subexpression); visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) + walk_opt_sp_ident(visitor, opt_sp_ident); } - ExprKind::Loop(ref block, opt_ident) => { + ExprKind::Loop(ref block, ref opt_sp_ident) => { visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) + walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::Match(ref subexpression, ref arms) => { visitor.visit_expr(subexpression); @@ -781,9 +756,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => { - for sp_ident in opt_sp_ident { - visitor.visit_ident(sp_ident.span, sp_ident.node); - } + walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index dce808756cf6a..3d5f32eadb3c4 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -52,22 +52,36 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) } let res = str_to_ident(&res_str); - let e = P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, - ast::Path { - span: sp, - global: false, - segments: vec!( - ast::PathSegment { - identifier: res, - parameters: ast::PathParameters::none(), - } - ) - } - ), - span: sp, - attrs: None, - }); - MacEager::expr(e) + struct Result { ident: ast::Ident, span: Span }; + + impl Result { + fn path(&self) -> ast::Path { + let segment = ast::PathSegment { + identifier: self.ident, + parameters: ast::PathParameters::none() + }; + ast::Path { span: self.span, global: false, segments: vec![segment] } + } + } + + impl base::MacResult for Result { + fn make_expr(self: Box) -> Option> { + Some(P(ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::Path(None, self.path()), + span: self.span, + attrs: None, + })) + } + + fn make_ty(self: Box) -> Option> { + Some(P(ast::Ty { + id: ast::DUMMY_NODE_ID, + node: ast::TyKind::Path(None, self.path()), + span: self.span, + })) + } + } + + Box::new(Result { ident: res, span: sp }) } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 20fb4bf32ccb7..9095230df630a 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -197,7 +197,7 @@ use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; -use syntax::codemap::{self, DUMMY_SP}; +use syntax::codemap::{self, respan, DUMMY_SP}; use syntax::codemap::Span; use syntax::errors::Handler; use syntax::util::move_map::MoveMap; @@ -806,25 +806,21 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef, type_ident: Ident, generics: &Generics) - -> (ast::ExplicitSelf, Vec>, Vec>, Vec<(Ident, P)>) { + -> (Option, Vec>, Vec>, Vec<(Ident, P)>) { let mut self_args = Vec::new(); let mut nonself_args = Vec::new(); let mut arg_tys = Vec::new(); let mut nonstatic = false; - let ast_explicit_self = match self.explicit_self { - Some(ref self_ptr) => { - let (self_expr, explicit_self) = - ty::get_explicit_self(cx, trait_.span, self_ptr); + let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { + let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr); - self_args.push(self_expr); - nonstatic = true; + self_args.push(self_expr); + nonstatic = true; - explicit_self - } - None => codemap::respan(trait_.span, ast::SelfKind::Static), - }; + explicit_self + }); for (i, ty) in self.args.iter().enumerate() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); @@ -857,24 +853,20 @@ impl<'a> MethodDef<'a> { type_ident: Ident, generics: &Generics, abi: Abi, - explicit_self: ast::ExplicitSelf, + explicit_self: Option, arg_types: Vec<(Ident, P)> , body: P) -> ast::ImplItem { // create the generics that aren't for Self let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); - let self_arg = match explicit_self.node { - ast::SelfKind::Static => None, - // creating fresh self id - _ => Some(ast::Arg::from_self(explicit_self.clone(), trait_.span, - ast::Mutability::Immutable)), - }; let args = { - let args = arg_types.into_iter().map(|(name, ty)| { - cx.arg(trait_.span, name, ty) - }); - self_arg.into_iter().chain(args).collect() + let self_args = explicit_self.map(|explicit_self| { + ast::Arg::from_self(explicit_self, respan(trait_.span, keywords::SelfValue.ident())) + }); + let nonself_args = arg_types.into_iter() + .map(|(name, ty)| cx.arg(trait_.span, name, ty)); + self_args.into_iter().chain(nonself_args).collect() }; let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); @@ -900,7 +892,6 @@ impl<'a> MethodDef<'a> { node: ast::ImplItemKind::Method(ast::MethodSig { generics: fn_generics, abi: abi, - explicit_self: explicit_self, unsafety: unsafety, constness: ast::Constness::NotConst, decl: fn_decl diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index e31d45d91a59f..b581f5267eaac 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -15,11 +15,10 @@ pub use self::PtrTy::*; pub use self::Ty::*; use syntax::ast; -use syntax::ast::{Expr,Generics,Ident}; +use syntax::ast::{Expr, Generics, Ident, SelfKind}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::{Span,respan}; -use syntax::parse::token::keywords; use syntax::ptr::P; /// The types of pointers @@ -258,12 +257,11 @@ impl<'a> LifetimeBounds<'a> { pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option) -> (P, ast::ExplicitSelf) { - // this constructs a fresh `self` path, which will match the fresh `self` binding - // created below. + // this constructs a fresh `self` path let self_path = cx.expr_self(span); match *self_ptr { None => { - (self_path, respan(span, ast::SelfKind::Value(keywords::SelfValue.ident()))) + (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))) } Some(ref ptr) => { let self_ty = respan( @@ -271,7 +269,7 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option) match *ptr { Borrowed(ref lt, mutbl) => { let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name)); - ast::SelfKind::Region(lt, mutbl, keywords::SelfValue.ident()) + SelfKind::Region(lt, mutbl) } Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition") }); diff --git a/src/rt/miniz.c b/src/rt/miniz.c index 2b803b06d0993..2daca9378a4a9 100644 --- a/src/rt/miniz.c +++ b/src/rt/miniz.c @@ -575,7 +575,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex { mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); - for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; + for ( i = 0; i <= 143; ++i) *p++ = 8; + for ( ; i <= 255; ++i) *p++ = 9; + for ( ; i <= 279; ++i) *p++ = 7; + for ( ; i <= 287; ++i) *p++ = 8; } else { @@ -1393,7 +1396,10 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; } - if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; + if (!dist) break; + p = s; q = d->m_dict + probe_pos; + for (probe_len = 0; probe_len < max_match_len; probe_len++) + if (*p++ != *q++) break; if (probe_len > match_len) { *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index b772525122001..06e547f0dd037 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -40,3 +40,5 @@ fn main() { //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; } + +//~ TRANS_ITEM drop-glue i8 diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index 45ba441bc8ba6..5c67ab7a82646 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -78,3 +78,5 @@ fn main() //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; } + +//~ TRANS_ITEM drop-glue i8 diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs index f849a6c9b18b8..8c425507975ca 100644 --- a/src/test/codegen/stores.rs +++ b/src/test/codegen/stores.rs @@ -26,8 +26,8 @@ pub struct Bytes { #[no_mangle] #[rustc_no_mir] // FIXME #27840 MIR has different codegen. pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { -// CHECK: [[VAR:%[0-9]+]] = bitcast [4 x i8]* %y to i32* -// CHECK: store i32 %{{.*}}, i32* [[VAR]], align 1 +// CHECK: store i32 %{{.*}}, i32* %{{.*}}, align 1 +// CHECK: [[VAR:%[0-9]+]] = bitcast i32* %{{.*}} to [4 x i8]* *x = y; } @@ -37,7 +37,7 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { #[no_mangle] #[rustc_no_mir] // FIXME #27840 MIR has different codegen. pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) { -// CHECK: [[VAR:%[0-9]+]] = bitcast %Bytes* %y to i32* -// CHECK: store i32 %{{.*}}, i32* [[VAR]], align 1 +// CHECK: store i32 %{{.*}}, i32* %{{.*}}, align 1 +// CHECK: [[VAR:%[0-9]+]] = bitcast i32* %{{.*}} to %Bytes* *x = y; } diff --git a/src/test/compile-fail/E0055.rs b/src/test/compile-fail/E0055.rs index cb78f4b3bb597..f86d7ec114b93 100644 --- a/src/test/compile-fail/E0055.rs +++ b/src/test/compile-fail/E0055.rs @@ -19,5 +19,4 @@ fn main() { let foo = Foo; let ref_foo = &&Foo; ref_foo.foo(); //~ ERROR E0055 - //~^ ERROR E0275 } diff --git a/src/test/compile-fail/E0062.rs b/src/test/compile-fail/E0062.rs new file mode 100644 index 0000000000000..86ec7db14b5c1 --- /dev/null +++ b/src/test/compile-fail/E0062.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + x: i32 +} + +fn main() { + let x = Foo { + x: 0, + x: 0, //~ ERROR E0062 + }; +} diff --git a/src/test/compile-fail/E0063.rs b/src/test/compile-fail/E0063.rs new file mode 100644 index 0000000000000..c94f807d807ca --- /dev/null +++ b/src/test/compile-fail/E0063.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + x: i32, + y: i32 +} + +fn main() { + let x = Foo { x: 0 }; //~ ERROR E0063 +} diff --git a/src/test/compile-fail/E0067.rs b/src/test/compile-fail/E0067.rs new file mode 100644 index 0000000000000..a3fc30ee1c71a --- /dev/null +++ b/src/test/compile-fail/E0067.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::LinkedList; + +fn main() { + LinkedList::new() += 1; //~ ERROR E0368 + //~^ ERROR E0067 +} diff --git a/src/test/compile-fail/E0069.rs b/src/test/compile-fail/E0069.rs new file mode 100644 index 0000000000000..d164d86348784 --- /dev/null +++ b/src/test/compile-fail/E0069.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() -> u8 { + return; //~ ERROR E0069 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0070.rs b/src/test/compile-fail/E0070.rs new file mode 100644 index 0000000000000..ba66bd03aef9d --- /dev/null +++ b/src/test/compile-fail/E0070.rs @@ -0,0 +1,23 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const SOME_CONST : i32 = 12; + +fn some_other_func() {} + +fn some_function() { + SOME_CONST = 14; //~ ERROR E0070 + 1 = 3; //~ ERROR E0070 + some_other_func() = 4; //~ ERROR E0070 + //~^ ERROR E0308 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0071.rs b/src/test/compile-fail/E0071.rs new file mode 100644 index 0000000000000..658c8fb155114 --- /dev/null +++ b/src/test/compile-fail/E0071.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { FirstValue(i32) } + +fn main() { + let u = Foo::FirstValue { value: 0 }; //~ ERROR E0071 + let t = u32 { value: 4 }; //~ ERROR E0071 +} diff --git a/src/test/compile-fail/E0072.rs b/src/test/compile-fail/E0072.rs new file mode 100644 index 0000000000000..2f96ba1046d74 --- /dev/null +++ b/src/test/compile-fail/E0072.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct ListNode { //~ ERROR E0072 + head: u8, + tail: Option, +} + +fn main() { +} diff --git a/src/test/compile-fail/E0075.rs b/src/test/compile-fail/E0075.rs new file mode 100644 index 0000000000000..d7783904e2e98 --- /dev/null +++ b/src/test/compile-fail/E0075.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad; //~ ERROR E0075 + +fn main() { +} diff --git a/src/test/compile-fail/E0076.rs b/src/test/compile-fail/E0076.rs new file mode 100644 index 0000000000000..b0f02a03e0051 --- /dev/null +++ b/src/test/compile-fail/E0076.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(u16, u32, u32); //~ ERROR E0076 + +fn main() { +} diff --git a/src/test/compile-fail/E0077.rs b/src/test/compile-fail/E0077.rs new file mode 100644 index 0000000000000..b074e90b2c01f --- /dev/null +++ b/src/test/compile-fail/E0077.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(String); //~ ERROR E0077 + +fn main() { +} diff --git a/src/test/compile-fail/E0079.rs b/src/test/compile-fail/E0079.rs new file mode 100644 index 0000000000000..23957c72ff00e --- /dev/null +++ b/src/test/compile-fail/E0079.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + Q = "32" //~ ERROR E0079 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0080.rs b/src/test/compile-fail/E0080.rs new file mode 100644 index 0000000000000..0329209d44bc7 --- /dev/null +++ b/src/test/compile-fail/E0080.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Enum { + X = (1 << 500), //~ ERROR E0080 + Y = (1 / 0) //~ ERROR E0080 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0081.rs b/src/test/compile-fail/E0081.rs new file mode 100644 index 0000000000000..b63265564b334 --- /dev/null +++ b/src/test/compile-fail/E0081.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Enum { + P = 3, + X = 3, //~ ERROR E0081 + Y = 5 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0084.rs b/src/test/compile-fail/E0084.rs new file mode 100644 index 0000000000000..c579101325f5d --- /dev/null +++ b/src/test/compile-fail/E0084.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[repr(i32)] +enum Foo {} //~ ERROR E0084 + +fn main() { +} diff --git a/src/test/compile-fail/E0087.rs b/src/test/compile-fail/E0087.rs new file mode 100644 index 0000000000000..ec559fc8389d2 --- /dev/null +++ b/src/test/compile-fail/E0087.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() {} + +fn main() { + foo::(); //~ ERROR E0087 +} diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs new file mode 100644 index 0000000000000..0b235aa240c3c --- /dev/null +++ b/src/test/compile-fail/E0088.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() {} + +fn main() { + f::<'static>(); //~ ERROR E0088 +} diff --git a/src/test/compile-fail/E0089.rs b/src/test/compile-fail/E0089.rs new file mode 100644 index 0000000000000..3b52f76bf09cc --- /dev/null +++ b/src/test/compile-fail/E0089.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() {} + +fn main() { + foo::(); //~ ERROR E0089 +} diff --git a/src/test/compile-fail/E0091.rs b/src/test/compile-fail/E0091.rs new file mode 100644 index 0000000000000..da988dbf819ac --- /dev/null +++ b/src/test/compile-fail/E0091.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type Foo = u32; //~ ERROR E0091 +type Foo2 = Box; //~ ERROR E0091 + +fn main() { +} diff --git a/src/test/compile-fail/E0092.rs b/src/test/compile-fail/E0092.rs new file mode 100644 index 0000000000000..b08164ac06d42 --- /dev/null +++ b/src/test/compile-fail/E0092.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn atomic_foo(); //~ ERROR E0092 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0093.rs b/src/test/compile-fail/E0093.rs new file mode 100644 index 0000000000000..9b23f6d984ee1 --- /dev/null +++ b/src/test/compile-fail/E0093.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn foo(); //~ ERROR E0093 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0094.rs b/src/test/compile-fail/E0094.rs new file mode 100644 index 0000000000000..3a31874b24422 --- /dev/null +++ b/src/test/compile-fail/E0094.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn size_of() -> usize; //~ ERROR E0094 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0101.rs b/src/test/compile-fail/E0101.rs new file mode 100644 index 0000000000000..7651626d44f85 --- /dev/null +++ b/src/test/compile-fail/E0101.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = |_| {}; //~ ERROR E0101 +} diff --git a/src/test/compile-fail/E0102.rs b/src/test/compile-fail/E0102.rs new file mode 100644 index 0000000000000..c4ddbab3e861a --- /dev/null +++ b/src/test/compile-fail/E0102.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = []; //~ ERROR E0102 +} diff --git a/src/test/compile-fail/E0106.rs b/src/test/compile-fail/E0106.rs new file mode 100644 index 0000000000000..f1cd530863d34 --- /dev/null +++ b/src/test/compile-fail/E0106.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + x: &bool, //~ ERROR E0106 +} +enum Bar { + A(u8), + B(&bool), //~ ERROR E0106 +} +type MyStr = &str; //~ ERROR E0106 + +fn main() { +} diff --git a/src/test/compile-fail/E0107.rs b/src/test/compile-fail/E0107.rs new file mode 100644 index 0000000000000..d27b70865bbfb --- /dev/null +++ b/src/test/compile-fail/E0107.rs @@ -0,0 +1,25 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo<'a>(&'a str); + +enum Bar { + A, + B, + C, +} + +struct Baz<'a> { + foo: Foo, //~ ERROR E0107 + bar: Bar<'a>, //~ ERROR E0107 +} + +fn main() { +} diff --git a/src/test/compile-fail/E0109.rs b/src/test/compile-fail/E0109.rs new file mode 100644 index 0000000000000..9fc478422504b --- /dev/null +++ b/src/test/compile-fail/E0109.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type X = u32; //~ ERROR E0109 + +fn main() { +} diff --git a/src/test/compile-fail/E0110.rs b/src/test/compile-fail/E0110.rs new file mode 100644 index 0000000000000..fd169f4acc5eb --- /dev/null +++ b/src/test/compile-fail/E0110.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type X = u32<'static>; //~ ERROR E0110 + +fn main() { +} diff --git a/src/test/compile-fail/E0116.rs b/src/test/compile-fail/E0116.rs new file mode 100644 index 0000000000000..4020aa9475aaa --- /dev/null +++ b/src/test/compile-fail/E0116.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +impl Vec {} //~ ERROR E0116 + +fn main() { +} diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs index 43a0ad6b5f6bf..1020a5ba8a42e 100644 --- a/src/test/compile-fail/asm-misplaced-option.rs +++ b/src/test/compile-fail/asm-misplaced-option.rs @@ -9,6 +9,8 @@ // except according to those terms. // ignore-android +// ignore-arm +// ignore-aarch64 #![feature(asm, rustc_attrs)] diff --git a/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs index 497b0e63edfc1..764d05be879b8 100644 --- a/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs +++ b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -99,7 +99,7 @@ fn assign_field1<'a>(x: Own) { } fn assign_field2<'a>(x: &'a Own) { - x.y = 3; //~ ERROR cannot assign + x.y = 3; //~ ERROR cannot borrow } fn assign_field3<'a>(x: &'a mut Own) { diff --git a/src/test/compile-fail/expanded-cfg.rs b/src/test/compile-fail/expanded-cfg.rs index 2f74aeba9eb43..77351f6e4f171 100644 --- a/src/test/compile-fail/expanded-cfg.rs +++ b/src/test/compile-fail/expanded-cfg.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] +#![feature(custom_attribute, rustc_attrs)] macro_rules! mac { {} => { @@ -16,7 +16,13 @@ macro_rules! mac { mod m { #[lang_item] fn f() {} + + #[cfg_attr(target_thread_local, custom)] + fn g() {} } + + #[cfg(attr)] + unconfigured_invocation!(); } } diff --git a/src/test/compile-fail/invalid-macro-matcher.rs b/src/test/compile-fail/invalid-macro-matcher.rs index 03bcaab4a9db5..a0ac5d4c72041 100644 --- a/src/test/compile-fail/invalid-macro-matcher.rs +++ b/src/test/compile-fail/invalid-macro-matcher.rs @@ -9,7 +9,7 @@ // except according to those terms. macro_rules! invalid { - _ => (); //~^ ERROR invalid macro matcher + _ => (); //~ ERROR invalid macro matcher } fn main() { diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index 6b81afe13c671..5e816bcfa61e4 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -32,7 +32,8 @@ impl MaybeDog { impl Groom for cat { fn shave(other: usize) { whiskers -= other; - //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`? + //~^ ERROR: unresolved name `whiskers` + //~| HELP this is an associated function shave(4); //~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`? purr(); @@ -77,7 +78,8 @@ impl cat { pub fn grow_older(other:usize) { whiskers = 4; - //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`? + //~^ ERROR: unresolved name `whiskers` + //~| HELP this is an associated function purr_louder(); //~^ ERROR: unresolved name `purr_louder` } @@ -86,5 +88,6 @@ impl cat { fn main() { self += 1; //~^ ERROR: unresolved name `self` + //~| HELP: Module // it's a bug if this suggests a missing `self` as we're not in a method } diff --git a/src/test/compile-fail/issue-24819.rs b/src/test/compile-fail/issue-24819.rs new file mode 100644 index 0000000000000..52f5f1cd079eb --- /dev/null +++ b/src/test/compile-fail/issue-24819.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashSet; + +fn main() { + let mut v = Vec::new(); + foo(&mut v); + //~^ ERROR mismatched types + //~| expected struct `std::collections::HashSet`, found struct `std::vec::Vec` +} + +fn foo(h: &mut HashSet) { +} diff --git a/src/test/compile-fail/issue-32004.rs b/src/test/compile-fail/issue-32004.rs index 0227a80fd75d3..8d74154655fce 100644 --- a/src/test/compile-fail/issue-32004.rs +++ b/src/test/compile-fail/issue-32004.rs @@ -18,12 +18,12 @@ struct S; fn main() { match Foo::Baz { Foo::Bar => {} - //~^ ERROR this pattern has 0 fields, but the corresponding variant + //~^ ERROR `Foo::Bar` does not name a tuple variant or a tuple struct _ => {} } match S { S(()) => {} - //~^ ERROR this pattern has 1 field, but the corresponding struct + //~^ ERROR `S` does not name a tuple variant or a tuple struct } } diff --git a/src/test/compile-fail/issue-33819.rs b/src/test/compile-fail/issue-33819.rs new file mode 100644 index 0000000000000..9c9677c1e9863 --- /dev/null +++ b/src/test/compile-fail/issue-33819.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +fn main() { + let mut op = Some(2); + match op { + Some(ref v) => { let a = &mut v; }, + //~^ ERROR:cannot borrow immutable + //~| use `ref mut v` here to make mutable + None => {}, + } +} diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index 817b675aedfe8..a69188da58d16 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that we report errors at macro definition, not expansion. +#![feature(type_macros)] macro_rules! foo { ($a:expr) => $a; //~ ERROR macro rhs must be delimited } fn main() { - foo!(0); + foo!(0); // Check that we report errors at macro definition, not expansion. + + let _: cfg!(foo) = (); //~ ERROR non-type macro in type position + derive!(); //~ ERROR `derive` can only be used in attributes } diff --git a/src/test/compile-fail/macro-invalid-fragment-spec.rs b/src/test/compile-fail/macro-invalid-fragment-spec.rs new file mode 100644 index 0000000000000..ca6cd664e7385 --- /dev/null +++ b/src/test/compile-fail/macro-invalid-fragment-spec.rs @@ -0,0 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo( + ($x:foo) => () + //~^ ERROR invalid fragment specifier + //~| HELP valid fragment specifiers are +); + +fn main() { + foo!(foo); +} diff --git a/src/test/compile-fail/macro-missing-delimiters.rs b/src/test/compile-fail/macro-missing-delimiters.rs new file mode 100644 index 0000000000000..eed2a207e89ef --- /dev/null +++ b/src/test/compile-fail/macro-missing-delimiters.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! baz( + baz => () //~ ERROR invalid macro matcher; +); + +fn main() { + baz!(baz); +} diff --git a/src/test/compile-fail/match-pattern-field-mismatch-2.rs b/src/test/compile-fail/match-pattern-field-mismatch-2.rs index e63ddf6c7fd9b..a4ba93ea17333 100644 --- a/src/test/compile-fail/match-pattern-field-mismatch-2.rs +++ b/src/test/compile-fail/match-pattern-field-mismatch-2.rs @@ -20,7 +20,7 @@ fn main() { color::rgb(_, _, _) => { } color::cmyk(_, _, _, _) => { } color::no_color(_) => { } - //~^ ERROR this pattern has 1 field, but the corresponding variant has no fields + //~^ ERROR `color::no_color` does not name a tuple variant or a tuple struct } } } diff --git a/src/test/compile-fail/mir-dataflow/README.md b/src/test/compile-fail/mir-dataflow/README.md new file mode 100644 index 0000000000000..a3ab14b23c7db --- /dev/null +++ b/src/test/compile-fail/mir-dataflow/README.md @@ -0,0 +1,53 @@ +This directory contains unit tests for the MIR-based dataflow +analysis. + +These unit tests check the dataflow analysis by embedding calls to a +special `rustc_peek` intrinsic within the code, in tandem with an +attribute `#[rustc_mir(rustc_peek_maybe_init)]` (\*). With that +attribute in place, `rustc_peek` calls are a signal to the compiler to +lookup the computed dataflow state for the Lvalue corresponding to the +argument expression being fed to `rustc_peek`. If the dataflow state +for that Lvalue is a 1-bit at that point in the control flow, then no +error is emitted by the compiler at that point; if it is a 0-bit, then +that invocation of `rustc_peek` will emit an error with the message +"rustc_peek: bit not set". + +(\*): Or `#[rustc_mir(rustc_peek_maybe_uninit)]`, and perhaps other +variants in the future. + +The end effect is that one can write unit tests for MIR dataflow that +perform simple-queries of the computed dataflow state, and the tests +should be able to be robust in the face of changes to how MIR is +represented or constructed. + +---- + +Sometimes understanding the dataflow results is difficult without +looking at the actual MIR control-flow graph being processed with the +corresponding GEN and KILL sets. + +For a graphviz-rendering with dataflow annotations, add the attribute +`#[rustc_mir(borrowck_graphviz_postflow="/path/to/suffix.dot")]` to +the function in question. (You can change the content of +`"suffix.dot"` to control the filenames used for the output). This +will generate a separate file for each dataflow analysis, adding a +prefix (corresponding to the name of the analysis) to the filename in +each generated output path. + + * For example, the above attribute will currently cause two files to + be generated: `/path/to/maybe_init_suffix.dot` and + `/path/to/maybe_uninit_suffix.dot`. + + * The generated `.dot` file shows both the computed dataflow results + on *entry* to each block, as well as the gen- and kill-sets that + were so-called "transfer functions" summarizing the effect of each + basic block. + + * (In addition to the `borrowck_graphviz_postflow` attribute-key + noted above, there is also `borrowck_graphviz_preflow`; it has the + same interface and generates the same set of files, but it renders + the dataflow state after building the gen- and kill-sets but + *before* running the dataflow analysis itself, so each entry-set is + just the initial default state for that dataflow analysis. This is + less useful for understanding the error message output in these + tests.) diff --git a/src/test/compile-fail/mir-dataflow/def-inits-1.rs b/src/test/compile-fail/mir-dataflow/def-inits-1.rs new file mode 100644 index 0000000000000..a133ddc15f1ac --- /dev/null +++ b/src/test/compile-fail/mir-dataflow/def-inits-1.rs @@ -0,0 +1,63 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir_borrowck] +#[rustc_mir(rustc_peek_definite_init,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized + unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + + // All function formal parameters start off initialized. + + unsafe { rustc_peek(&x) }; + unsafe { rustc_peek(&y) }; + unsafe { rustc_peek(&z) }; + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + // `z` may be uninitialized here. + unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set + + // `y` is definitely uninitialized here. + unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + + // `x` is still (definitely) initialized (replace above is a reborrow). + unsafe { rustc_peek(&x); } + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + + // `ret` is now definitely initialized (via `if` above). + unsafe { rustc_peek(&ret); } + + ret +} +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/src/test/compile-fail/mir-dataflow/inits-1.rs b/src/test/compile-fail/mir-dataflow/inits-1.rs new file mode 100644 index 0000000000000..949688098f622 --- /dev/null +++ b/src/test/compile-fail/mir-dataflow/inits-1.rs @@ -0,0 +1,65 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// General test of maybe_inits state computed by MIR dataflow. + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir_borrowck] +#[rustc_mir(rustc_peek_maybe_init,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized, so we get an error report here. + unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + + // All function formal parameters start off initialized. + + unsafe { rustc_peek(&x) }; + unsafe { rustc_peek(&y) }; + unsafe { rustc_peek(&z) }; + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + + // `z` may be initialized here. + unsafe { rustc_peek(&z); } + + // `y` is definitely uninitialized here. + unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set + + // `x` is still (definitely) initialized (replace above is a reborrow). + unsafe { rustc_peek(&x); } + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + + // `ret` is now definitely initialized (via `if` above). + unsafe { rustc_peek(&ret); } + + ret +} + +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/src/test/compile-fail/mir-dataflow/uninits-1.rs b/src/test/compile-fail/mir-dataflow/uninits-1.rs new file mode 100644 index 0000000000000..c13daae24f35d --- /dev/null +++ b/src/test/compile-fail/mir-dataflow/uninits-1.rs @@ -0,0 +1,63 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir_borrowck] +#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized + unsafe { rustc_peek(&ret); } + + // All function formal parameters start off initialized. + + unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set + unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set + unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + // `z` may be uninitialized here. + unsafe { rustc_peek(&z); } + + // `y` is definitely uninitialized here. + unsafe { rustc_peek(&y); } + + // `x` is still (definitely) initialized (replace above is a reborrow). + unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + unsafe { rustc_peek(&x); } + + // `ret` is now definitely initialized (via `if` above). + unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set + + ret +} +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/src/test/compile-fail/mir-dataflow/uninits-2.rs b/src/test/compile-fail/mir-dataflow/uninits-2.rs new file mode 100644 index 0000000000000..e0bf42534499c --- /dev/null +++ b/src/test/compile-fail/mir-dataflow/uninits-2.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir_borrowck] +#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)] +fn foo(x: &mut S) { + // `x` is initialized here, so maybe-uninit bit is 0. + + unsafe { *rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set + + ::std::mem::drop(x); + + // `x` definitely uninitialized here, so maybe-uninit bit is 1. + unsafe { rustc_peek(&x) }; +} +fn main() { + foo(&mut S(13)); + foo(&mut S(13)); +} diff --git a/src/test/compile-fail/pat-tuple-bad-type.rs b/src/test/compile-fail/pat-tuple-bad-type.rs new file mode 100644 index 0000000000000..0d50a30dd0526 --- /dev/null +++ b/src/test/compile-fail/pat-tuple-bad-type.rs @@ -0,0 +1,27 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn main() { + let x; + + match x { + (..) => {} //~ ERROR the type of this value must be known in this context + _ => {} + } + + match 0u8 { + (..) => {} //~ ERROR mismatched types + _ => {} + } + + x = 10; +} diff --git a/src/test/compile-fail/pat-tuple-feature-gate.rs b/src/test/compile-fail/pat-tuple-feature-gate.rs new file mode 100644 index 0000000000000..55ca05bdef381 --- /dev/null +++ b/src/test/compile-fail/pat-tuple-feature-gate.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match 0 { + (..) => {} //~ ERROR `..` in tuple patterns is experimental + (pat, ..) => {} //~ ERROR `..` in tuple patterns is experimental + S(pat, ..) => {} //~ ERROR `..` in tuple struct patterns is experimental + } +} diff --git a/src/test/compile-fail/pat-tuple-overfield.rs b/src/test/compile-fail/pat-tuple-overfield.rs new file mode 100644 index 0000000000000..034ef4a72e21c --- /dev/null +++ b/src/test/compile-fail/pat-tuple-overfield.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +struct S(u8, u8, u8); + +fn main() { + match (1, 2, 3) { + (1, 2, 3, 4) => {} //~ ERROR mismatched types + (1, 2, .., 3, 4) => {} //~ ERROR mismatched types + _ => {} + } + match S(1, 2, 3) { + S(1, 2, 3, 4) => {} + //~^ ERROR this pattern has 4 fields, but the corresponding struct has 3 fields + S(1, 2, .., 3, 4) => {} + //~^ ERROR this pattern has 4 fields, but the corresponding struct has 3 fields + _ => {} + } +} diff --git a/src/test/compile-fail/pattern-error-continue.rs b/src/test/compile-fail/pattern-error-continue.rs index d9f3bb3c40f8d..507012e8c5c06 100644 --- a/src/test/compile-fail/pattern-error-continue.rs +++ b/src/test/compile-fail/pattern-error-continue.rs @@ -25,7 +25,7 @@ fn f(_c: char) {} fn main() { match A::B(1, 2) { A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but - A::D(_) => (), //~ ERROR this pattern has 1 field, but + A::D(_) => (), //~ ERROR `A::D` does not name a tuple variant or a tuple struct _ => () } match 'c' { diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs index abffd33e3f83e..6e60a373d9b0c 100644 --- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs +++ b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs @@ -34,7 +34,8 @@ impl<'a, 't> Foo<'a, 't> for &'a isize { } fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { - //~^ ERROR method `wrong_bound1` has an incompatible type for trait + //~^ ERROR method not compatible with trait + //~^^ ERROR method not compatible with trait // // Note: This is a terrible error message. It is caused // because, in the trait, 'b is early bound, and in the impl, diff --git a/src/test/compile-fail/regions-trait-1.rs b/src/test/compile-fail/regions-trait-1.rs index 01439ce5e6877..9cd08656b62c5 100644 --- a/src/test/compile-fail/regions-trait-1.rs +++ b/src/test/compile-fail/regions-trait-1.rs @@ -23,7 +23,7 @@ impl<'a> get_ctxt for has_ctxt<'a> { // Here an error occurs because we used `&self` but // the definition used `&`: - fn get_ctxt(&self) -> &'a ctxt { //~ ERROR method `get_ctxt` has an incompatible type + fn get_ctxt(&self) -> &'a ctxt { //~ ERROR method not compatible with trait self.c } diff --git a/src/test/compile-fail/symbol-names/impl1.rs b/src/test/compile-fail/symbol-names/impl1.rs index 39bee26da20b8..93fa48b880fdf 100644 --- a/src/test/compile-fail/symbol-names/impl1.rs +++ b/src/test/compile-fail/symbol-names/impl1.rs @@ -25,7 +25,7 @@ mod bar { use foo::Foo; impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN5impl13bar26_$LT$impl$u20$foo..Foo$GT$3baz + #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz #[rustc_item_path] //~ ERROR item-path(bar::::baz) fn baz() { } } diff --git a/src/test/compile-fail/syntax-extension-minor.rs b/src/test/compile-fail/syntax-extension-minor.rs index 38a6834a9c460..3e36b126523a7 100644 --- a/src/test/compile-fail/syntax-extension-minor.rs +++ b/src/test/compile-fail/syntax-extension-minor.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// this now fails (correctly, I claim) because hygiene prevents -// the assembled identifier from being a reference to the binding. -#![feature(concat_idents)] +#![feature(concat_idents, type_macros)] pub fn main() { + struct Foo; + let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions + let asdf_fdsa = "<.<".to_string(); + // this now fails (correctly, I claim) because hygiene prevents + // the assembled identifier from being a reference to the binding. assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); //~^ ERROR: unresolved name `asdf_fdsa` diff --git a/src/test/compile-fail/unresolved_static_type_field.rs b/src/test/compile-fail/unresolved_static_type_field.rs new file mode 100644 index 0000000000000..80f6108f02d30 --- /dev/null +++ b/src/test/compile-fail/unresolved_static_type_field.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f(_: bool) {} + +struct Foo { + cx: bool, +} + +impl Foo { + fn bar() { + f(cx); //~ ERROR E0425 + //~| HELP this is an associated function + } +} + +fn main() {} diff --git a/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs b/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs index 2494dca0509b1..446d97e5bc054 100644 --- a/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs +++ b/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs @@ -17,5 +17,3 @@ pub type X = u32; pub type X = i32; pub type Y = char; - -pub fn foo() { } diff --git a/src/test/parse-fail/issue-33569.rs b/src/test/parse-fail/issue-33569.rs new file mode 100644 index 0000000000000..130278d778ab0 --- /dev/null +++ b/src/test/parse-fail/issue-33569.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z no-analysis + +macro_rules! foo { + { $+ } => { //~ ERROR expected identifier, found `+` + $(x)(y) //~ ERROR expected `*` or `+` + //~^ ERROR no rules expected the token `y` + } +} diff --git a/src/test/parse-fail/pat-lt-bracket-6.rs b/src/test/parse-fail/pat-lt-bracket-6.rs index 5ed8f6dee8cd8..fb78e558a951a 100644 --- a/src/test/parse-fail/pat-lt-bracket-6.rs +++ b/src/test/parse-fail/pat-lt-bracket-6.rs @@ -9,6 +9,5 @@ // except according to those terms. fn main() { - let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[` - //~^ ERROR expected one of `:`, `;`, `=`, or `@`, found `[` + let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[` } diff --git a/src/test/parse-fail/pat-lt-bracket-7.rs b/src/test/parse-fail/pat-lt-bracket-7.rs index 00681e6149785..d75589d8889e3 100644 --- a/src/test/parse-fail/pat-lt-bracket-7.rs +++ b/src/test/parse-fail/pat-lt-bracket-7.rs @@ -9,6 +9,5 @@ // except according to those terms. fn main() { - for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[` - //~^ ERROR expected one of `@` or `in`, found `[` + for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[` } diff --git a/src/test/compile-fail/E0024.rs b/src/test/parse-fail/pat-tuple-1.rs similarity index 74% rename from src/test/compile-fail/E0024.rs rename to src/test/parse-fail/pat-tuple-1.rs index 18f4dcf19d706..945d0740654e8 100644 --- a/src/test/compile-fail/E0024.rs +++ b/src/test/parse-fail/pat-tuple-1.rs @@ -8,15 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum Number { - Zero, - One(u32) -} +// compile-flags: -Z parse-only fn main() { - let x = Number::Zero; - match x { - Number::Zero(inside) => {}, //~ ERROR E0024 - Number::One(inside) => {}, + match 0 { + (, ..) => {} //~ ERROR expected pattern, found `,` } } diff --git a/src/test/parse-fail/pat-tuple-2.rs b/src/test/parse-fail/pat-tuple-2.rs new file mode 100644 index 0000000000000..ad52fa5787007 --- /dev/null +++ b/src/test/parse-fail/pat-tuple-2.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main() { + match 0 { + (pat, ..,) => {} //~ ERROR expected pattern, found `)` + } +} diff --git a/src/test/parse-fail/pat-tuple-3.rs b/src/test/parse-fail/pat-tuple-3.rs new file mode 100644 index 0000000000000..029dc7a295678 --- /dev/null +++ b/src/test/parse-fail/pat-tuple-3.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main() { + match 0 { + (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern + } +} diff --git a/src/test/parse-fail/pat-tuple-4.rs b/src/test/parse-fail/pat-tuple-4.rs new file mode 100644 index 0000000000000..f4c3afa07f106 --- /dev/null +++ b/src/test/parse-fail/pat-tuple-4.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main() { + match 0 { + (.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat` + } +} diff --git a/src/test/parse-fail/pat-tuple-5.rs b/src/test/parse-fail/pat-tuple-5.rs new file mode 100644 index 0000000000000..145d1f9d8ec76 --- /dev/null +++ b/src/test/parse-fail/pat-tuple-5.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main() { + match 0 { + (pat ..) => {} //~ ERROR expected one of `)`, `,`, or `@`, found `..` + } +} diff --git a/src/test/parse-fail/pat-tuple-6.rs b/src/test/parse-fail/pat-tuple-6.rs new file mode 100644 index 0000000000000..3252d92fe1b50 --- /dev/null +++ b/src/test/parse-fail/pat-tuple-6.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main() { + match 0 { + (pat) => {} //~ ERROR expected one of `,` or `@`, found `)` + } +} diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs index 3963d20df8873..da8769e616c3f 100644 --- a/src/test/run-make/unicode-input/span_length.rs +++ b/src/test/run-make/unicode-input/span_length.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rand, core)] +#![feature(rand)] use std::fs::File; use std::io::prelude::*; @@ -18,6 +18,11 @@ use std::process::Command; use std::__rand::{thread_rng, Rng}; use std::{char, env}; +pub fn check_old_skool() -> bool { + use std::env; + env::var("RUST_NEW_ERROR_FORMAT").is_err() +} + // creates a file with `fn main() { }` and checks the // compiler emits a span of the appropriate length (for the // "unresolved name" message); currently just using the number of code @@ -65,10 +70,17 @@ fn main() { let err = String::from_utf8_lossy(&result.stderr); - // the span should end the line (e.g no extra ~'s) - let expected_span = format!("^{}\n", repeat("~").take(n - 1) - .collect::()); - assert!(err.contains(&expected_span)); + if check_old_skool() { + // the span should end the line (e.g no extra ~'s) + let expected_span = format!("^{}\n", repeat("~").take(n - 1) + .collect::()); + assert!(err.contains(&expected_span)); + } else { + // the span should end the line (e.g no extra ~'s) + let expected_span = format!("^{}\n", repeat("^").take(n - 1) + .collect::()); + assert!(err.contains(&expected_span)); + } } // Test multi-column characters and tabs @@ -77,9 +89,6 @@ fn main() { r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#); } - // Extra characters. Every line is preceded by `filename:lineno ` - let offset = main_file.to_str().unwrap().len() + 3; - let result = Command::new("sh") .arg("-c") .arg(format!("{} {}", @@ -91,17 +100,31 @@ fn main() { // Test both the length of the snake and the leading spaces up to it - // First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset) - let expected_span = format!("\n{}^{}\n", - repeat(" ").take(offset + 7).collect::(), - repeat("~").take(8).collect::()); - assert!(err.contains(&expected_span)); - // Second snake is only 7 ~s long, with 36 preceding spaces, - // because rustc counts chars() now rather than width(). This - // is because width() functions are to be removed from - // librustc_unicode - let expected_span = format!("\n{}^{}\n", - repeat(" ").take(offset + 36).collect::(), - repeat("~").take(7).collect::()); - assert!(err.contains(&expected_span)); + if check_old_skool() { + // Extra characters. Every line is preceded by `filename:lineno ` + let offset = main_file.to_str().unwrap().len() + 3; + + // First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset) + let expected_span = format!("\n{}^{}\n", + repeat(" ").take(offset + 7).collect::(), + repeat("~").take(8).collect::()); + assert!(err.contains(&expected_span)); + // Second snake is only 7 ~s long, with 36 preceding spaces, + // because rustc counts chars() now rather than width(). This + // is because width() functions are to be removed from + // librustc_unicode + let expected_span = format!("\n{}^{}\n", + repeat(" ").take(offset + 36).collect::(), + repeat("~").take(7).collect::()); + assert!(err.contains(&expected_span)); + } else { + let expected_span = format!("\n |>{}{}\n", + repeat(" ").take(8).collect::(), + repeat("^").take(9).collect::()); + assert!(err.contains(&expected_span)); + let expected_span = format!("\n |>{}{}\n", + repeat(" ").take(37).collect::(), + repeat("^").take(8).collect::()); + assert!(err.contains(&expected_span)); + } } diff --git a/src/test/run-pass/foreign-truncated-arguments.rs b/src/test/run-pass/foreign-truncated-arguments.rs new file mode 100644 index 0000000000000..a983a4a95988c --- /dev/null +++ b/src/test/run-pass/foreign-truncated-arguments.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -O +// Regression test for https://github.com/rust-lang/rust/issues/33868 + +#[repr(C)] +pub struct S { + a: u32, + b: f32, + c: u32 +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn test(s: S) -> u32 { + s.c +} + +fn main() { + assert_eq!(test(S{a: 0, b: 0.0, c: 42}), 42); +} diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 5ac0378318508..a7748b6d6a2a4 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -47,8 +47,7 @@ fn check_status(status: std::process::ExitStatus) use std::os::unix::process::ExitStatusExt; assert!(!status.success()); - assert!(status.signal() != Some(libc::SIGSEGV) - && status.signal() != Some(libc::SIGBUS)); + assert_eq!(status.signal(), Some(libc::SIGABRT)); } #[cfg(not(unix))] diff --git a/src/test/run-pass/pat-tuple-1.rs b/src/test/run-pass/pat-tuple-1.rs new file mode 100644 index 0000000000000..c3796210a8e5b --- /dev/null +++ b/src/test/run-pass/pat-tuple-1.rs @@ -0,0 +1,104 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + match x { + (a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + (.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + (a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + S(.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-2.rs b/src/test/run-pass/pat-tuple-2.rs new file mode 100644 index 0000000000000..881e96a9d788c --- /dev/null +++ b/src/test/run-pass/pat-tuple-2.rs @@ -0,0 +1,34 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1,); + match x { + (2, ..) => panic!(), + (..) => () + } +} + +fn tuple_struct() { + struct S(u8); + + let x = S(1); + match x { + S(2, ..) => panic!(), + S(..) => () + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-3.rs b/src/test/run-pass/pat-tuple-3.rs new file mode 100644 index 0000000000000..94d33d41899a4 --- /dev/null +++ b/src/test/run-pass/pat-tuple-3.rs @@ -0,0 +1,40 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + let branch = match x { + (1, 1, ..) => 0, + (1, 2, 3, ..) => 1, + (1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + let branch = match x { + S(1, 1, ..) => 0, + S(1, 2, 3, ..) => 1, + S(1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-4.rs b/src/test/run-pass/pat-tuple-4.rs new file mode 100644 index 0000000000000..ffd82fea99622 --- /dev/null +++ b/src/test/run-pass/pat-tuple-4.rs @@ -0,0 +1,68 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3); + match x { + (1, 2, 4) => unreachable!(), + (0, 2, 3, ..) => unreachable!(), + (0, .., 3) => unreachable!(), + (0, ..) => unreachable!(), + (1, 2, 3) => (), + (_, _, _) => unreachable!(), + } + match x { + (..) => (), + } + match x { + (_, _, _, ..) => (), + } + match x { + (a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(1, 2, 4) => unreachable!(), + S(0, 2, 3, ..) => unreachable!(), + S(0, .., 3) => unreachable!(), + S(0, ..) => unreachable!(), + S(1, 2, 3) => (), + S(_, _, _) => unreachable!(), + } + match x { + S(..) => (), + } + match x { + S(_, _, _, ..) => (), + } + match x { + S(a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-5.rs b/src/test/run-pass/pat-tuple-5.rs new file mode 100644 index 0000000000000..41c4d02abcbd3 --- /dev/null +++ b/src/test/run-pass/pat-tuple-5.rs @@ -0,0 +1,40 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + struct S; + struct Z; + struct W; + let x = (S, Z, W); + match x { (S, ..) => {} } + match x { (.., W) => {} } + match x { (S, .., W) => {} } + match x { (.., Z, _) => {} } +} + +fn tuple_struct() { + struct SS(S, Z, W); + + struct S; + struct Z; + struct W; + let x = SS(S, Z, W); + match x { SS(S, ..) => {} } + match x { SS(.., W) => {} } + match x { SS(S, .., W) => {} } + match x { SS(.., Z, _) => {} } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/pat-tuple-6.rs b/src/test/run-pass/pat-tuple-6.rs new file mode 100644 index 0000000000000..6f3f2b3aed550 --- /dev/null +++ b/src/test/run-pass/pat-tuple-6.rs @@ -0,0 +1,56 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dotdot_in_tuple_patterns)] + +fn tuple() { + let x = (1, 2, 3, 4, 5); + match x { + (a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + (a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8, u8, u8); + + let x = S(1, 2, 3, 4, 5); + match x { + S(a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + S(a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/src/test/run-pass/test-vs-cfg-test.rs b/src/test/run-pass/test-vs-cfg-test.rs new file mode 100644 index 0000000000000..708fde5988862 --- /dev/null +++ b/src/test/run-pass/test-vs-cfg-test.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --cfg test + +// Make sure `--cfg test` does not inject test harness + +#[test] +fn test() { panic!(); } + +fn main() {} diff --git a/src/test/compile-fail/issue-26480.rs b/src/test/ui/mismatched_types/issue-26480.rs similarity index 72% rename from src/test/compile-fail/issue-26480.rs rename to src/test/ui/mismatched_types/issue-26480.rs index 634a4014e1189..96db31f4b116f 100644 --- a/src/test/compile-fail/issue-26480.rs +++ b/src/test/ui/mismatched_types/issue-26480.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// rustc-env:RUST_NEW_ERROR_FORMAT extern { fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; } @@ -24,25 +25,16 @@ macro_rules! write { unsafe { write(stdout, $arr.as_ptr() as *const i8, $arr.len() * size_of($arr[0])); - //~^ ERROR mismatched types - //~| expected u64, found usize - //~| expected type - //~| found type } }} } macro_rules! cast { - ($x:expr) => ($x as ()) //~ ERROR non-scalar cast + ($x:expr) => ($x as ()) } fn main() { let hello = ['H', 'e', 'y']; write!(hello); - //~^ NOTE in this expansion of write! - //~| NOTE in this expansion of write! - //~| NOTE in this expansion of write! - cast!(2); - //~^ NOTE in this expansion of cast! } diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr new file mode 100644 index 0000000000000..c00594a59c115 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -0,0 +1,15 @@ +error: mismatched types [--explain E0308] + --> $DIR/issue-26480.rs:27:19 + |> +27 |> $arr.len() * size_of($arr[0])); + |> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize +$DIR/issue-26480.rs:38:5: 38:19: note: in this expansion of write! (defined in $DIR/issue-26480.rs) + +error: non-scalar cast: `_` as `()` + --> $DIR/issue-26480.rs:33:19 + |> +33 |> ($x:expr) => ($x as ()) + |> ^^^^^^^^ +$DIR/issue-26480.rs:39:5: 39:14: note: in this expansion of cast! (defined in $DIR/issue-26480.rs) + +error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr index 98bc11752e0ed..1af332ee5bea7 100644 --- a/src/test/ui/mismatched_types/main.stderr +++ b/src/test/ui/mismatched_types/main.stderr @@ -1,5 +1,6 @@ error: mismatched types [--explain E0308] --> $DIR/main.rs:14:18 + |> 14 |> let x: u32 = ( |> ^ expected u32, found () note: expected type `u32` diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e6dc3a9d360ff..4040b55ff98cb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -371,9 +371,16 @@ actual:\n\ } else { &*self.config.target }; + + let out_dir = self.output_base_name().with_extension("pretty-out"); + let _ = fs::remove_dir_all(&out_dir); + self.create_dir_racy(&out_dir); + // FIXME (#9639): This needs to handle non-utf8 paths let mut args = vec!("-".to_owned(), "-Zno-trans".to_owned(), + "--out-dir".to_owned(), + out_dir.to_str().unwrap().to_owned(), format!("--target={}", target), "-L".to_owned(), self.config.build_base.to_str().unwrap().to_owned(),