mirror of https://github.com/rust-lang/rust.git
Auto merge of #127635 - matthiaskrgr:rollup-foopajr, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #127164 (match lowering: Clarify the main loop of the algorithm) - #127422 (as_simd: fix doc comment to be in line with align_to) - #127596 (More suggestion for converting `Option<&Vec<T>>` to `Option<&[T]>`) - #127607 (compiletest: Better error message for bad `normalize-*` headers) - #127622 (Mark `builtin_syntax` as internal) - #127625 (Revert accidental comment deletion) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b286722878
|
@ -821,6 +821,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
|||
| TerminatorKind::Return
|
||||
| TerminatorKind::TailCall { .. }
|
||||
| TerminatorKind::CoroutineDrop => {
|
||||
// Returning from the function implicitly kills storage for all locals and statics.
|
||||
// Often, the storage will already have been killed by an explicit
|
||||
// StorageDead, but we don't always emit those (notably on unwind paths),
|
||||
// so this "extra check" serves as a kind of backup.
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
|
|
|
@ -248,6 +248,8 @@ declare_features! (
|
|||
(unstable, auto_traits, "1.50.0", Some(13231)),
|
||||
/// Allows using `box` in patterns (RFC 469).
|
||||
(unstable, box_patterns, "1.0.0", Some(29641)),
|
||||
/// Allows builtin # foo() syntax
|
||||
(internal, builtin_syntax, "1.71.0", Some(110680)),
|
||||
/// Allows `#[doc(notable_trait)]`.
|
||||
/// Renamed from `doc_spotlight`.
|
||||
(unstable, doc_notable_trait, "1.52.0", Some(45040)),
|
||||
|
@ -361,8 +363,6 @@ declare_features! (
|
|||
(unstable, async_fn_track_caller, "1.73.0", Some(110011)),
|
||||
/// Allows `for await` loops.
|
||||
(unstable, async_for_loop, "1.77.0", Some(118898)),
|
||||
/// Allows builtin # foo() syntax
|
||||
(unstable, builtin_syntax, "1.71.0", Some(110680)),
|
||||
/// Allows using C-variadics.
|
||||
(unstable, c_variadic, "1.34.0", Some(44930)),
|
||||
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
|
||||
|
|
|
@ -466,21 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
} else if let Some((deref_ty, _)) =
|
||||
self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1)
|
||||
&& self.can_eq(self.param_env, deref_ty, peeled)
|
||||
&& error_tys_equate_as_ref
|
||||
{
|
||||
let sugg = prefix_wrap(".as_deref()");
|
||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||
span: expr.span.shrink_to_hi(),
|
||||
sugg,
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
|
||||
} else if let ty::Ref(_, peeled_found_ty, _) = found_ty_inner.kind()
|
||||
&& let ty::Adt(adt, _) = peeled_found_ty.peel_refs().kind()
|
||||
&& self.tcx.is_lang_item(adt.did(), LangItem::String)
|
||||
&& peeled.is_str()
|
||||
// `Result::map`, conversely, does not take ref of the error type.
|
||||
|
@ -496,12 +483,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
if !error_tys_equate_as_ref {
|
||||
return false;
|
||||
}
|
||||
let mut steps = self.autoderef(expr.span, found_ty_inner).silence_errors();
|
||||
if let Some((deref_ty, _)) = steps.nth(1)
|
||||
&& self.can_eq(self.param_env, deref_ty, peeled)
|
||||
{
|
||||
let sugg = prefix_wrap(".as_deref()");
|
||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||
span: expr.span.shrink_to_hi(),
|
||||
sugg,
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
for (deref_ty, n_step) in steps {
|
||||
if self.can_eq(self.param_env, deref_ty, peeled) {
|
||||
let explicit_deref = "*".repeat(n_step);
|
||||
let sugg = prefix_wrap(&format!(".map(|v| &{explicit_deref}v)"));
|
||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||
span: expr.span.shrink_to_hi(),
|
||||
sugg,
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// If `ty` is `Option<T>`, returns `T, T, None`.
|
||||
/// If `ty` is `Result<T, E>`, returns `T, T, Some(E, E)`.
|
||||
/// Otherwise, returns `None`.
|
||||
fn deconstruct_option_or_result(
|
||||
&self,
|
||||
found_ty: Ty<'tcx>,
|
||||
|
|
|
@ -1119,6 +1119,11 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns whether the first match pair of this candidate is an or-pattern.
|
||||
fn starts_with_or_pattern(&self) -> bool {
|
||||
matches!(&*self.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..])
|
||||
}
|
||||
|
||||
/// Visit the leaf candidates (those with no subcandidates) contained in
|
||||
/// this candidate.
|
||||
fn visit_leaves<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
|
||||
|
@ -1308,11 +1313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
candidates: &mut [&mut Candidate<'pat, 'tcx>],
|
||||
refutable: bool,
|
||||
) -> BasicBlock {
|
||||
// This will generate code to test scrutinee_place and branch to the appropriate arm block.
|
||||
// See the doc comment on `match_candidates` for why we have an otherwise block.
|
||||
let otherwise_block = self.cfg.start_new_block();
|
||||
|
||||
// This will generate code to test scrutinee_place and branch to the appropriate arm block
|
||||
self.match_candidates(match_start_span, scrutinee_span, block, otherwise_block, candidates);
|
||||
let otherwise_block =
|
||||
self.match_candidates(match_start_span, scrutinee_span, block, candidates);
|
||||
|
||||
// Link each leaf candidate to the `false_edge_start_block` of the next one.
|
||||
let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None;
|
||||
|
@ -1363,27 +1367,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
otherwise_block
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// The main match algorithm. It begins with a set of candidates `candidates` and has the job of
|
||||
/// generating code that branches to an appropriate block if the scrutinee matches one of these
|
||||
/// candidates. The
|
||||
/// candidates are sorted such that the first item in the list
|
||||
/// has the highest priority. When a candidate is found to match
|
||||
/// the value, we will set and generate a branch to the appropriate
|
||||
/// pre-binding block.
|
||||
///
|
||||
/// If we find that *NONE* of the candidates apply, we branch to `otherwise_block`.
|
||||
/// If none of the candidates apply, we continue to the returned `otherwise_block`.
|
||||
///
|
||||
/// It might be surprising that the input can be non-exhaustive.
|
||||
/// Indeed, initially, it is not, because all matches are
|
||||
/// Indeed, for matches, 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 how our lowering approach (called "backtracking
|
||||
/// automaton" in the literature) works.
|
||||
/// See [`Builder::test_candidates`] for more details.
|
||||
///
|
||||
/// If `fake_borrows` is `Some`, then places which need fake borrows
|
||||
/// will be added to it.
|
||||
///
|
||||
/// For an example of how we use `otherwise_block`, consider:
|
||||
/// ```
|
||||
/// # fn foo((x, y): (bool, bool)) -> u32 {
|
||||
|
@ -1408,7 +1409,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// }
|
||||
/// if y {
|
||||
/// if x {
|
||||
/// // This is actually unreachable because the `(true, true)` case was handled above.
|
||||
/// // This is actually unreachable because the `(true, true)` case was handled above,
|
||||
/// // but we don't know that from within the lowering algorithm.
|
||||
/// // continue
|
||||
/// } else {
|
||||
/// return 3
|
||||
|
@ -1425,161 +1427,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// the algorithm. For more details on why we lower like this, see [`Builder::test_candidates`].
|
||||
///
|
||||
/// Note how we test `x` twice. This is the tradeoff of backtracking automata: we prefer smaller
|
||||
/// code size at the expense of non-optimal code paths.
|
||||
/// code size so we accept non-optimal code paths.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn match_candidates<'pat>(
|
||||
fn match_candidates(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
start_block: BasicBlock,
|
||||
otherwise_block: BasicBlock,
|
||||
candidates: &mut [&mut Candidate<'pat, 'tcx>],
|
||||
) {
|
||||
// We process or-patterns here. If any candidate starts with an or-pattern, we have to
|
||||
// expand the or-pattern before we can proceed further.
|
||||
//
|
||||
// We can't expand them freely however. The rule is: if the candidate has an or-pattern as
|
||||
// its only remaining match pair, we can expand it freely. If it has other match pairs, we
|
||||
// can expand it but we can't process more candidates after it.
|
||||
//
|
||||
// If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the following,
|
||||
// or-pattern simplification (in `merge_trivial_subcandidates`) makes it so the `1` and `2`
|
||||
// cases branch to a same block (which then tests `false`). If we took `(2, _)` in the same
|
||||
// set of candidates, when we reach the block that tests `false` we don't know whether we
|
||||
// came from `1` or `2`, hence we can't know where to branch on failure.
|
||||
// ```ignore(illustrative)
|
||||
// match (1, true) {
|
||||
// (1 | 2, false) => {},
|
||||
// (2, _) => {},
|
||||
// _ => {}
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// We therefore split the `candidates` slice in two, expand or-patterns in the first half,
|
||||
// and process both halves separately.
|
||||
let mut expand_until = 0;
|
||||
for (i, candidate) in candidates.iter().enumerate() {
|
||||
if matches!(
|
||||
&*candidate.match_pairs,
|
||||
[MatchPair { test_case: TestCase::Or { .. }, .. }, ..]
|
||||
) {
|
||||
expand_until = i + 1;
|
||||
if candidate.match_pairs.len() > 1 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if expand_until != 0 {
|
||||
expand_until = i + 1;
|
||||
}
|
||||
}
|
||||
let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until);
|
||||
|
||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||
) -> BasicBlock {
|
||||
ensure_sufficient_stack(|| {
|
||||
if candidates_to_expand.is_empty() {
|
||||
// No candidates start with an or-pattern, we can continue.
|
||||
self.match_expanded_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
start_block,
|
||||
otherwise_block,
|
||||
remaining_candidates,
|
||||
);
|
||||
} else {
|
||||
// Expand one level of or-patterns for each candidate in `candidates_to_expand`.
|
||||
let mut expanded_candidates = Vec::new();
|
||||
for candidate in candidates_to_expand.iter_mut() {
|
||||
if let [MatchPair { test_case: TestCase::Or { .. }, .. }, ..] =
|
||||
&*candidate.match_pairs
|
||||
{
|
||||
let or_match_pair = candidate.match_pairs.remove(0);
|
||||
// Expand the or-pattern into subcandidates.
|
||||
self.create_or_subcandidates(candidate, or_match_pair);
|
||||
// Collect the newly created subcandidates.
|
||||
for subcandidate in candidate.subcandidates.iter_mut() {
|
||||
expanded_candidates.push(subcandidate);
|
||||
}
|
||||
} else {
|
||||
expanded_candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Process the expanded candidates.
|
||||
let remainder_start = self.cfg.start_new_block();
|
||||
// There might be new or-patterns obtained from expanding the old ones, so we call
|
||||
// `match_candidates` again.
|
||||
self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
start_block,
|
||||
remainder_start,
|
||||
expanded_candidates.as_mut_slice(),
|
||||
);
|
||||
|
||||
// Simplify subcandidates and process any leftover match pairs.
|
||||
for candidate in candidates_to_expand {
|
||||
if !candidate.subcandidates.is_empty() {
|
||||
self.finalize_or_candidate(span, scrutinee_span, candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Process the remaining candidates.
|
||||
self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
remainder_start,
|
||||
otherwise_block,
|
||||
remaining_candidates,
|
||||
);
|
||||
}
|
||||
});
|
||||
self.match_candidates_inner(span, scrutinee_span, start_block, candidates)
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct the decision tree for `candidates`. Caller must ensure that no candidate in
|
||||
/// `candidates` starts with an or-pattern.
|
||||
fn match_expanded_candidates(
|
||||
/// Construct the decision tree for `candidates`. Don't call this, call `match_candidates`
|
||||
/// instead to reserve sufficient stack space.
|
||||
fn match_candidates_inner(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
mut start_block: BasicBlock,
|
||||
otherwise_block: BasicBlock,
|
||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||
) {
|
||||
) -> BasicBlock {
|
||||
if let [first, ..] = candidates {
|
||||
if first.false_edge_start_block.is_none() {
|
||||
first.false_edge_start_block = Some(start_block);
|
||||
}
|
||||
}
|
||||
|
||||
match candidates {
|
||||
// Process a prefix of the candidates.
|
||||
let rest = match candidates {
|
||||
[] => {
|
||||
// If there are no candidates that still need testing, we're done. Since all matches are
|
||||
// exhaustive, execution should never reach this point.
|
||||
let source_info = self.source_info(span);
|
||||
self.cfg.goto(start_block, source_info, otherwise_block);
|
||||
// If there are no candidates that still need testing, we're done.
|
||||
return start_block;
|
||||
}
|
||||
[first, remaining @ ..] if first.match_pairs.is_empty() => {
|
||||
// The first candidate has satisfied all its match pairs; we link it up and continue
|
||||
// with the remaining candidates.
|
||||
start_block = self.select_matched_candidate(first, start_block);
|
||||
self.match_expanded_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
start_block,
|
||||
otherwise_block,
|
||||
remaining,
|
||||
)
|
||||
let remainder_start = self.select_matched_candidate(first, start_block);
|
||||
remainder_start.and(remaining)
|
||||
}
|
||||
candidates if candidates.iter().any(|candidate| candidate.starts_with_or_pattern()) => {
|
||||
// If any candidate starts with an or-pattern, we have to expand the or-pattern before we
|
||||
// can proceed further.
|
||||
self.expand_and_match_or_candidates(span, scrutinee_span, start_block, candidates)
|
||||
}
|
||||
candidates => {
|
||||
// The first candidate has some unsatisfied match pairs; we proceed to do more tests.
|
||||
self.test_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
candidates,
|
||||
start_block,
|
||||
otherwise_block,
|
||||
);
|
||||
self.test_candidates(span, scrutinee_span, candidates, start_block)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Process any candidates that remain.
|
||||
let remaining_candidates = unpack!(start_block = rest);
|
||||
self.match_candidates(span, scrutinee_span, start_block, remaining_candidates)
|
||||
}
|
||||
|
||||
/// Link up matched candidates.
|
||||
|
@ -1624,6 +1526,102 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
otherwise_block
|
||||
}
|
||||
|
||||
/// Takes a list of candidates such that some of the candidates' first match pairs are
|
||||
/// or-patterns. This expands as many or-patterns as possible and processes the resulting
|
||||
/// candidates. Returns the unprocessed candidates if any.
|
||||
fn expand_and_match_or_candidates<'pat, 'b, 'c>(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
start_block: BasicBlock,
|
||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
||||
// We can't expand or-patterns freely. The rule is: if the candidate has an
|
||||
// or-pattern as its only remaining match pair, we can expand it freely. If it has
|
||||
// other match pairs, we can expand it but we can't process more candidates after
|
||||
// it.
|
||||
//
|
||||
// If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the
|
||||
// following, or-pattern simplification (in `merge_trivial_subcandidates`) makes it
|
||||
// so the `1` and `2` cases branch to a same block (which then tests `false`). If we
|
||||
// took `(2, _)` in the same set of candidates, when we reach the block that tests
|
||||
// `false` we don't know whether we came from `1` or `2`, hence we can't know where
|
||||
// to branch on failure.
|
||||
//
|
||||
// ```ignore(illustrative)
|
||||
// match (1, true) {
|
||||
// (1 | 2, false) => {},
|
||||
// (2, _) => {},
|
||||
// _ => {}
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// We therefore split the `candidates` slice in two, expand or-patterns in the first half,
|
||||
// and process the rest separately.
|
||||
let mut expand_until = 0;
|
||||
for (i, candidate) in candidates.iter().enumerate() {
|
||||
expand_until = i + 1;
|
||||
if candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() {
|
||||
// The candidate has an or-pattern as well as more match pairs: we must
|
||||
// split the candidates list here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until);
|
||||
|
||||
// Expand one level of or-patterns for each candidate in `candidates_to_expand`.
|
||||
let mut expanded_candidates = Vec::new();
|
||||
for candidate in candidates_to_expand.iter_mut() {
|
||||
if candidate.starts_with_or_pattern() {
|
||||
let or_match_pair = candidate.match_pairs.remove(0);
|
||||
// Expand the or-pattern into subcandidates.
|
||||
self.create_or_subcandidates(candidate, or_match_pair);
|
||||
// Collect the newly created subcandidates.
|
||||
for subcandidate in candidate.subcandidates.iter_mut() {
|
||||
expanded_candidates.push(subcandidate);
|
||||
}
|
||||
} else {
|
||||
expanded_candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Process the expanded candidates.
|
||||
let remainder_start = self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
start_block,
|
||||
expanded_candidates.as_mut_slice(),
|
||||
);
|
||||
|
||||
// Simplify subcandidates and process any leftover match pairs.
|
||||
for candidate in candidates_to_expand {
|
||||
if !candidate.subcandidates.is_empty() {
|
||||
self.finalize_or_candidate(span, scrutinee_span, candidate);
|
||||
}
|
||||
}
|
||||
|
||||
remainder_start.and(remaining_candidates)
|
||||
}
|
||||
|
||||
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
|
||||
/// subcandidate. Any candidate that has been expanded that way should be passed to
|
||||
/// `finalize_or_candidate` after its subcandidates have been processed.
|
||||
fn create_or_subcandidates<'pat>(
|
||||
&mut self,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
match_pair: MatchPair<'pat, 'tcx>,
|
||||
) {
|
||||
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
||||
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
||||
candidate.or_span = Some(match_pair.pattern.span);
|
||||
candidate.subcandidates = pats
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
|
||||
.collect();
|
||||
candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block;
|
||||
}
|
||||
|
||||
/// Simplify subcandidates and process any leftover match pairs. The candidate should have been
|
||||
/// expanded with `create_or_subcandidates`.
|
||||
///
|
||||
|
@ -1690,6 +1688,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.merge_trivial_subcandidates(candidate);
|
||||
|
||||
if !candidate.match_pairs.is_empty() {
|
||||
let or_span = candidate.or_span.unwrap_or(candidate.extra_data.span);
|
||||
let source_info = self.source_info(or_span);
|
||||
// If more match pairs remain, test them after each subcandidate.
|
||||
// We could add them to the or-candidates before the call to `test_or_pattern` but this
|
||||
// would make it impossible to detect simplifiable or-patterns. That would guarantee
|
||||
|
@ -1703,6 +1703,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
assert!(leaf_candidate.match_pairs.is_empty());
|
||||
leaf_candidate.match_pairs.extend(remaining_match_pairs.iter().cloned());
|
||||
let or_start = leaf_candidate.pre_binding_block.unwrap();
|
||||
let otherwise =
|
||||
self.match_candidates(span, scrutinee_span, or_start, &mut [leaf_candidate]);
|
||||
// In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
|
||||
// R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
|
||||
// directly to `last_otherwise`. If there is a guard,
|
||||
|
@ -1713,36 +1715,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
} else {
|
||||
last_otherwise.unwrap()
|
||||
};
|
||||
self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
or_start,
|
||||
or_otherwise,
|
||||
&mut [leaf_candidate],
|
||||
);
|
||||
self.cfg.goto(otherwise, source_info, or_otherwise);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
|
||||
/// subcandidate. Any candidate that has been expanded that way should be passed to
|
||||
/// `finalize_or_candidate` after its subcandidates have been processed.
|
||||
fn create_or_subcandidates<'pat>(
|
||||
&mut self,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
match_pair: MatchPair<'pat, 'tcx>,
|
||||
) {
|
||||
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
||||
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
||||
candidate.or_span = Some(match_pair.pattern.span);
|
||||
candidate.subcandidates = pats
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
|
||||
.collect();
|
||||
candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block;
|
||||
}
|
||||
|
||||
/// Try to merge all of the subcandidates of the given candidate into one. This avoids
|
||||
/// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The candidate should have been
|
||||
/// expanded with `create_or_subcandidates`.
|
||||
|
@ -1992,14 +1969,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// We return the unprocessed candidates.
|
||||
fn test_candidates<'pat, 'b, 'c>(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
start_block: BasicBlock,
|
||||
otherwise_block: BasicBlock,
|
||||
) {
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
||||
// Extract the match-pair from the highest priority candidate and build a test from it.
|
||||
let (match_place, test) = self.pick_test(candidates);
|
||||
|
||||
|
@ -2010,33 +1988,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
// The block that we should branch to if none of the
|
||||
// `target_candidates` match.
|
||||
let remainder_start = if !remaining_candidates.is_empty() {
|
||||
let remainder_start = self.cfg.start_new_block();
|
||||
self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
remainder_start,
|
||||
otherwise_block,
|
||||
remaining_candidates,
|
||||
);
|
||||
remainder_start
|
||||
} else {
|
||||
otherwise_block
|
||||
};
|
||||
let remainder_start = self.cfg.start_new_block();
|
||||
|
||||
// For each outcome of test, process the candidates that still apply.
|
||||
let target_blocks: FxIndexMap<_, _> = target_candidates
|
||||
.into_iter()
|
||||
.map(|(branch, mut candidates)| {
|
||||
let candidate_start = self.cfg.start_new_block();
|
||||
self.match_candidates(
|
||||
span,
|
||||
scrutinee_span,
|
||||
candidate_start,
|
||||
remainder_start,
|
||||
&mut *candidates,
|
||||
);
|
||||
(branch, candidate_start)
|
||||
let branch_start = self.cfg.start_new_block();
|
||||
let branch_otherwise =
|
||||
self.match_candidates(span, scrutinee_span, branch_start, &mut *candidates);
|
||||
let source_info = self.source_info(span);
|
||||
self.cfg.goto(branch_otherwise, source_info, remainder_start);
|
||||
(branch, branch_start)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -2050,6 +2013,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&test,
|
||||
target_blocks,
|
||||
);
|
||||
|
||||
remainder_start.and(remaining_candidates)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3959,17 +3959,8 @@ impl<T> [T] {
|
|||
|
||||
/// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
|
||||
///
|
||||
/// This is a safe wrapper around [`slice::align_to`], so has the same weak
|
||||
/// postconditions as that method. You're only assured that
|
||||
/// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`.
|
||||
///
|
||||
/// Notably, all of the following are possible:
|
||||
/// - `prefix.len() >= LANES`.
|
||||
/// - `middle.is_empty()` despite `self.len() >= 3 * LANES`.
|
||||
/// - `suffix.len() >= LANES`.
|
||||
///
|
||||
/// That said, this is a safe method, so if you're only writing safe code,
|
||||
/// then this can at most cause incorrect logic, not unsoundness.
|
||||
/// This is a safe wrapper around [`slice::align_to`], so inherits the same
|
||||
/// guarantees as that method.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
@ -4033,17 +4024,8 @@ impl<T> [T] {
|
|||
/// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types,
|
||||
/// and a mutable suffix.
|
||||
///
|
||||
/// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak
|
||||
/// postconditions as that method. You're only assured that
|
||||
/// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`.
|
||||
///
|
||||
/// Notably, all of the following are possible:
|
||||
/// - `prefix.len() >= LANES`.
|
||||
/// - `middle.is_empty()` despite `self.len() >= 3 * LANES`.
|
||||
/// - `suffix.len() >= LANES`.
|
||||
///
|
||||
/// That said, this is a safe method, so if you're only writing safe code,
|
||||
/// then this can at most cause incorrect logic, not unsoundness.
|
||||
/// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same
|
||||
/// guarantees as that method.
|
||||
///
|
||||
/// This is the mutable version of [`slice::as_simd`]; see that for examples.
|
||||
///
|
||||
|
|
|
@ -991,13 +991,19 @@ impl Config {
|
|||
}
|
||||
|
||||
fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> {
|
||||
if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
|
||||
let (regex, replacement) = parse_normalize_rule(line)
|
||||
.unwrap_or_else(|| panic!("couldn't parse custom normalization rule: `{line}`"));
|
||||
Some((regex, replacement))
|
||||
} else {
|
||||
None
|
||||
let parsed = parse_cfg_name_directive(self, line, prefix);
|
||||
if parsed.outcome != MatchOutcome::Match {
|
||||
return None;
|
||||
}
|
||||
let name = parsed.name.expect("successful match always has a name");
|
||||
|
||||
let Some((regex, replacement)) = parse_normalize_rule(line) else {
|
||||
panic!(
|
||||
"couldn't parse custom normalization rule: `{line}`\n\
|
||||
help: expected syntax is: `{prefix}-{name}: \"REGEX\" -> \"REPLACEMENT\"`"
|
||||
);
|
||||
};
|
||||
Some((regex, replacement))
|
||||
}
|
||||
|
||||
fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
|
||||
|
|
|
@ -62,7 +62,7 @@ fn full_tested_match() -> () {
|
|||
_6 = &((_2 as Some).0: i32);
|
||||
_3 = &fake shallow _2;
|
||||
StorageLive(_7);
|
||||
_7 = guard() -> [return: bb8, unwind: bb16];
|
||||
_7 = guard() -> [return: bb8, unwind: bb15];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
|
@ -118,11 +118,7 @@ fn full_tested_match() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb15: {
|
||||
goto -> bb14;
|
||||
}
|
||||
|
||||
bb16 (cleanup): {
|
||||
bb15 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ fn full_tested_match2() -> () {
|
|||
_6 = &((_2 as Some).0: i32);
|
||||
_3 = &fake shallow _2;
|
||||
StorageLive(_7);
|
||||
_7 = guard() -> [return: bb8, unwind: bb16];
|
||||
_7 = guard() -> [return: bb8, unwind: bb15];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
|
@ -118,11 +118,7 @@ fn full_tested_match2() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb15: {
|
||||
goto -> bb14;
|
||||
}
|
||||
|
||||
bb16 (cleanup): {
|
||||
bb15 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,65 +38,61 @@ fn main() -> () {
|
|||
StorageLive(_2);
|
||||
_2 = Option::<i32>::Some(const 1_i32);
|
||||
PlaceMention(_2);
|
||||
_5 = discriminant(_2);
|
||||
switchInt(move _5) -> [1: bb8, otherwise: bb2];
|
||||
_4 = discriminant(_2);
|
||||
switchInt(move _4) -> [1: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
unreachable;
|
||||
falseEdge -> [real: bb14, imaginary: bb4];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
falseEdge -> [real: bb15, imaginary: bb3];
|
||||
falseEdge -> [real: bb9, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_4 = discriminant(_2);
|
||||
switchInt(move _4) -> [1: bb6, otherwise: bb4];
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_5 = discriminant(_2);
|
||||
switchInt(move _5) -> [1: bb6, otherwise: bb5];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_14);
|
||||
_14 = _2;
|
||||
_1 = const 4_i32;
|
||||
StorageDead(_14);
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
goto -> bb1;
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
falseEdge -> [real: bb16, imaginary: bb4];
|
||||
falseEdge -> [real: bb15, imaginary: bb5];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
goto -> bb4;
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
falseEdge -> [real: bb10, imaginary: bb2];
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
goto -> bb2;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageLive(_7);
|
||||
_7 = &((_2 as Some).0: i32);
|
||||
_3 = &fake shallow _2;
|
||||
StorageLive(_8);
|
||||
_8 = guard() -> [return: bb11, unwind: bb24];
|
||||
_8 = guard() -> [return: bb10, unwind: bb22];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
switchInt(move _8) -> [0: bb12, otherwise: bb11];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
switchInt(move _8) -> [0: bb13, otherwise: bb12];
|
||||
}
|
||||
|
||||
bb12: {
|
||||
StorageDead(_8);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
FakeRead(ForGuardBinding, _7);
|
||||
|
@ -105,42 +101,42 @@ fn main() -> () {
|
|||
_1 = const 1_i32;
|
||||
StorageDead(_6);
|
||||
StorageDead(_7);
|
||||
goto -> bb21;
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb12: {
|
||||
goto -> bb13;
|
||||
}
|
||||
|
||||
bb13: {
|
||||
goto -> bb14;
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
falseEdge -> [real: bb3, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb14: {
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
falseEdge -> [real: bb9, imaginary: bb2];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
StorageLive(_9);
|
||||
_9 = _2;
|
||||
_1 = const 2_i32;
|
||||
StorageDead(_9);
|
||||
goto -> bb21;
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb16: {
|
||||
bb15: {
|
||||
StorageLive(_11);
|
||||
_11 = &((_2 as Some).0: i32);
|
||||
_3 = &fake shallow _2;
|
||||
StorageLive(_12);
|
||||
StorageLive(_13);
|
||||
_13 = (*_11);
|
||||
_12 = guard2(move _13) -> [return: bb17, unwind: bb24];
|
||||
_12 = guard2(move _13) -> [return: bb16, unwind: bb22];
|
||||
}
|
||||
|
||||
bb16: {
|
||||
switchInt(move _12) -> [0: bb18, otherwise: bb17];
|
||||
}
|
||||
|
||||
bb17: {
|
||||
switchInt(move _12) -> [0: bb19, otherwise: bb18];
|
||||
}
|
||||
|
||||
bb18: {
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
|
@ -150,21 +146,21 @@ fn main() -> () {
|
|||
_1 = const 3_i32;
|
||||
StorageDead(_10);
|
||||
StorageDead(_11);
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb19: {
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb20: {
|
||||
bb18: {
|
||||
goto -> bb19;
|
||||
}
|
||||
|
||||
bb19: {
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
falseEdge -> [real: bb7, imaginary: bb4];
|
||||
falseEdge -> [real: bb7, imaginary: bb5];
|
||||
}
|
||||
|
||||
bb21: {
|
||||
bb20: {
|
||||
PlaceMention(_1);
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
|
@ -172,16 +168,12 @@ fn main() -> () {
|
|||
return;
|
||||
}
|
||||
|
||||
bb22: {
|
||||
bb21: {
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb23: {
|
||||
goto -> bb22;
|
||||
}
|
||||
|
||||
bb24 (cleanup): {
|
||||
bb22 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,16 @@ fn match_bool(_1: bool) -> usize {
|
|||
|
||||
bb0: {
|
||||
PlaceMention(_1);
|
||||
switchInt(_1) -> [0: bb2, otherwise: bb4];
|
||||
switchInt(_1) -> [0: bb1, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
_0 = const 20_usize;
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_0 = const 20_usize;
|
||||
goto -> bb7;
|
||||
falseEdge -> [real: bb5, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
|
@ -24,19 +23,16 @@ fn match_bool(_1: bool) -> usize {
|
|||
}
|
||||
|
||||
bb4: {
|
||||
falseEdge -> [real: bb6, imaginary: bb2];
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
goto -> bb2;
|
||||
_0 = const 10_usize;
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_0 = const 10_usize;
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ fn match_enum(_1: E1) -> bool {
|
|||
bb0: {
|
||||
PlaceMention(_1);
|
||||
_2 = discriminant(_1);
|
||||
switchInt(move _2) -> [0: bb3, 1: bb5, 2: bb7, otherwise: bb2];
|
||||
switchInt(move _2) -> [0: bb2, 1: bb4, 2: bb6, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -17,44 +17,40 @@ fn match_enum(_1: E1) -> bool {
|
|||
}
|
||||
|
||||
bb2: {
|
||||
goto -> bb1;
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb9;
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
goto -> bb2;
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
goto -> bb9;
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
goto -> bb2;
|
||||
_0 = const false;
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_0 = const false;
|
||||
goto -> bb11;
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb2;
|
||||
falseEdge -> [real: bb9, imaginary: bb6];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
falseEdge -> [real: bb10, imaginary: bb7];
|
||||
_0 = const true;
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_0 = const true;
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb11: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,52 +23,52 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
|
|||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
PlaceMention(_3);
|
||||
_9 = <str as PartialEq>::eq((_3.0: &str), const "a") -> [return: bb11, unwind: bb19];
|
||||
_9 = <str as PartialEq>::eq((_3.0: &str), const "a") -> [return: bb9, unwind: bb19];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt((_3.1: bool)) -> [0: bb2, otherwise: bb3];
|
||||
switchInt((_3.1: bool)) -> [0: bb10, otherwise: bb11];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
falseEdge -> [real: bb12, imaginary: bb5];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
falseEdge -> [real: bb16, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_8 = <str as PartialEq>::eq((_3.0: &str), const "b") -> [return: bb8, unwind: bb19];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
falseEdge -> [real: bb15, imaginary: bb3];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
switchInt(move _8) -> [0: bb1, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
switchInt(move _9) -> [0: bb5, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_0 = const 5_u32;
|
||||
goto -> bb18;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
falseEdge -> [real: bb17, imaginary: bb2];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
falseEdge -> [real: bb12, imaginary: bb7];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb6];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
falseEdge -> [real: bb16, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_8 = <str as PartialEq>::eq((_3.0: &str), const "b") -> [return: bb10, unwind: bb19];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
switchInt((_3.1: bool)) -> [0: bb1, otherwise: bb9];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
falseEdge -> [real: bb15, imaginary: bb5];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
switchInt(move _8) -> [0: bb1, otherwise: bb8];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
switchInt(move _9) -> [0: bb7, otherwise: bb4];
|
||||
falseEdge -> [real: bb17, imaginary: bb10];
|
||||
}
|
||||
|
||||
bb12: {
|
||||
|
@ -89,7 +89,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
|
|||
|
||||
bb14: {
|
||||
StorageDead(_10);
|
||||
falseEdge -> [real: bb5, imaginary: bb7];
|
||||
falseEdge -> [real: bb3, imaginary: bb5];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
|
|
|
@ -26,7 +26,7 @@ fn move_out_by_subslice() -> () {
|
|||
StorageLive(_2);
|
||||
_3 = SizeOf(i32);
|
||||
_4 = AlignOf(i32);
|
||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14];
|
||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -34,7 +34,7 @@ fn move_out_by_subslice() -> () {
|
|||
_6 = ShallowInitBox(move _5, i32);
|
||||
(*_6) = const 1_i32;
|
||||
_2 = move _6;
|
||||
drop(_6) -> [return: bb2, unwind: bb13];
|
||||
drop(_6) -> [return: bb2, unwind: bb12];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -42,7 +42,7 @@ fn move_out_by_subslice() -> () {
|
|||
StorageLive(_7);
|
||||
_8 = SizeOf(i32);
|
||||
_9 = AlignOf(i32);
|
||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13];
|
||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
|
@ -50,18 +50,18 @@ fn move_out_by_subslice() -> () {
|
|||
_11 = ShallowInitBox(move _10, i32);
|
||||
(*_11) = const 2_i32;
|
||||
_7 = move _11;
|
||||
drop(_11) -> [return: bb4, unwind: bb12];
|
||||
drop(_11) -> [return: bb4, unwind: bb11];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_11);
|
||||
_1 = [move _2, move _7];
|
||||
drop(_7) -> [return: bb5, unwind: bb13];
|
||||
drop(_7) -> [return: bb5, unwind: bb12];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_7);
|
||||
drop(_2) -> [return: bb6, unwind: bb14];
|
||||
drop(_2) -> [return: bb6, unwind: bb13];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
|
@ -71,7 +71,7 @@ fn move_out_by_subslice() -> () {
|
|||
StorageLive(_12);
|
||||
_12 = move _1[0..2];
|
||||
_0 = const ();
|
||||
drop(_12) -> [return: bb9, unwind: bb11];
|
||||
drop(_12) -> [return: bb8, unwind: bb10];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
@ -80,32 +80,28 @@ fn move_out_by_subslice() -> () {
|
|||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb7;
|
||||
StorageDead(_12);
|
||||
drop(_1) -> [return: bb9, unwind: bb13];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_12);
|
||||
drop(_1) -> [return: bb10, unwind: bb14];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
||||
bb10 (cleanup): {
|
||||
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb11 (cleanup): {
|
||||
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
|
||||
drop(_7) -> [return: bb12, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb12 (cleanup): {
|
||||
drop(_7) -> [return: bb13, unwind terminate(cleanup)];
|
||||
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb13 (cleanup): {
|
||||
drop(_2) -> [return: bb14, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb14 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn move_out_from_end() -> () {
|
|||
StorageLive(_2);
|
||||
_3 = SizeOf(i32);
|
||||
_4 = AlignOf(i32);
|
||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb14];
|
||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb13];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -34,7 +34,7 @@ fn move_out_from_end() -> () {
|
|||
_6 = ShallowInitBox(move _5, i32);
|
||||
(*_6) = const 1_i32;
|
||||
_2 = move _6;
|
||||
drop(_6) -> [return: bb2, unwind: bb13];
|
||||
drop(_6) -> [return: bb2, unwind: bb12];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -42,7 +42,7 @@ fn move_out_from_end() -> () {
|
|||
StorageLive(_7);
|
||||
_8 = SizeOf(i32);
|
||||
_9 = AlignOf(i32);
|
||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb13];
|
||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb12];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
|
@ -50,18 +50,18 @@ fn move_out_from_end() -> () {
|
|||
_11 = ShallowInitBox(move _10, i32);
|
||||
(*_11) = const 2_i32;
|
||||
_7 = move _11;
|
||||
drop(_11) -> [return: bb4, unwind: bb12];
|
||||
drop(_11) -> [return: bb4, unwind: bb11];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_11);
|
||||
_1 = [move _2, move _7];
|
||||
drop(_7) -> [return: bb5, unwind: bb13];
|
||||
drop(_7) -> [return: bb5, unwind: bb12];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_7);
|
||||
drop(_2) -> [return: bb6, unwind: bb14];
|
||||
drop(_2) -> [return: bb6, unwind: bb13];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
|
@ -71,7 +71,7 @@ fn move_out_from_end() -> () {
|
|||
StorageLive(_12);
|
||||
_12 = move _1[1 of 2];
|
||||
_0 = const ();
|
||||
drop(_12) -> [return: bb9, unwind: bb11];
|
||||
drop(_12) -> [return: bb8, unwind: bb10];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
@ -80,32 +80,28 @@ fn move_out_from_end() -> () {
|
|||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb7;
|
||||
StorageDead(_12);
|
||||
drop(_1) -> [return: bb9, unwind: bb13];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_12);
|
||||
drop(_1) -> [return: bb10, unwind: bb14];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
||||
bb10 (cleanup): {
|
||||
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb11 (cleanup): {
|
||||
drop(_1) -> [return: bb14, unwind terminate(cleanup)];
|
||||
drop(_7) -> [return: bb12, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb12 (cleanup): {
|
||||
drop(_7) -> [return: bb13, unwind terminate(cleanup)];
|
||||
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb13 (cleanup): {
|
||||
drop(_2) -> [return: bb14, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb14 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,59 +22,55 @@
|
|||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_7 = Len((*_2));
|
||||
_8 = const 4_usize;
|
||||
_9 = Ge(move _7, move _8);
|
||||
- switchInt(move _9) -> [0: bb2, otherwise: bb7];
|
||||
+ switchInt(move _9) -> [0: bb2, otherwise: bb6];
|
||||
_4 = Len((*_2));
|
||||
_5 = const 4_usize;
|
||||
_6 = Ge(move _4, move _5);
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_4 = Len((*_2));
|
||||
_5 = const 3_usize;
|
||||
_6 = Ge(move _4, move _5);
|
||||
- switchInt(move _6) -> [0: bb3, otherwise: bb4];
|
||||
+ switchInt(move _6) -> [0: bb10, otherwise: bb3];
|
||||
_7 = Len((*_2));
|
||||
_8 = const 3_usize;
|
||||
_9 = Ge(move _7, move _8);
|
||||
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
|
||||
+ switchInt(move _9) -> [0: bb10, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- _0 = const false;
|
||||
- goto -> bb14;
|
||||
+ switchInt((*_2)[0 of 3]) -> [47: bb4, otherwise: bb10];
|
||||
switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
- switchInt((*_2)[0 of 3]) -> [47: bb5, otherwise: bb3];
|
||||
+ switchInt((*_2)[1 of 3]) -> [47: bb5, otherwise: bb10];
|
||||
switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
- switchInt((*_2)[1 of 3]) -> [47: bb6, otherwise: bb3];
|
||||
+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
|
||||
switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb3];
|
||||
+ switchInt((*_2)[0 of 4]) -> [47: bb7, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
- switchInt((*_2)[0 of 4]) -> [47: bb8, otherwise: bb2];
|
||||
+ switchInt((*_2)[1 of 4]) -> [47: bb8, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
- switchInt((*_2)[1 of 4]) -> [47: bb9, otherwise: bb2];
|
||||
+ switchInt((*_2)[2 of 4]) -> [47: bb9, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
- switchInt((*_2)[2 of 4]) -> [47: bb10, otherwise: bb2];
|
||||
- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
|
||||
+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
- _0 = const false;
|
||||
- goto -> bb14;
|
||||
+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
|
||||
+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
|
||||
+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
|
||||
- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
|
||||
- }
|
||||
-
|
||||
- bb11: {
|
||||
|
|
|
@ -22,59 +22,55 @@
|
|||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_7 = Len((*_2));
|
||||
_8 = const 4_usize;
|
||||
_9 = Ge(move _7, move _8);
|
||||
- switchInt(move _9) -> [0: bb2, otherwise: bb7];
|
||||
+ switchInt(move _9) -> [0: bb2, otherwise: bb6];
|
||||
_4 = Len((*_2));
|
||||
_5 = const 4_usize;
|
||||
_6 = Ge(move _4, move _5);
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_4 = Len((*_2));
|
||||
_5 = const 3_usize;
|
||||
_6 = Ge(move _4, move _5);
|
||||
- switchInt(move _6) -> [0: bb3, otherwise: bb4];
|
||||
+ switchInt(move _6) -> [0: bb10, otherwise: bb3];
|
||||
_7 = Len((*_2));
|
||||
_8 = const 3_usize;
|
||||
_9 = Ge(move _7, move _8);
|
||||
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
|
||||
+ switchInt(move _9) -> [0: bb10, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- _0 = const false;
|
||||
- goto -> bb14;
|
||||
+ switchInt((*_2)[0 of 3]) -> [47: bb4, otherwise: bb10];
|
||||
switchInt((*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
- switchInt((*_2)[0 of 3]) -> [47: bb5, otherwise: bb3];
|
||||
+ switchInt((*_2)[1 of 3]) -> [47: bb5, otherwise: bb10];
|
||||
switchInt((*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
- switchInt((*_2)[1 of 3]) -> [47: bb6, otherwise: bb3];
|
||||
+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
|
||||
switchInt((*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb3];
|
||||
+ switchInt((*_2)[0 of 4]) -> [47: bb7, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
- switchInt((*_2)[0 of 4]) -> [47: bb8, otherwise: bb2];
|
||||
+ switchInt((*_2)[1 of 4]) -> [47: bb8, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
- switchInt((*_2)[1 of 4]) -> [47: bb9, otherwise: bb2];
|
||||
+ switchInt((*_2)[2 of 4]) -> [47: bb9, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
- switchInt((*_2)[2 of 4]) -> [47: bb10, otherwise: bb2];
|
||||
- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
|
||||
+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
- _0 = const false;
|
||||
- goto -> bb14;
|
||||
+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
|
||||
+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
|
||||
+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
|
||||
- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
|
||||
- }
|
||||
-
|
||||
- bb11: {
|
||||
|
|
|
@ -19,8 +19,4 @@ fn bar(_1: [(Never, u32); 1]) -> u32 {
|
|||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
goto -> bb1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ fn main() -> () {
|
|||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb7];
|
||||
_1 = std::mem::size_of::<Foo>() -> [return: bb1, unwind: bb5];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -40,7 +40,7 @@ fn main() -> () {
|
|||
_6 = const 0_usize;
|
||||
_7 = Len(_2);
|
||||
_8 = Lt(_6, _7);
|
||||
assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb4, unwind: bb7];
|
||||
assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb5];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -49,10 +49,6 @@ fn main() -> () {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb2;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_5 = (_2[_6].0: u64);
|
||||
PlaceMention(_5);
|
||||
StorageDead(_6);
|
||||
|
@ -62,16 +58,12 @@ fn main() -> () {
|
|||
return;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
bb4: {
|
||||
FakeRead(ForMatchedPlace(None), _5);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
goto -> bb5;
|
||||
}
|
||||
|
||||
bb7 (cleanup): {
|
||||
bb5 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,11 @@ fn f(_1: Void) -> ! {
|
|||
|
||||
bb0: {
|
||||
PlaceMention(_1);
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb1: {
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
bb1: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ fn bar(_1: Box<[T]>) -> () {
|
|||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = &(*_1);
|
||||
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb5];
|
||||
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb4];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -20,7 +20,7 @@ fn bar(_1: Box<[T]>) -> () {
|
|||
PlaceMention((*_2));
|
||||
StorageDead(_2);
|
||||
_0 = const ();
|
||||
drop(_1) -> [return: bb4, unwind: bb6];
|
||||
drop(_1) -> [return: bb3, unwind: bb5];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -29,18 +29,14 @@ fn bar(_1: Box<[T]>) -> () {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb2;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
return;
|
||||
}
|
||||
|
||||
bb5 (cleanup): {
|
||||
drop(_1) -> [return: bb6, unwind terminate(cleanup)];
|
||||
bb4 (cleanup): {
|
||||
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
|
||||
}
|
||||
|
||||
bb6 (cleanup): {
|
||||
bb5 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ fn hey(_1: &[T]) -> () {
|
|||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = &(*_1);
|
||||
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb4];
|
||||
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb3];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -32,11 +32,7 @@ fn hey(_1: &[T]) -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb2;
|
||||
}
|
||||
|
||||
bb4 (cleanup): {
|
||||
bb3 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ fn main() -> () {
|
|||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25];
|
||||
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -91,7 +91,7 @@ fn main() -> () {
|
|||
_11 = &(*_8);
|
||||
StorageLive(_12);
|
||||
_12 = &(*_9);
|
||||
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25];
|
||||
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -100,24 +100,20 @@ fn main() -> () {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb2;
|
||||
switchInt(move _10) -> [0: bb5, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
switchInt(move _10) -> [0: bb6, otherwise: bb5];
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb9;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb10;
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
StorageLive(_14);
|
||||
|
@ -136,10 +132,10 @@ fn main() -> () {
|
|||
_19 = &(*_20);
|
||||
StorageLive(_21);
|
||||
_21 = Option::<Arguments<'_>>::None;
|
||||
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25;
|
||||
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
bb7: {
|
||||
StorageDead(_21);
|
||||
StorageDead(_19);
|
||||
StorageDead(_17);
|
||||
|
@ -151,23 +147,23 @@ fn main() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
goto -> bb11;
|
||||
_1 = const ();
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_1 = const ();
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb11: {
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
goto -> bb12;
|
||||
}
|
||||
|
||||
bb12: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
StorageDead(_4);
|
||||
|
@ -177,10 +173,10 @@ fn main() -> () {
|
|||
StorageLive(_23);
|
||||
StorageLive(_24);
|
||||
StorageLive(_25);
|
||||
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25];
|
||||
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23];
|
||||
}
|
||||
|
||||
bb13: {
|
||||
bb12: {
|
||||
_24 = &_25;
|
||||
StorageLive(_26);
|
||||
StorageLive(_27);
|
||||
|
@ -199,33 +195,29 @@ fn main() -> () {
|
|||
_31 = &(*_28);
|
||||
StorageLive(_32);
|
||||
_32 = &(*_29);
|
||||
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25];
|
||||
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23];
|
||||
}
|
||||
|
||||
bb14: {
|
||||
bb13: {
|
||||
FakeRead(ForMatchedPlace(None), _23);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb14: {
|
||||
switchInt(move _30) -> [0: bb16, otherwise: bb15];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
goto -> bb14;
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb16: {
|
||||
switchInt(move _30) -> [0: bb18, otherwise: bb17];
|
||||
goto -> bb17;
|
||||
}
|
||||
|
||||
bb17: {
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
goto -> bb22;
|
||||
}
|
||||
|
||||
bb18: {
|
||||
goto -> bb19;
|
||||
}
|
||||
|
||||
bb19: {
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
StorageLive(_34);
|
||||
|
@ -244,10 +236,10 @@ fn main() -> () {
|
|||
_39 = &(*_40);
|
||||
StorageLive(_41);
|
||||
_41 = Option::<Arguments<'_>>::None;
|
||||
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25;
|
||||
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23;
|
||||
}
|
||||
|
||||
bb20: {
|
||||
bb18: {
|
||||
StorageDead(_41);
|
||||
StorageDead(_39);
|
||||
StorageDead(_37);
|
||||
|
@ -259,23 +251,23 @@ fn main() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb21: {
|
||||
goto -> bb23;
|
||||
bb19: {
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb22: {
|
||||
bb20: {
|
||||
_22 = const ();
|
||||
goto -> bb23;
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb23: {
|
||||
bb21: {
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
goto -> bb24;
|
||||
goto -> bb22;
|
||||
}
|
||||
|
||||
bb24: {
|
||||
bb22: {
|
||||
StorageDead(_27);
|
||||
StorageDead(_25);
|
||||
StorageDead(_23);
|
||||
|
@ -284,7 +276,7 @@ fn main() -> () {
|
|||
return;
|
||||
}
|
||||
|
||||
bb25 (cleanup): {
|
||||
bb23 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ fn main() -> () {
|
|||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb25];
|
||||
_4 = function_with_bytes::<&*b"AAAA">() -> [return: bb1, unwind: bb23];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -91,7 +91,7 @@ fn main() -> () {
|
|||
_11 = &(*_8);
|
||||
StorageLive(_12);
|
||||
_12 = &(*_9);
|
||||
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb4, unwind: bb25];
|
||||
_10 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _11, move _12) -> [return: bb3, unwind: bb23];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -100,24 +100,20 @@ fn main() -> () {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb2;
|
||||
switchInt(move _10) -> [0: bb5, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
switchInt(move _10) -> [0: bb6, otherwise: bb5];
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb9;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
goto -> bb10;
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb6: {
|
||||
goto -> bb7;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
StorageLive(_14);
|
||||
|
@ -136,10 +132,10 @@ fn main() -> () {
|
|||
_19 = &(*_20);
|
||||
StorageLive(_21);
|
||||
_21 = Option::<Arguments<'_>>::None;
|
||||
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb25;
|
||||
_15 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _16, move _17, move _19, move _21) -> bb23;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
bb7: {
|
||||
StorageDead(_21);
|
||||
StorageDead(_19);
|
||||
StorageDead(_17);
|
||||
|
@ -151,23 +147,23 @@ fn main() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
goto -> bb11;
|
||||
_1 = const ();
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_1 = const ();
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb11: {
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
goto -> bb12;
|
||||
}
|
||||
|
||||
bb12: {
|
||||
StorageDead(_7);
|
||||
StorageDead(_6);
|
||||
StorageDead(_4);
|
||||
|
@ -177,10 +173,10 @@ fn main() -> () {
|
|||
StorageLive(_23);
|
||||
StorageLive(_24);
|
||||
StorageLive(_25);
|
||||
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb13, unwind: bb25];
|
||||
_25 = function_with_bytes::<&*b"AAAA">() -> [return: bb12, unwind: bb23];
|
||||
}
|
||||
|
||||
bb13: {
|
||||
bb12: {
|
||||
_24 = &_25;
|
||||
StorageLive(_26);
|
||||
StorageLive(_27);
|
||||
|
@ -199,33 +195,29 @@ fn main() -> () {
|
|||
_31 = &(*_28);
|
||||
StorageLive(_32);
|
||||
_32 = &(*_29);
|
||||
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb16, unwind: bb25];
|
||||
_30 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _31, move _32) -> [return: bb14, unwind: bb23];
|
||||
}
|
||||
|
||||
bb14: {
|
||||
bb13: {
|
||||
FakeRead(ForMatchedPlace(None), _23);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb14: {
|
||||
switchInt(move _30) -> [0: bb16, otherwise: bb15];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
goto -> bb14;
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
goto -> bb20;
|
||||
}
|
||||
|
||||
bb16: {
|
||||
switchInt(move _30) -> [0: bb18, otherwise: bb17];
|
||||
goto -> bb17;
|
||||
}
|
||||
|
||||
bb17: {
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
goto -> bb22;
|
||||
}
|
||||
|
||||
bb18: {
|
||||
goto -> bb19;
|
||||
}
|
||||
|
||||
bb19: {
|
||||
StorageDead(_32);
|
||||
StorageDead(_31);
|
||||
StorageLive(_34);
|
||||
|
@ -244,10 +236,10 @@ fn main() -> () {
|
|||
_39 = &(*_40);
|
||||
StorageLive(_41);
|
||||
_41 = Option::<Arguments<'_>>::None;
|
||||
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb25;
|
||||
_35 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _36, move _37, move _39, move _41) -> bb23;
|
||||
}
|
||||
|
||||
bb20: {
|
||||
bb18: {
|
||||
StorageDead(_41);
|
||||
StorageDead(_39);
|
||||
StorageDead(_37);
|
||||
|
@ -259,23 +251,23 @@ fn main() -> () {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
bb21: {
|
||||
goto -> bb23;
|
||||
bb19: {
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb22: {
|
||||
bb20: {
|
||||
_22 = const ();
|
||||
goto -> bb23;
|
||||
goto -> bb21;
|
||||
}
|
||||
|
||||
bb23: {
|
||||
bb21: {
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
goto -> bb24;
|
||||
goto -> bb22;
|
||||
}
|
||||
|
||||
bb24: {
|
||||
bb22: {
|
||||
StorageDead(_27);
|
||||
StorageDead(_25);
|
||||
StorageDead(_23);
|
||||
|
@ -284,7 +276,7 @@ fn main() -> () {
|
|||
return;
|
||||
}
|
||||
|
||||
bb25 (cleanup): {
|
||||
bb23 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,25 +32,33 @@
|
|||
|
||||
bb0: {
|
||||
PlaceMention(_2);
|
||||
- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
|
||||
- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
|
||||
- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
|
||||
+ switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3];
|
||||
- falseEdge -> [real: bb8, imaginary: bb1];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- falseEdge -> [real: bb20, imaginary: bb4];
|
||||
- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5];
|
||||
- }
|
||||
-
|
||||
- bb4: {
|
||||
- falseEdge -> [real: bb13, imaginary: bb3];
|
||||
- }
|
||||
-
|
||||
- bb5: {
|
||||
- falseEdge -> [real: bb20, imaginary: bb6];
|
||||
- }
|
||||
-
|
||||
- bb6: {
|
||||
StorageLive(_15);
|
||||
_15 = (_2.1: bool);
|
||||
StorageLive(_16);
|
||||
|
@ -59,14 +67,6 @@
|
|||
+ goto -> bb16;
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
- falseEdge -> [real: bb13, imaginary: bb2];
|
||||
- }
|
||||
-
|
||||
- bb6: {
|
||||
- falseEdge -> [real: bb8, imaginary: bb1];
|
||||
- }
|
||||
-
|
||||
- bb7: {
|
||||
+ bb4: {
|
||||
_0 = const 1_i32;
|
||||
|
@ -184,7 +184,7 @@
|
|||
StorageDead(_12);
|
||||
StorageDead(_8);
|
||||
StorageDead(_6);
|
||||
- falseEdge -> [real: bb2, imaginary: bb2];
|
||||
- falseEdge -> [real: bb3, imaginary: bb3];
|
||||
+ goto -> bb2;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,25 +32,33 @@
|
|||
|
||||
bb0: {
|
||||
PlaceMention(_2);
|
||||
- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
|
||||
- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
|
||||
- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
|
||||
+ switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3];
|
||||
- falseEdge -> [real: bb8, imaginary: bb1];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- falseEdge -> [real: bb20, imaginary: bb4];
|
||||
- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5];
|
||||
- }
|
||||
-
|
||||
- bb4: {
|
||||
- falseEdge -> [real: bb13, imaginary: bb3];
|
||||
- }
|
||||
-
|
||||
- bb5: {
|
||||
- falseEdge -> [real: bb20, imaginary: bb6];
|
||||
- }
|
||||
-
|
||||
- bb6: {
|
||||
StorageLive(_15);
|
||||
_15 = (_2.1: bool);
|
||||
StorageLive(_16);
|
||||
|
@ -59,14 +67,6 @@
|
|||
+ goto -> bb16;
|
||||
}
|
||||
|
||||
- bb5: {
|
||||
- falseEdge -> [real: bb13, imaginary: bb2];
|
||||
- }
|
||||
-
|
||||
- bb6: {
|
||||
- falseEdge -> [real: bb8, imaginary: bb1];
|
||||
- }
|
||||
-
|
||||
- bb7: {
|
||||
+ bb4: {
|
||||
_0 = const 1_i32;
|
||||
|
@ -184,7 +184,7 @@
|
|||
StorageDead(_12);
|
||||
StorageDead(_8);
|
||||
StorageDead(_6);
|
||||
- falseEdge -> [real: bb2, imaginary: bb2];
|
||||
- falseEdge -> [real: bb3, imaginary: bb3];
|
||||
+ goto -> bb2;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,24 +18,24 @@ fn shortcut_second_or() -> () {
|
|||
_1 = (move _2, const 0_i32);
|
||||
StorageDead(_2);
|
||||
PlaceMention(_1);
|
||||
switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb4, otherwise: bb2];
|
||||
switchInt(((_1.0: (i32, i32)).0: i32)) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb4, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_0 = const ();
|
||||
goto -> bb14;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
switchInt(((_1.0: (i32, i32)).1: i32)) -> [1: bb3, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
switchInt((_1.1: i32)) -> [2: bb5, 3: bb6, otherwise: bb1];
|
||||
switchInt((_1.1: i32)) -> [2: bb7, 3: bb8, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
|
@ -43,7 +43,7 @@ fn shortcut_second_or() -> () {
|
|||
}
|
||||
|
||||
bb6: {
|
||||
falseEdge -> [real: bb11, imaginary: bb2];
|
||||
falseEdge -> [real: bb11, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
@ -51,7 +51,7 @@ fn shortcut_second_or() -> () {
|
|||
}
|
||||
|
||||
bb8: {
|
||||
falseEdge -> [real: bb13, imaginary: bb1];
|
||||
falseEdge -> [real: bb13, imaginary: bb3];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Regression test for <https://github.com/rust-lang/rust/issues/127545>.
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
|
||||
arg //~ ERROR 5:5: 5:8: mismatched types [E0308]
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/transforming-option-ref-issue-127545.rs:5:5
|
||||
|
|
||||
LL | pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
|
||||
| -------------- expected `Option<&[i32]>` because of return type
|
||||
LL | arg
|
||||
| ^^^ expected `Option<&[i32]>`, found `Option<&Vec<i32>>`
|
||||
|
|
||||
= note: expected enum `Option<&[i32]>`
|
||||
found enum `Option<&Vec<i32>>`
|
||||
help: try using `.map(|v| &**v)` to convert `Option<&Vec<i32>>` to `Option<&[i32]>`
|
||||
|
|
||||
LL | arg.map(|v| &**v)
|
||||
| ++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue