提交 afd4a542 编写于 作者: B bors

Auto merge of #29795 - Manishearth:rollup, r=Manishearth

- Successful merges: #29776, #29785, #29786, #29787
- Failed merges:
......@@ -79,8 +79,11 @@
use core::mem::{align_of_val, size_of_val};
use core::intrinsics::abort;
use core::mem;
use core::ops::{Deref, CoerceUnsized};
use core::ops::Deref;
#[cfg(not(stage0))]
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
#[cfg(not(stage0))]
use core::marker::Unsize;
use core::hash::{Hash, Hasher};
use core::{usize, isize};
......
......@@ -161,9 +161,13 @@
use core::fmt;
use core::hash::{Hasher, Hash};
use core::intrinsics::{assume, abort};
use core::marker::{self, Unsize};
use core::marker;
#[cfg(not(stage0))]
use core::marker::Unsize;
use core::mem::{self, align_of_val, size_of_val, forget};
use core::ops::{CoerceUnsized, Deref};
use core::ops::Deref;
#[cfg(not(stage0))]
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use heap::deallocate;
......
......@@ -456,7 +456,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
// Transforming contained values
/////////////////////////////////////////////////////////////////////////
/// Maps a `Result<T, E>` to `Result<U, E>` by applying a function to an
/// Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a
/// contained `Ok` value, leaving an `Err` value untouched.
///
/// This function can be used to compose the results of two functions.
......@@ -484,7 +484,7 @@ pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U,E> {
}
}
/// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to an
/// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a
/// contained `Err` value, leaving an `Ok` value untouched.
///
/// This function can be used to pass through a successful result while handling
......
......@@ -85,7 +85,15 @@ pub fn match_expr(&mut self,
// this will generate code to test discriminant_lvalue and
// branch to the appropriate arm block
self.match_candidates(span, &mut arm_blocks, candidates, block);
let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
// because all matches are exhaustive, in principle we expect
// an empty vector to be returned here, but the algorithm is
// not entirely precise
if !otherwise.is_empty() {
let join_block = self.join_otherwise_blocks(otherwise);
self.panic(join_block);
}
// all the arm blocks will rejoin here
let end_block = self.cfg.start_new_block();
......@@ -279,11 +287,32 @@ struct Test<'tcx> {
// Main matching algorithm
impl<'a,'tcx> Builder<'a,'tcx> {
/// The main match algorithm. It begins with a set of candidates
/// `candidates` and has the job of generating code to determine
/// which of these candidates, if any, is the correct one. The
/// candidates are sorted in inverse priority -- so the last item
/// in the list has highest priority. When a candidate is found to
/// match the value, we will generate a branch to the appropriate
/// block found in `arm_blocks`.
///
/// The return value is a list of "otherwise" blocks. These are
/// points in execution where we found that *NONE* of the
/// candidates apply. In principle, this means that the input
/// list was not exhaustive, though at present we sometimes are
/// not smart enough to recognize all exhaustive inputs.
///
/// It might be surprising that the input can be inexhaustive.
/// Indeed, initially, it is not, because all matches are
/// exhaustive in Rust. But during processing we sometimes divide
/// up the list of candidates and recurse with a non-exhaustive
/// list. This is important to keep the size of the generated code
/// under control. See `test_candidates` for more details.
fn match_candidates<'pat>(&mut self,
span: Span,
arm_blocks: &mut ArmBlocks,
mut candidates: Vec<Candidate<'pat, 'tcx>>,
mut block: BasicBlock)
-> Vec<BasicBlock>
{
debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})",
span, block, candidates);
......@@ -311,17 +340,127 @@ fn match_candidates<'pat>(&mut self,
} else {
// if None is returned, then any remaining candidates
// are unreachable (at least not through this path).
return;
return vec![];
}
}
// If there are no candidates that still need testing, we're done.
// Since all matches are exhaustive, execution should never reach this point.
if candidates.is_empty() {
return self.panic(block);
return vec![block];
}
// Test candidates where possible.
let (otherwise, tested_candidates) =
self.test_candidates(span, arm_blocks, &candidates, block);
// If the target candidates were exhaustive, then we are done.
if otherwise.is_empty() {
return vec![];
}
// If all candidates were sorted into `target_candidates` somewhere, then
// the initial set was inexhaustive.
let untested_candidates = candidates.len() - tested_candidates;
if untested_candidates == 0 {
return otherwise;
}
// otherwise, extract the next match pair and construct tests
// Otherwise, let's process those remaining candidates.
let join_block = self.join_otherwise_blocks(otherwise);
candidates.truncate(untested_candidates);
self.match_candidates(span, arm_blocks, candidates, join_block)
}
fn join_otherwise_blocks(&mut self,
otherwise: Vec<BasicBlock>)
-> BasicBlock
{
if otherwise.len() == 1 {
otherwise[0]
} else {
let join_block = self.cfg.start_new_block();
for block in otherwise {
self.cfg.terminate(block, Terminator::Goto { target: join_block });
}
join_block
}
}
/// This is the most subtle part of the matching algorithm. At
/// this point, the input candidates have been fully simplified,
/// and so we know that all remaining match-pairs require some
/// sort of test. To decide what test to do, we take the highest
/// priority candidate (last one in the list) and extract the
/// first match-pair from the list. From this we decide what kind
/// of test is needed using `test`, defined in the `test` module.
///
/// *Note:* taking the first match pair is somewhat arbitrary, and
/// we might do better here by choosing more carefully what to
/// test.
///
/// For example, consider the following possible match-pairs:
///
/// 1. `x @ Some(P)` -- we will do a `Switch` to decide what variant `x` has
/// 2. `x @ 22` -- we will do a `SwitchInt`
/// 3. `x @ 3..5` -- we will do a range test
/// 4. etc.
///
/// Once we know what sort of test we are going to perform, this
/// test may also help us with other candidates. So we walk over
/// the candidates (from high to low priority) and check. This
/// gives us, for each outcome of the test, a transformed list of
/// candidates. For example, if we are testing the current
/// variant of `x.0`, and we have a candidate `{x.0 @ Some(v), x.1
/// @ 22}`, then we would have a resulting candidate of `{(x.0 as
/// Some).0 @ v, x.1 @ 22}`. Note that the first match-pair is now
/// simpler (and, in fact, irrefutable).
///
/// But there may also be candidates that the test just doesn't
/// apply to. For example, consider the case of #29740:
///
/// ```rust
/// match x {
/// "foo" => ...,
/// "bar" => ...,
/// "baz" => ...,
/// _ => ...,
/// }
/// ```
///
/// Here the match-pair we are testing will be `x @ "foo"`, and we
/// will generate an `Eq` test. Because `"bar"` and `"baz"` are different
/// constants, we will decide that these later candidates are just not
/// informed by the eq test. So we'll wind up with three candidate sets:
///
/// - If outcome is that `x == "foo"` (one candidate, derived from `x @ "foo"`)
/// - If outcome is that `x != "foo"` (empty list of candidates)
/// - Otherwise (three candidates, `x @ "bar"`, `x @ "baz"`, `x @
/// _`). Here we have the invariant that everything in the
/// otherwise list is of **lower priority** than the stuff in the
/// other lists.
///
/// So we'll compile the test. For each outcome of the test, we
/// recursively call `match_candidates` with the corresponding set
/// of candidates. But note that this set is now inexhaustive: for
/// example, in the case where the test returns false, there are
/// NO candidates, even though there is stll a value to be
/// matched. So we'll collect the return values from
/// `match_candidates`, which are the blocks where control-flow
/// goes if none of the candidates matched. At this point, we can
/// continue with the "otherwise" list.
///
/// If you apply this to the above test, you basically wind up
/// with an if-else-if chain, testing each candidate in turn,
/// which is precisely what we want.
fn test_candidates<'pat>(&mut self,
span: Span,
arm_blocks: &mut ArmBlocks,
candidates: &[Candidate<'pat, 'tcx>],
block: BasicBlock)
-> (Vec<BasicBlock>, usize)
{
// extract the match-pair from the highest priority candidate
let match_pair = &candidates.last().unwrap().match_pairs[0];
let mut test = self.test(match_pair);
......@@ -331,35 +470,57 @@ fn match_candidates<'pat>(&mut self,
// available
match test.kind {
TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => {
for candidate in &candidates {
self.add_cases_to_switch(&match_pair.lvalue,
candidate,
switch_ty,
options,
indices);
for candidate in candidates.iter().rev() {
if !self.add_cases_to_switch(&match_pair.lvalue,
candidate,
switch_ty,
options,
indices) {
break;
}
}
}
_ => { }
}
// perform the test, branching to one of N blocks. For each of
// those N possible outcomes, create a (initially empty)
// vector of candidates. Those are the candidates that still
// apply if the test has that particular outcome.
debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair);
let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
for candidate in &candidates {
self.sort_candidate(&match_pair.lvalue,
&test,
candidate,
&mut target_candidates);
}
for (target_block, target_candidates) in
// Sort the candidates into the appropriate vector in
// `target_candidates`. Note that at some point we may
// encounter a candidate where the test is not relevant; at
// that point, we stop sorting.
let tested_candidates =
candidates.iter()
.rev()
.take_while(|c| self.sort_candidate(&match_pair.lvalue,
&test,
c,
&mut target_candidates))
.count();
assert!(tested_candidates > 0); // at least the last candidate ought to be tested
// For each outcome of test, process the candidates that still
// apply. Collect a list of blocks where control flow will
// branch if one of the `target_candidate` sets is not
// exhaustive.
let otherwise: Vec<_> =
target_blocks.into_iter()
.zip(target_candidates.into_iter())
{
self.match_candidates(span, arm_blocks, target_candidates, target_block);
}
.zip(target_candidates)
.flat_map(|(target_block, target_candidates)| {
self.match_candidates(span,
arm_blocks,
target_candidates,
target_block)
})
.collect();
(otherwise, tested_candidates)
}
/// Initializes each of the bindings from the candidate by
......
......@@ -105,10 +105,11 @@ pub fn add_cases_to_switch<'pat>(&mut self,
switch_ty: Ty<'tcx>,
options: &mut Vec<ConstVal>,
indices: &mut FnvHashMap<ConstVal, usize>)
-> bool
{
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
Some(match_pair) => match_pair,
_ => { return; }
_ => { return false; }
};
match *match_pair.pattern.kind {
......@@ -121,11 +122,10 @@ pub fn add_cases_to_switch<'pat>(&mut self,
options.push(value.clone());
options.len() - 1
});
true
}
PatternKind::Range { .. } => {
}
PatternKind::Range { .. } |
PatternKind::Constant { .. } |
PatternKind::Variant { .. } |
PatternKind::Slice { .. } |
......@@ -134,6 +134,8 @@ pub fn add_cases_to_switch<'pat>(&mut self,
PatternKind::Binding { .. } |
PatternKind::Leaf { .. } |
PatternKind::Deref { .. } => {
// don't know how to add these patterns to a switch
false
}
}
}
......@@ -284,18 +286,29 @@ fn call_comparison_fn(&mut self,
/// P0` to the `resulting_candidates` entry corresponding to the
/// variant `Some`.
///
/// In many cases we will add the `candidate` to more than one
/// outcome. For example, say that the test is `x == 22`, but the
/// candidate is `x @ 13..55`. In that case, if the test is true,
/// then we know that the candidate applies (without this match
/// pair, potentially, though we don't optimize this due to
/// #29623). If the test is false, the candidate may also apply
/// (with the match pair, still).
/// However, in some cases, the test may just not be relevant to
/// candidate. For example, suppose we are testing whether `foo.x == 22`,
/// but in one match arm we have `Foo { x: _, ... }`... in that case,
/// the test for what value `x` has has no particular relevance
/// to this candidate. In such cases, this function just returns false
/// without doing anything. This is used by the overall `match_candidates`
/// algorithm to structure the match as a whole. See `match_candidates` for
/// more details.
///
/// FIXME(#29623). In some cases, we have some tricky choices to
/// make. for example, if we are testing that `x == 22`, but the
/// candidate is `x @ 13..55`, what should we do? In the event
/// that the test is true, we know that the candidate applies, but
/// in the event of false, we don't know that it *doesn't*
/// apply. For now, we return false, indicate that the test does
/// not apply to this candidate, but it might be we can get
/// tighter match code if we do something a bit different.
pub fn sort_candidate<'pat>(&mut self,
test_lvalue: &Lvalue<'tcx>,
test: &Test<'tcx>,
candidate: &Candidate<'pat, 'tcx>,
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>]) {
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>])
-> bool {
// Find the match_pair for this lvalue (if any). At present,
// afaik, there can be at most one. (In the future, if we
// adopted a more general `@` operator, there might be more
......@@ -311,7 +324,7 @@ pub fn sort_candidate<'pat>(&mut self,
None => {
// We are not testing this lvalue. Therefore, this
// candidate applies to ALL outcomes.
return self.add_to_all_candidate_sets(candidate, resulting_candidates);
return false;
}
};
......@@ -329,9 +342,10 @@ pub fn sort_candidate<'pat>(&mut self,
subpatterns,
candidate);
resulting_candidates[variant_index].push(new_candidate);
true
}
_ => {
self.add_to_all_candidate_sets(candidate, resulting_candidates);
false
}
}
}
......@@ -349,9 +363,10 @@ pub fn sort_candidate<'pat>(&mut self,
let new_candidate = self.candidate_without_match_pair(match_pair_index,
candidate);
resulting_candidates[index].push(new_candidate);
true
}
_ => {
self.add_to_all_candidate_sets(candidate, resulting_candidates);
false
}
}
}
......@@ -367,8 +382,9 @@ pub fn sort_candidate<'pat>(&mut self,
let new_candidate = self.candidate_without_match_pair(match_pair_index,
candidate);
resulting_candidates[0].push(new_candidate);
true
} else {
self.add_to_all_candidate_sets(candidate, resulting_candidates);
false
}
}
}
......@@ -392,14 +408,6 @@ fn candidate_without_match_pair<'pat>(&mut self,
}
}
fn add_to_all_candidate_sets<'pat>(&mut self,
candidate: &Candidate<'pat, 'tcx>,
resulting_candidates: &mut [Vec<Candidate<'pat, 'tcx>>]) {
for resulting_candidate in resulting_candidates {
resulting_candidate.push(candidate.clone());
}
}
fn candidate_after_variant_switch<'pat>(&mut self,
match_pair_index: usize,
adt_def: ty::AdtDef<'tcx>,
......@@ -447,5 +455,5 @@ fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> !
}
fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool {
ty.is_integral() || ty.is_char()
ty.is_integral() || ty.is_char() || ty.is_bool()
}
......@@ -10,119 +10,136 @@
//! The Rust Prelude
//!
//! Because `std` is required by most serious Rust software, it is
//! imported at the topmost level of every crate by default, as if
//! each crate contains the following:
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particuarly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::thread::spawn`,
//! etc.
//!
//! Additionally, `std` contains a versioned *prelude* that reexports many of the
//! most common traits, types, and functions. *The contents of the prelude are
//! imported into every module by default*. Implicitly, all modules behave as if
//! they contained the following [`use` statement][book-use]:
//!
//! [book-use]: ../../book/crates-and-modules.html#importing-modules-with-use
//! into the crate root of every crate, and
//!
//! ```ignore
//! use std::prelude::v1::*;
//! ```
//!
//! The prelude is primarily concerned with exporting *traits* that
//! are so pervasive that they would be onerous to import for every use,
//! particularly those that are commonly mentioned in [generic type
//! bounds][book-traits].
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The differece between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their consitutent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`](v1/index.html), and reexports the following.
//! [`std::prelude::v1`], and reexports the following.
//!
//! * `std::marker::`{
//! [`Copy`](../marker/trait.Copy.html),
//! [`Send`](../marker/trait.Send.html),
//! [`Sized`](../marker/trait.Sized.html),
//! [`Sync`](../marker/trait.Sync.html)
//! }.
//! The marker traits indicate fundamental properties of types.
//! * `std::ops::`{
//! [`Drop`](../ops/trait.Drop.html),
//! [`Fn`](../ops/trait.Fn.html),
//! [`FnMut`](../ops/trait.FnMut.html),
//! [`FnOnce`](../ops/trait.FnOnce.html)
//! }.
//! The [destructor][book-dtor] trait and the
//! [closure][book-closures] traits, reexported from the same
//! [module that also defines overloaded
//! operators](../ops/index.html).
//! * `std::mem::`[`drop`](../mem/fn.drop.html).
//! A convenience function for explicitly dropping a value.
//! * `std::boxed::`[`Box`](../boxed/struct.Box.html).
//! The owned heap pointer.
//! * `std::borrow::`[`ToOwned`](../borrow/trait.ToOwned.html).
//! The conversion trait that defines `to_owned`, the generic method
//! for creating an owned type from a borrowed type.
//! * `std::clone::`[`Clone`](../clone/trait.Clone.html).
//! The ubiquitous trait that defines `clone`, the method for
//! producing copies of values that are consider expensive to copy.
//! * `std::cmp::`{
//! [`PartialEq`](../cmp/trait.PartialEq.html),
//! [`PartialOrd`](../cmp/trait.PartialOrd.html),
//! [`Eq`](../cmp/trait.Eq.html),
//! [`Ord`](../cmp/trait.Ord.html)
//! }.
//! The comparison traits, which implement the comparison operators
//! and are often seen in trait bounds.
//! * `std::convert::`{
//! [`AsRef`](../convert/trait.AsRef.html),
//! [`AsMut`](../convert/trait.AsMut.html),
//! [`Into`](../convert/trait.Into.html),
//! [`From`](../convert/trait.From.html)
//! }.
//! Generic conversions, used by savvy API authors to create
//! overloaded methods.
//! * `std::default::`[`Default`](../default/trait.Default.html).
//! Types that have default values.
//! * `std::iter::`{
//! [`Iterator`](../iter/trait.Iterator.html),
//! [`Extend`](../iter/trait.Extend.html),
//! [`IntoIterator`](../iter/trait.IntoIterator.html),
//! [`DoubleEndedIterator`](../iter/trait.DoubleEndedIterator.html),
//! [`ExactSizeIterator`](../iter/trait.ExactSizeIterator.html)
//! }.
//! [Iterators][book-iter].
//! * `std::option::Option::`{
//! [`self`](../option/enum.Option.html),
//! [`Some`](../option/enum.Option.html),
//! [`None`](../option/enum.Option.html)
//! }.
//! The ubiquitous `Option` type and its two [variants][book-enums],
//! `Some` and `None`.
//! * `std::result::Result::`{
//! [`self`](../result/enum.Result.html),
//! [`Ok`](../result/enum.Result.html),
//! [`Err`](../result/enum.Result.html)
//! }.
//! The ubiquitous `Result` type and its two [variants][book-enums],
//! `Ok` and `Err`.
//! * `std::slice::`[`SliceConcatExt`](../slice/trait.SliceConcatExt.html).
//! An unstable extension to slices that shouldn't have to exist.
//! * `std::string::`{
//! [`String`](../string/struct.String.html),
//! [`ToString`](../string/trait.ToString.html)
//! }.
//! Heap allocated strings.
//! * `std::vec::`[`Vec`](../vec/struct.Vec.html).
//! Heap allocated vectors.
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//! traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//! operations for both destuctors and overloading `()`.
//! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a
//! value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//! [`to_owned()`], the generic method for creating an owned type from a
//! borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`],
//! the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//! comparison traits, which implement the comparison operators and are often
//! seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//! conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//! [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//! kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//! expresses the presence or absence of a value. This type is so commonly
//! used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//! that may succeed or fail. Like [`Option`], its variants are exported as
//! well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//! reasons, but shouldn't have to exist. It provides a few useful methods on
//! slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//! vector.
//!
//! [book-traits]: ../../book/traits.html
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone
//! [`drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/closures.html
//! [book-dtor]: ../../book/drop.html
//! [book-iter]: ../../book/iterators.html
//! [book-enums]: ../../book/enums.html
//! [book-iter]: ../../book/iterators.html
#![stable(feature = "rust1", since = "1.0.0")]
......
......@@ -9,6 +9,8 @@
// except according to those terms.
//! The first version of the prelude of The Rust Standard Library.
//!
//! See the [module-level documentation](../index.html) for more.
#![stable(feature = "rust1", since = "1.0.0")]
......
// Copyright 2012 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for #29740. Inefficient MIR matching algorithms
// generated way too much code for this sort of case, leading to OOM.
// ignore-pretty
pub mod KeyboardEventConstants {
pub const DOM_KEY_LOCATION_STANDARD: u32 = 0;
pub const DOM_KEY_LOCATION_LEFT: u32 = 1;
pub const DOM_KEY_LOCATION_RIGHT: u32 = 2;
pub const DOM_KEY_LOCATION_NUMPAD: u32 = 3;
} // mod KeyboardEventConstants
pub enum Key {
Space,
Apostrophe,
Comma,
Minus,
Period,
Slash,
Num0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
Semicolon,
Equal,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LeftBracket,
Backslash,
RightBracket,
GraveAccent,
World1,
World2,
Escape,
Enter,
Tab,
Backspace,
Insert,
Delete,
Right,
Left,
Down,
Up,
PageUp,
PageDown,
Home,
End,
CapsLock,
ScrollLock,
NumLock,
PrintScreen,
Pause,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
F25,
Kp0,
Kp1,
Kp2,
Kp3,
Kp4,
Kp5,
Kp6,
Kp7,
Kp8,
Kp9,
KpDecimal,
KpDivide,
KpMultiply,
KpSubtract,
KpAdd,
KpEnter,
KpEqual,
LeftShift,
LeftControl,
LeftAlt,
LeftSuper,
RightShift,
RightControl,
RightAlt,
RightSuper,
Menu,
}
fn key_from_string(key_string: &str, location: u32) -> Option<Key> {
match key_string {
" " => Some(Key::Space),
"\"" => Some(Key::Apostrophe),
"'" => Some(Key::Apostrophe),
"<" => Some(Key::Comma),
"," => Some(Key::Comma),
"_" => Some(Key::Minus),
"-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Minus),
">" => Some(Key::Period),
"." if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Period),
"?" => Some(Key::Slash),
"/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Slash),
"~" => Some(Key::GraveAccent),
"`" => Some(Key::GraveAccent),
")" => Some(Key::Num0),
"0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num0),
"!" => Some(Key::Num1),
"1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num1),
"@" => Some(Key::Num2),
"2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num2),
"#" => Some(Key::Num3),
"3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num3),
"$" => Some(Key::Num4),
"4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num4),
"%" => Some(Key::Num5),
"5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num5),
"^" => Some(Key::Num6),
"6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num6),
"&" => Some(Key::Num7),
"7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num7),
"*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8),
"8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8),
"(" => Some(Key::Num9),
"9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num9),
":" => Some(Key::Semicolon),
";" => Some(Key::Semicolon),
"+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal),
"=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal),
"A" => Some(Key::A),
"a" => Some(Key::A),
"B" => Some(Key::B),
"b" => Some(Key::B),
"C" => Some(Key::C),
"c" => Some(Key::C),
"D" => Some(Key::D),
"d" => Some(Key::D),
"E" => Some(Key::E),
"e" => Some(Key::E),
"F" => Some(Key::F),
"f" => Some(Key::F),
"G" => Some(Key::G),
"g" => Some(Key::G),
"H" => Some(Key::H),
"h" => Some(Key::H),
"I" => Some(Key::I),
"i" => Some(Key::I),
"J" => Some(Key::J),
"j" => Some(Key::J),
"K" => Some(Key::K),
"k" => Some(Key::K),
"L" => Some(Key::L),
"l" => Some(Key::L),
"M" => Some(Key::M),
"m" => Some(Key::M),
"N" => Some(Key::N),
"n" => Some(Key::N),
"O" => Some(Key::O),
"o" => Some(Key::O),
"P" => Some(Key::P),
"p" => Some(Key::P),
"Q" => Some(Key::Q),
"q" => Some(Key::Q),
"R" => Some(Key::R),
"r" => Some(Key::R),
"S" => Some(Key::S),
"s" => Some(Key::S),
"T" => Some(Key::T),
"t" => Some(Key::T),
"U" => Some(Key::U),
"u" => Some(Key::U),
"V" => Some(Key::V),
"v" => Some(Key::V),
"W" => Some(Key::W),
"w" => Some(Key::W),
"X" => Some(Key::X),
"x" => Some(Key::X),
"Y" => Some(Key::Y),
"y" => Some(Key::Y),
"Z" => Some(Key::Z),
"z" => Some(Key::Z),
"{" => Some(Key::LeftBracket),
"[" => Some(Key::LeftBracket),
"|" => Some(Key::Backslash),
"\\" => Some(Key::Backslash),
"}" => Some(Key::RightBracket),
"]" => Some(Key::RightBracket),
"Escape" => Some(Key::Escape),
"Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD
=> Some(Key::Enter),
"Tab" => Some(Key::Tab),
"Backspace" => Some(Key::Backspace),
"Insert" => Some(Key::Insert),
"Delete" => Some(Key::Delete),
"ArrowRight" => Some(Key::Right),
"ArrowLeft" => Some(Key::Left),
"ArrowDown" => Some(Key::Down),
"ArrowUp" => Some(Key::Up),
"PageUp" => Some(Key::PageUp),
"PageDown" => Some(Key::PageDown),
"Home" => Some(Key::Home),
"End" => Some(Key::End),
"CapsLock" => Some(Key::CapsLock),
"ScrollLock" => Some(Key::ScrollLock),
"NumLock" => Some(Key::NumLock),
"PrintScreen" => Some(Key::PrintScreen),
"Pause" => Some(Key::Pause),
"F1" => Some(Key::F1),
"F2" => Some(Key::F2),
"F3" => Some(Key::F3),
"F4" => Some(Key::F4),
"F5" => Some(Key::F5),
"F6" => Some(Key::F6),
"F7" => Some(Key::F7),
"F8" => Some(Key::F8),
"F9" => Some(Key::F9),
"F10" => Some(Key::F10),
"F11" => Some(Key::F11),
"F12" => Some(Key::F12),
"F13" => Some(Key::F13),
"F14" => Some(Key::F14),
"F15" => Some(Key::F15),
"F16" => Some(Key::F16),
"F17" => Some(Key::F17),
"F18" => Some(Key::F18),
"F19" => Some(Key::F19),
"F20" => Some(Key::F20),
"F21" => Some(Key::F21),
"F22" => Some(Key::F22),
"F23" => Some(Key::F23),
"F24" => Some(Key::F24),
"F25" => Some(Key::F25),
"0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp0),
"1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp1),
"2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp2),
"3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp3),
"4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp4),
"5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp5),
"6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp6),
"7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp7),
"8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp8),
"9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp9),
"." if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDecimal),
"/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDivide),
"*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpMultiply),
"-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpSubtract),
"+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpAdd),
"Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD
=> Some(Key::KpEnter),
"=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEqual),
"Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
=> Some(Key::LeftShift),
"Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
=> Some(Key::LeftControl),
"Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftAlt),
"Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT
=> Some(Key::LeftSuper),
"Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
=> Some(Key::RightShift),
"Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
=> Some(Key::RightControl),
"Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt),
"Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT
=> Some(Key::RightSuper),
"ContextMenu" => Some(Key::Menu),
_ => None
}
}
fn main() { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册