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:
bors 2024-07-12 03:40:38 +00:00
commit b286722878
28 changed files with 559 additions and 638 deletions

View File

@ -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();

View File

@ -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.

View File

@ -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>,

View File

@ -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)
}
}

View File

@ -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.
///

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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: {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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: {

View File

@ -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: {

View File

@ -19,8 +19,4 @@ fn bar(_1: [(Never, u32); 1]) -> u32 {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb2: {
goto -> bb1;
}
}

View File

@ -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;
}
}

View File

@ -6,15 +6,11 @@ fn f(_1: Void) -> ! {
bb0: {
PlaceMention(_1);
goto -> bb1;
}
bb1: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb2: {
bb1: {
return;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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: {

View File

@ -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]
}

View File

@ -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`.