Auto merge of #80105 - JohnTitor:rollup-8c030u5, r=JohnTitor
Rollup of 11 pull requests Successful merges: - #79051 (Implement if-let match guards) - #79877 (Allow `since="TBD"` for rustc_deprecated) - #79882 (Fix issue #78496) - #80026 (expand-yaml-anchors: Make the output directory separator-insensitive) - #80039 (Remove unused `TyEncoder::tcx` required method) - #80069 (Test that `core::assert!` is valid) - #80072 (Fixed conflict with drop elaboration and coverage) - #80073 (Add support for target aliases) - #80082 (Revert #78790 - rust-src vendoring) - #80097 (Add `popcount` and `popcnt` as doc aliases for `count_ones` methods.) - #80103 (Remove docs for non-existent parameters in `rustc_expand`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9b84d36a0b
@ -505,14 +505,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||
let pat = self.lower_pat(&arm.pat);
|
||||
let guard = arm.guard.as_ref().map(|cond| {
|
||||
if let ExprKind::Let(ref pat, ref scrutinee) = cond.kind {
|
||||
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
|
||||
} else {
|
||||
hir::Guard::If(self.lower_expr(cond))
|
||||
}
|
||||
});
|
||||
hir::Arm {
|
||||
hir_id: self.next_id(),
|
||||
attrs: self.lower_attrs(&arm.attrs),
|
||||
pat: self.lower_pat(&arm.pat),
|
||||
guard: match arm.guard {
|
||||
Some(ref x) => Some(hir::Guard::If(self.lower_expr(x))),
|
||||
_ => None,
|
||||
},
|
||||
pat,
|
||||
guard,
|
||||
body: self.lower_expr(&arm.body),
|
||||
span: arm.span,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! This is an NFA-based parser, which calls out to the main rust parser for named non-terminals
|
||||
//! This is an NFA-based parser, which calls out to the main Rust parser for named non-terminals
|
||||
//! (which it commits to fully when it hits one in a grammar). There's a set of current NFA threads
|
||||
//! and a set of next ones. Instead of NTs, we have a special case for Kleene star. The big-O, in
|
||||
//! pathological cases, is worse than traditional use of NFA or Earley parsing, but it's an easier
|
||||
@ -422,7 +422,6 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `sess`: the parsing session into which errors are emitted.
|
||||
/// - `cur_items`: the set of current items to be processed. This should be empty by the end of a
|
||||
/// successful execution of this function.
|
||||
/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
|
||||
@ -430,8 +429,6 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
|
||||
/// - `eof_items`: the set of items that would be valid if this was the EOF.
|
||||
/// - `bb_items`: the set of items that are waiting for the black-box parser.
|
||||
/// - `token`: the current token of the parser.
|
||||
/// - `span`: the `Span` in the source code corresponding to the token trees we are trying to match
|
||||
/// against the matcher positions in `cur_items`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
|
@ -1160,6 +1160,7 @@ pub struct Arm<'hir> {
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
pub enum Guard<'hir> {
|
||||
If(&'hir Expr<'hir>),
|
||||
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable_Generic)]
|
||||
@ -1721,6 +1722,8 @@ pub enum MatchSource {
|
||||
IfDesugar { contains_else_clause: bool },
|
||||
/// An `if let _ = _ { .. }` (optionally with `else { .. }`).
|
||||
IfLetDesugar { contains_else_clause: bool },
|
||||
/// An `if let _ = _ => { .. }` match guard.
|
||||
IfLetGuardDesugar,
|
||||
/// A `while _ { .. }` (which was desugared to a `loop { match _ { .. } }`).
|
||||
WhileDesugar,
|
||||
/// A `while let _ = _ { .. }` (which was desugared to a
|
||||
@ -1739,7 +1742,7 @@ impl MatchSource {
|
||||
use MatchSource::*;
|
||||
match self {
|
||||
Normal => "match",
|
||||
IfDesugar { .. } | IfLetDesugar { .. } => "if",
|
||||
IfDesugar { .. } | IfLetDesugar { .. } | IfLetGuardDesugar => "if",
|
||||
WhileDesugar | WhileLetDesugar => "while",
|
||||
ForLoopDesugar => "for",
|
||||
TryDesugar => "?",
|
||||
|
@ -1228,6 +1228,10 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
|
||||
if let Some(ref g) = arm.guard {
|
||||
match g {
|
||||
Guard::If(ref e) => visitor.visit_expr(e),
|
||||
Guard::IfLet(ref pat, ref e) => {
|
||||
visitor.visit_pat(pat);
|
||||
visitor.visit_expr(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
visitor.visit_expr(&arm.body);
|
||||
|
@ -2002,6 +2002,15 @@ impl<'a> State<'a> {
|
||||
self.print_expr(&e);
|
||||
self.s.space();
|
||||
}
|
||||
hir::Guard::IfLet(pat, e) => {
|
||||
self.word_nbsp("if");
|
||||
self.word_nbsp("let");
|
||||
self.print_pat(&pat);
|
||||
self.s.space();
|
||||
self.word_space("=");
|
||||
self.print_expr(&e);
|
||||
self.s.space();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.word_space("=>");
|
||||
|
@ -319,10 +319,6 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
|
||||
self.opaque.position()
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
|
||||
&mut self.type_shorthands
|
||||
}
|
||||
|
@ -132,37 +132,37 @@ pub fn report_unstable(
|
||||
/// Checks whether an item marked with `deprecated(since="X")` is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc version).
|
||||
pub fn deprecation_in_effect(is_since_rustc_version: bool, since: Option<&str>) -> bool {
|
||||
let since = if let Some(since) = since {
|
||||
if is_since_rustc_version {
|
||||
since
|
||||
} else {
|
||||
// We assume that the deprecation is in effect if it's not a
|
||||
// rustc version.
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// If since attribute is not set, then we're definitely in effect.
|
||||
return true;
|
||||
};
|
||||
fn parse_version(ver: &str) -> Vec<u32> {
|
||||
// We ignore non-integer components of the version (e.g., "nightly").
|
||||
ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect()
|
||||
}
|
||||
|
||||
if let Some(rustc) = option_env!("CFG_RELEASE") {
|
||||
let since: Vec<u32> = parse_version(&since);
|
||||
let rustc: Vec<u32> = parse_version(rustc);
|
||||
// We simply treat invalid `since` attributes as relating to a previous
|
||||
// Rust version, thus always displaying the warning.
|
||||
if since.len() != 3 {
|
||||
return true;
|
||||
}
|
||||
since <= rustc
|
||||
} else {
|
||||
// By default, a deprecation warning applies to
|
||||
// the current version of the compiler.
|
||||
true
|
||||
if !is_since_rustc_version {
|
||||
// The `since` field doesn't have semantic purpose in the stable `deprecated`
|
||||
// attribute, only in `rustc_deprecated`.
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(since) = since {
|
||||
if since == "TBD" {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(rustc) = option_env!("CFG_RELEASE") {
|
||||
let since: Vec<u32> = parse_version(&since);
|
||||
let rustc: Vec<u32> = parse_version(rustc);
|
||||
// We simply treat invalid `since` attributes as relating to a previous
|
||||
// Rust version, thus always displaying the warning.
|
||||
if since.len() != 3 {
|
||||
return true;
|
||||
}
|
||||
return since <= rustc;
|
||||
}
|
||||
};
|
||||
|
||||
// Assume deprecation is in effect if "since" field is missing
|
||||
// or if we can't determine the current Rust version.
|
||||
true
|
||||
}
|
||||
|
||||
pub fn deprecation_suggestion(
|
||||
@ -182,19 +182,24 @@ pub fn deprecation_suggestion(
|
||||
}
|
||||
|
||||
pub fn deprecation_message(depr: &Deprecation, kind: &str, path: &str) -> (String, &'static Lint) {
|
||||
let (message, lint) = if deprecation_in_effect(
|
||||
depr.is_since_rustc_version,
|
||||
depr.since.map(Symbol::as_str).as_deref(),
|
||||
) {
|
||||
let since = depr.since.map(Symbol::as_str);
|
||||
let (message, lint) = if deprecation_in_effect(depr.is_since_rustc_version, since.as_deref()) {
|
||||
(format!("use of deprecated {} `{}`", kind, path), DEPRECATED)
|
||||
} else {
|
||||
(
|
||||
format!(
|
||||
"use of {} `{}` that will be deprecated in future version {}",
|
||||
kind,
|
||||
path,
|
||||
depr.since.unwrap()
|
||||
),
|
||||
if since.as_deref() == Some("TBD") {
|
||||
format!(
|
||||
"use of {} `{}` that will be deprecated in a future Rust version",
|
||||
kind, path
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"use of {} `{}` that will be deprecated in future version {}",
|
||||
kind,
|
||||
path,
|
||||
since.unwrap()
|
||||
)
|
||||
},
|
||||
DEPRECATED_IN_FUTURE,
|
||||
)
|
||||
};
|
||||
|
@ -69,7 +69,6 @@ impl OpaqueEncoder for rustc_serialize::opaque::Encoder {
|
||||
pub trait TyEncoder<'tcx>: Encoder {
|
||||
const CLEAR_CROSS_CRATE: bool;
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
fn position(&self) -> usize;
|
||||
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
|
||||
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize>;
|
||||
|
@ -1044,9 +1044,6 @@ where
|
||||
{
|
||||
const CLEAR_CROSS_CRATE: bool = false;
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
fn position(&self) -> usize {
|
||||
self.encoder.encoder_position()
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
||||
inject_statement(
|
||||
self.mir_body,
|
||||
counter_kind,
|
||||
self.bcb_last_bb(bcb),
|
||||
self.bcb_leader_bb(bcb),
|
||||
Some(make_code_region(file_name, &self.source_file, span, body_span)),
|
||||
);
|
||||
}
|
||||
@ -470,7 +470,7 @@ fn inject_statement(
|
||||
code_region: some_code_region,
|
||||
}),
|
||||
};
|
||||
data.statements.push(statement);
|
||||
data.statements.insert(0, statement);
|
||||
}
|
||||
|
||||
// Non-code expressions are injected into the coverage map, without generating executable code.
|
||||
|
@ -284,6 +284,33 @@ impl<'a, 'tcx> Helper<'a, 'tcx> {
|
||||
return None;
|
||||
}
|
||||
|
||||
// when the second place is a projection of the first one, it's not safe to calculate their discriminant values sequentially.
|
||||
// for example, this should not be optimized:
|
||||
//
|
||||
// ```rust
|
||||
// enum E<'a> { Empty, Some(&'a E<'a>), }
|
||||
// let Some(Some(_)) = e;
|
||||
// ```
|
||||
//
|
||||
// ```mir
|
||||
// bb0: {
|
||||
// _2 = discriminant(*_1)
|
||||
// switchInt(_2) -> [...]
|
||||
// }
|
||||
// bb1: {
|
||||
// _3 = discriminant(*(((*_1) as Some).0: &E))
|
||||
// switchInt(_3) -> [...]
|
||||
// }
|
||||
// ```
|
||||
let discr_place = discr_info.place_of_adt_discr_read;
|
||||
let this_discr_place = this_bb_discr_info.place_of_adt_discr_read;
|
||||
if discr_place.local == this_discr_place.local
|
||||
&& this_discr_place.projection.starts_with(discr_place.projection)
|
||||
{
|
||||
trace!("NO: one target is the projection of another");
|
||||
return None;
|
||||
}
|
||||
|
||||
// if we reach this point, the optimization applies, and we should be able to optimize this case
|
||||
// store the info that is needed to apply the optimization
|
||||
|
||||
|
@ -228,6 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
guard: Option<&Guard<'tcx>>,
|
||||
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
|
||||
scrutinee_span: Span,
|
||||
arm_span: Option<Span>,
|
||||
arm_scope: Option<region::Scope>,
|
||||
) -> BasicBlock {
|
||||
if candidate.subcandidates.is_empty() {
|
||||
@ -239,6 +240,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
guard,
|
||||
fake_borrow_temps,
|
||||
scrutinee_span,
|
||||
arm_span,
|
||||
true,
|
||||
)
|
||||
} else {
|
||||
@ -274,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
guard,
|
||||
&fake_borrow_temps,
|
||||
scrutinee_span,
|
||||
arm_span,
|
||||
schedule_drops,
|
||||
);
|
||||
if arm_scope.is_none() {
|
||||
@ -436,6 +439,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&fake_borrow_temps,
|
||||
irrefutable_pat.span,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unit()
|
||||
}
|
||||
@ -817,11 +821,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// For an example of a case where we set `otherwise_block`, even for an
|
||||
/// exhaustive match consider:
|
||||
///
|
||||
/// ```rust
|
||||
/// match x {
|
||||
/// (true, true) => (),
|
||||
/// (_, false) => (),
|
||||
/// (false, true) => (),
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For this match, we check if `x.0` matches `true` (for the first
|
||||
/// arm). If that's false, we check `x.1`. If it's `true` we check if
|
||||
@ -935,11 +941,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Link up matched candidates. For example, if we have something like
|
||||
/// this:
|
||||
///
|
||||
/// ```rust
|
||||
/// ...
|
||||
/// Some(x) if cond => ...
|
||||
/// Some(x) => ...
|
||||
/// Some(x) if cond => ...
|
||||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// We generate real edges from:
|
||||
/// * `start_block` to the `prebinding_block` of the first pattern,
|
||||
@ -1517,7 +1525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Initializes each of the bindings from the candidate by
|
||||
/// moving/copying/ref'ing the source as appropriate. Tests the guard, if
|
||||
/// any, and then branches to the arm. Returns the block for the case where
|
||||
/// the guard fails.
|
||||
/// the guard succeeds.
|
||||
///
|
||||
/// Note: we do not check earlier that if there is a guard,
|
||||
/// there cannot be move bindings. We avoid a use-after-move by only
|
||||
@ -1529,6 +1537,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
guard: Option<&Guard<'tcx>>,
|
||||
fake_borrows: &Vec<(Place<'tcx>, Local)>,
|
||||
scrutinee_span: Span,
|
||||
arm_span: Option<Span>,
|
||||
schedule_drops: bool,
|
||||
) -> BasicBlock {
|
||||
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
||||
@ -1659,15 +1668,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
|
||||
}
|
||||
|
||||
// the block to branch to if the guard fails; if there is no
|
||||
// guard, this block is simply unreachable
|
||||
let guard = match guard {
|
||||
Guard::If(e) => self.hir.mirror(e.clone()),
|
||||
let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match guard {
|
||||
Guard::If(e) => {
|
||||
let e = self.hir.mirror(e.clone());
|
||||
let source_info = self.source_info(e.span);
|
||||
(e.span, self.test_bool(block, e, source_info))
|
||||
},
|
||||
Guard::IfLet(pat, scrutinee) => {
|
||||
let scrutinee_span = scrutinee.span();
|
||||
let scrutinee_place = unpack!(block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span));
|
||||
let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false);
|
||||
let wildcard = Pat::wildcard_from_ty(pat.ty);
|
||||
let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false);
|
||||
let fake_borrow_temps =
|
||||
self.lower_match_tree(block, pat.span, false, &mut [&mut guard_candidate, &mut otherwise_candidate]);
|
||||
self.declare_bindings(
|
||||
None,
|
||||
pat.span.to(arm_span.unwrap()),
|
||||
pat,
|
||||
ArmHasGuard(false),
|
||||
Some((Some(&scrutinee_place), scrutinee.span())),
|
||||
);
|
||||
let post_guard_block = self.bind_pattern(
|
||||
self.source_info(pat.span),
|
||||
guard_candidate,
|
||||
None,
|
||||
&fake_borrow_temps,
|
||||
scrutinee.span(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
|
||||
(scrutinee_span, (post_guard_block, otherwise_post_guard_block))
|
||||
}
|
||||
};
|
||||
let source_info = self.source_info(guard.span);
|
||||
let guard_end = self.source_info(tcx.sess.source_map().end_point(guard.span));
|
||||
let (post_guard_block, otherwise_post_guard_block) =
|
||||
self.test_bool(block, guard, source_info);
|
||||
let source_info = self.source_info(guard_span);
|
||||
let guard_end = self.source_info(tcx.sess.source_map().end_point(guard_span));
|
||||
let guard_frame = self.guard_context.pop().unwrap();
|
||||
debug!("Exiting guard building context with locals: {:?}", guard_frame);
|
||||
|
||||
|
@ -1197,6 +1197,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
arm.guard.as_ref(),
|
||||
&fake_borrow_temps,
|
||||
scrutinee_span,
|
||||
Some(arm.span),
|
||||
Some(arm.scope),
|
||||
);
|
||||
|
||||
|
@ -776,10 +776,10 @@ impl ToBorrowKind for hir::Mutability {
|
||||
fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> {
|
||||
Arm {
|
||||
pattern: cx.pattern_from_hir(&arm.pat),
|
||||
guard: match arm.guard {
|
||||
Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
|
||||
_ => None,
|
||||
},
|
||||
guard: arm.guard.as_ref().map(|g| match g {
|
||||
hir::Guard::If(ref e) => Guard::If(e.to_ref()),
|
||||
hir::Guard::IfLet(ref pat, ref e) => Guard::IfLet(cx.pattern_from_hir(pat), e.to_ref()),
|
||||
}),
|
||||
body: arm.body.to_ref(),
|
||||
lint_level: LintLevel::Explicit(arm.hir_id),
|
||||
scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
|
||||
|
@ -344,6 +344,7 @@ crate struct Arm<'tcx> {
|
||||
#[derive(Clone, Debug)]
|
||||
crate enum Guard<'tcx> {
|
||||
If(ExprRef<'tcx>),
|
||||
IfLet(Pat<'tcx>, ExprRef<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -164,10 +164,20 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||
for arm in arms {
|
||||
// Check the arm for some things unrelated to exhaustiveness.
|
||||
self.check_patterns(&arm.pat);
|
||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||
self.check_patterns(pat);
|
||||
}
|
||||
}
|
||||
|
||||
let mut cx = self.new_cx(scrut.hir_id);
|
||||
|
||||
for arm in arms {
|
||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
|
||||
check_if_let_guard(&mut cx, &tpat, pat.hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
let mut have_errors = false;
|
||||
|
||||
let arms: Vec<_> = arms
|
||||
@ -360,12 +370,28 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, source: hir::
|
||||
let msg = match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => "irrefutable if-let pattern",
|
||||
hir::MatchSource::WhileLetDesugar => "irrefutable while-let pattern",
|
||||
hir::MatchSource::IfLetGuardDesugar => "irrefutable if-let guard",
|
||||
_ => bug!(),
|
||||
};
|
||||
lint.build(msg).emit()
|
||||
});
|
||||
}
|
||||
|
||||
fn check_if_let_guard<'p, 'tcx>(
|
||||
cx: &mut MatchCheckCtxt<'p, 'tcx>,
|
||||
pat: &'p super::Pat<'tcx>,
|
||||
pat_id: HirId,
|
||||
) {
|
||||
let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
|
||||
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
|
||||
report_arm_reachability(&cx, &report, hir::MatchSource::IfLetGuardDesugar);
|
||||
|
||||
if report.non_exhaustiveness_witnesses.is_empty() {
|
||||
// The match is exhaustive, i.e. the if let pattern is irrefutable.
|
||||
irrefutable_let_pattern(cx.tcx, pat.span, pat_id, hir::MatchSource::IfLetGuardDesugar)
|
||||
}
|
||||
}
|
||||
|
||||
/// Report unreachable arms, if any.
|
||||
fn report_arm_reachability<'p, 'tcx>(
|
||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||
@ -390,6 +416,11 @@ fn report_arm_reachability<'p, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
hir::MatchSource::IfLetGuardDesugar => {
|
||||
assert_eq!(arm_index, 0);
|
||||
unreachable_pattern(cx.tcx, arm.pat.span, arm.hir_id, None);
|
||||
}
|
||||
|
||||
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
|
||||
unreachable_pattern(cx.tcx, arm.pat.span, arm.hir_id, catchall);
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ impl NonConstExpr {
|
||||
return None;
|
||||
}
|
||||
|
||||
Self::Match(IfLetGuardDesugar) => bug!("if-let guard outside a `match` expression"),
|
||||
|
||||
// All other expressions are allowed.
|
||||
Self::Loop(Loop | While | WhileLet)
|
||||
| Self::Match(
|
||||
|
@ -360,6 +360,9 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
||||
|
||||
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
|
||||
self.add_from_pat(&arm.pat);
|
||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||
self.add_from_pat(pat);
|
||||
}
|
||||
intravisit::walk_arm(self, arm);
|
||||
}
|
||||
|
||||
@ -866,10 +869,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
for arm in arms {
|
||||
let body_succ = self.propagate_through_expr(&arm.body, succ);
|
||||
|
||||
let guard_succ = self.propagate_through_opt_expr(
|
||||
arm.guard.as_ref().map(|hir::Guard::If(e)| *e),
|
||||
body_succ,
|
||||
);
|
||||
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
|
||||
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
|
||||
hir::Guard::IfLet(pat, e) => {
|
||||
let let_bind = self.define_bindings_in_pat(pat, body_succ);
|
||||
self.propagate_through_expr(e, let_bind)
|
||||
}
|
||||
});
|
||||
let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
|
||||
self.merge_from_succ(ln, arm_succ);
|
||||
}
|
||||
|
@ -182,28 +182,32 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
for (dep_v, stab_v) in
|
||||
dep_since.as_str().split('.').zip(stab_since.as_str().split('.'))
|
||||
{
|
||||
if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) {
|
||||
match dep_v.cmp(&stab_v) {
|
||||
Ordering::Less => {
|
||||
self.tcx.sess.span_err(
|
||||
item_sp,
|
||||
"An API can't be stabilized \
|
||||
after it is deprecated",
|
||||
);
|
||||
match stab_v.parse::<u64>() {
|
||||
Err(_) => {
|
||||
self.tcx.sess.span_err(item_sp, "Invalid stability version found");
|
||||
break;
|
||||
}
|
||||
Ok(stab_vp) => match dep_v.parse::<u64>() {
|
||||
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
|
||||
Ordering::Less => {
|
||||
self.tcx.sess.span_err(
|
||||
item_sp,
|
||||
"An API can't be stabilized after it is deprecated",
|
||||
);
|
||||
break;
|
||||
}
|
||||
Ordering::Equal => continue,
|
||||
Ordering::Greater => break,
|
||||
},
|
||||
Err(_) => {
|
||||
if dep_v != "TBD" {
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(item_sp, "Invalid deprecation version found");
|
||||
}
|
||||
break;
|
||||
}
|
||||
Ordering::Equal => continue,
|
||||
Ordering::Greater => break,
|
||||
}
|
||||
} else {
|
||||
// Act like it isn't less because the question is now nonsensical,
|
||||
// and this makes us not do anything else interesting.
|
||||
self.tcx.sess.span_err(
|
||||
item_sp,
|
||||
"Invalid stability or deprecation \
|
||||
version found",
|
||||
);
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1491,7 +1491,7 @@ fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType
|
||||
early_error(error_format, &format!("target file {:?} does not exist", path))
|
||||
})
|
||||
}
|
||||
Some(target) => TargetTriple::TargetTriple(target),
|
||||
Some(target) => TargetTriple::from_alias(target),
|
||||
_ => TargetTriple::from_triple(host_triple()),
|
||||
}
|
||||
}
|
||||
|
@ -1800,6 +1800,24 @@ impl TargetTriple {
|
||||
Ok(TargetTriple::TargetPath(canonicalized_path))
|
||||
}
|
||||
|
||||
/// Creates a target triple from its alias
|
||||
pub fn from_alias(triple: String) -> Self {
|
||||
macro_rules! target_aliases {
|
||||
( $(($alias:literal, $target:literal ),)+ ) => {
|
||||
match triple.as_str() {
|
||||
$( $alias => TargetTriple::from_triple($target), )+
|
||||
_ => TargetTriple::TargetTriple(triple),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target_aliases! {
|
||||
// `x86_64-pc-solaris` is an alias for `x86_64_sun_solaris` for backwards compatibility reasons.
|
||||
// (See <https://github.com/rust-lang/rust/issues/40531>.)
|
||||
("x86_64-pc-solaris", "x86_64-sun-solaris"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string triple for this target.
|
||||
///
|
||||
/// If this target is a path, the file name (without extension) is returned.
|
||||
|
@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// FIXME(60707): Consider removing hack with principled solution.
|
||||
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
|
||||
} else {
|
||||
self.demand_scrutinee_type(arms, scrut)
|
||||
self.demand_scrutinee_type(scrut, arms_contain_ref_bindings(arms), arms.is_empty())
|
||||
};
|
||||
|
||||
// If there are no arms, that is a diverging match; a special case.
|
||||
@ -98,7 +98,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
match g {
|
||||
hir::Guard::If(e) => {
|
||||
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {})
|
||||
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
|
||||
}
|
||||
hir::Guard::IfLet(pat, e) => {
|
||||
let scrutinee_ty = self.demand_scrutinee_type(
|
||||
e,
|
||||
pat.contains_explicit_ref_binding(),
|
||||
false,
|
||||
);
|
||||
self.check_pat_top(&pat, scrutinee_ty, None, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -450,8 +458,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
fn demand_scrutinee_type(
|
||||
&self,
|
||||
arms: &'tcx [hir::Arm<'tcx>],
|
||||
scrut: &'tcx hir::Expr<'tcx>,
|
||||
contains_ref_bindings: Option<hir::Mutability>,
|
||||
no_arms: bool,
|
||||
) -> Ty<'tcx> {
|
||||
// Not entirely obvious: if matches may create ref bindings, we want to
|
||||
// use the *precise* type of the scrutinee, *not* some supertype, as
|
||||
@ -505,17 +514,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// (once introduced) is populated by the time we get here.
|
||||
//
|
||||
// See #44848.
|
||||
let contains_ref_bindings = arms
|
||||
.iter()
|
||||
.filter_map(|a| a.pat.contains_explicit_ref_binding())
|
||||
.max_by_key(|m| match *m {
|
||||
hir::Mutability::Mut => 1,
|
||||
hir::Mutability::Not => 0,
|
||||
});
|
||||
|
||||
if let Some(m) = contains_ref_bindings {
|
||||
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
|
||||
} else if arms.is_empty() {
|
||||
} else if no_arms {
|
||||
self.check_expr(scrut)
|
||||
} else {
|
||||
// ...but otherwise we want to use any supertype of the
|
||||
@ -546,3 +547,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
|
||||
arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m {
|
||||
hir::Mutability::Mut => 1,
|
||||
hir::Mutability::Not => 0,
|
||||
})
|
||||
}
|
||||
|
@ -246,6 +246,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||
Guard::If(ref e) => {
|
||||
self.visit_expr(e);
|
||||
}
|
||||
Guard::IfLet(ref pat, ref e) => {
|
||||
self.visit_pat(pat);
|
||||
self.visit_expr(e);
|
||||
}
|
||||
}
|
||||
|
||||
let mut scope_var_ids =
|
||||
|
@ -92,6 +92,8 @@ $EndFeature, "
|
||||
"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
|
||||
#[doc(alias = "popcount")]
|
||||
#[doc(alias = "popcnt")]
|
||||
#[inline]
|
||||
pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ assert_eq!(n.count_ones(), 3);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
|
||||
#[doc(alias = "popcount")]
|
||||
#[doc(alias = "popcnt")]
|
||||
#[inline]
|
||||
pub const fn count_ones(self) -> u32 {
|
||||
intrinsics::ctpop(self as $ActualT) as u32
|
||||
|
@ -453,6 +453,8 @@ let n = Wrapping(0b01001100", stringify!($t), ");
|
||||
assert_eq!(n.count_ones(), 3);
|
||||
```"),
|
||||
#[inline]
|
||||
#[doc(alias = "popcount")]
|
||||
#[doc(alias = "popcnt")]
|
||||
#[unstable(feature = "wrapping_int_impl", issue = "32463")]
|
||||
pub const fn count_ones(self) -> u32 {
|
||||
self.0.count_ones()
|
||||
|
@ -1043,30 +1043,6 @@ impl Step for Src {
|
||||
builder.copy(&builder.src.join(file), &dst_src.join(file));
|
||||
}
|
||||
|
||||
// libtest includes std and everything else, so vendoring it
|
||||
// creates exactly what's needed for `cargo -Zbuild-std` or any
|
||||
// other analysis of the stdlib's source. Cargo also needs help
|
||||
// finding the lock, so we copy it to libtest temporarily.
|
||||
//
|
||||
// Note that this requires std to only have one version of each
|
||||
// crate. e.g. two versions of getopts won't be patchable.
|
||||
let dst_libtest = dst_src.join("library/test");
|
||||
let dst_vendor = dst_src.join("vendor");
|
||||
let root_lock = dst_src.join("Cargo.lock");
|
||||
let temp_lock = dst_libtest.join("Cargo.lock");
|
||||
|
||||
// `cargo vendor` will delete everything from the lockfile that
|
||||
// isn't used by libtest, so we need to not use any links!
|
||||
builder.really_copy(&root_lock, &temp_lock);
|
||||
|
||||
let mut cmd = Command::new(&builder.initial_cargo);
|
||||
cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest);
|
||||
builder.info("Dist src");
|
||||
let _time = timeit(builder);
|
||||
builder.run(&mut cmd);
|
||||
|
||||
builder.remove(&temp_lock);
|
||||
|
||||
// Create source tarball in rust-installer format
|
||||
let mut cmd = rust_installer(builder);
|
||||
cmd.arg("generate")
|
||||
@ -1083,6 +1059,8 @@ impl Step for Src {
|
||||
.arg("--component-name=rust-src")
|
||||
.arg("--legacy-manifest-dirs=rustlib,cargo");
|
||||
|
||||
builder.info("Dist src");
|
||||
let _time = timeit(builder);
|
||||
builder.run(&mut cmd);
|
||||
|
||||
builder.remove_dir(&image);
|
||||
|
@ -1182,27 +1182,6 @@ impl Build {
|
||||
paths
|
||||
}
|
||||
|
||||
/// Copies a file from `src` to `dst` and doesn't use links, so
|
||||
/// that the copy can be modified without affecting the original.
|
||||
pub fn really_copy(&self, src: &Path, dst: &Path) {
|
||||
if self.config.dry_run {
|
||||
return;
|
||||
}
|
||||
self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst));
|
||||
if src == dst {
|
||||
return;
|
||||
}
|
||||
let _ = fs::remove_file(&dst);
|
||||
let metadata = t!(src.symlink_metadata());
|
||||
if let Err(e) = fs::copy(src, dst) {
|
||||
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
|
||||
}
|
||||
t!(fs::set_permissions(dst, metadata.permissions()));
|
||||
let atime = FileTime::from_last_access_time(&metadata);
|
||||
let mtime = FileTime::from_last_modification_time(&metadata);
|
||||
t!(filetime::set_file_times(dst, atime, mtime));
|
||||
}
|
||||
|
||||
/// Copies a file from `src` to `dst`
|
||||
pub fn copy(&self, src: &Path, dst: &Path) {
|
||||
if self.config.dry_run {
|
||||
|
@ -2279,7 +2279,11 @@ fn short_item_info(item: &clean::Item, cx: &Context, parent: Option<&clean::Item
|
||||
let mut message = if let Some(since) = since {
|
||||
let since = &since.as_str();
|
||||
if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) {
|
||||
format!("Deprecating in {}", Escape(since))
|
||||
if *since == "TBD" {
|
||||
format!("Deprecating in a future Rust version")
|
||||
} else {
|
||||
format!("Deprecating in {}", Escape(since))
|
||||
}
|
||||
} else {
|
||||
format!("Deprecated since {}", Escape(since))
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ digraph Cov_0_4 {
|
||||
graph [fontname="Courier, monospace"];
|
||||
node [fontname="Courier, monospace"];
|
||||
edge [fontname="Courier, monospace"];
|
||||
bcb0__Cov_0_4 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 18:1-20:2<br/> 19:5-19:9: @0[0]: _0 = const true<br/> 20:2-20:2: @0.Return: return</td></tr><tr><td align="left" balign="left">bb0: Return</td></tr></table>>];
|
||||
bcb0__Cov_0_4 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 18:1-20:2<br/> 19:5-19:9: @0[0]: Coverage::Counter(1) for $DIR/coverage_graphviz.rs:18:1 - 20:2<br/> 20:2-20:2: @0.Return: return</td></tr><tr><td align="left" balign="left">bb0: Return</td></tr></table>>];
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ digraph Cov_0_3 {
|
||||
graph [fontname="Courier, monospace"];
|
||||
node [fontname="Courier, monospace"];
|
||||
edge [fontname="Courier, monospace"];
|
||||
bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/> 13:10-13:10: @4[0]: _1 = const ()</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
|
||||
bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/> 13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
|
||||
bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/> 12:13-12:18: @5[0]: _0 = const ()<br/>Expression(bcb1 + 0) at 15:2-15:2<br/> 15:2-15:2: @5.Return: return</td></tr><tr><td align="left" balign="left">bb3: FalseEdge</td></tr><tr><td align="left" balign="left">bb5: Return</td></tr></table>>];
|
||||
bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/> 11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb6]<br/> 11:12-11:17: @2[0]: FakeRead(ForMatchedPlace, _2)</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
|
||||
bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>];
|
||||
|
@ -5,8 +5,8 @@
|
||||
let mut _0: bool; // return place in scope 0 at /the/src/instrument_coverage.rs:19:13: 19:17
|
||||
|
||||
bb0: {
|
||||
_0 = const true; // scope 0 at /the/src/instrument_coverage.rs:20:5: 20:9
|
||||
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:19:1 - 21:2; // scope 0 at /the/src/instrument_coverage.rs:21:2: 21:2
|
||||
_0 = const true; // scope 0 at /the/src/instrument_coverage.rs:20:5: 20:9
|
||||
return; // scope 0 at /the/src/instrument_coverage.rs:21:2: 21:2
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10
|
||||
|
||||
bb0: {
|
||||
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
|
||||
falseUnwind -> [real: bb1, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
|
||||
}
|
||||
|
||||
@ -21,26 +22,25 @@
|
||||
|
||||
bb2: {
|
||||
FakeRead(ForMatchedPlace, _2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
|
||||
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
|
||||
switchInt(_2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
|
||||
}
|
||||
|
||||
bb3: {
|
||||
+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
|
||||
+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
|
||||
falseEdge -> [real: bb5, imaginary: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
|
||||
}
|
||||
|
||||
bb4: {
|
||||
+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
|
||||
_1 = const (); // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10
|
||||
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6
|
||||
+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
|
||||
goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
|
||||
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:15:5: 15:6
|
||||
+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
|
||||
+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
|
||||
return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 15,
|
||||
"covered": 12,
|
||||
"percent": 80
|
||||
"covered": 13,
|
||||
"percent": 86.66666666666667
|
||||
},
|
||||
"regions": {
|
||||
"count": 14,
|
||||
"covered": 12,
|
||||
"notcovered": 2,
|
||||
"percent": 85.71428571428571
|
||||
"covered": 13,
|
||||
"notcovered": 1,
|
||||
"percent": 92.85714285714286
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,14 +42,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 15,
|
||||
"covered": 12,
|
||||
"percent": 80
|
||||
"covered": 13,
|
||||
"percent": 86.66666666666667
|
||||
},
|
||||
"regions": {
|
||||
"count": 14,
|
||||
"covered": 12,
|
||||
"notcovered": 2,
|
||||
"percent": 85.71428571428571
|
||||
"covered": 13,
|
||||
"notcovered": 1,
|
||||
"percent": 92.85714285714286
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 23,
|
||||
"covered": 19,
|
||||
"percent": 82.6086956521739
|
||||
"covered": 21,
|
||||
"percent": 91.30434782608695
|
||||
},
|
||||
"regions": {
|
||||
"count": 13,
|
||||
"covered": 11,
|
||||
"notcovered": 2,
|
||||
"percent": 84.61538461538461
|
||||
"covered": 12,
|
||||
"notcovered": 1,
|
||||
"percent": 92.3076923076923
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,14 +42,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 23,
|
||||
"covered": 19,
|
||||
"percent": 82.6086956521739
|
||||
"covered": 21,
|
||||
"percent": 91.30434782608695
|
||||
},
|
||||
"regions": {
|
||||
"count": 13,
|
||||
"covered": 11,
|
||||
"notcovered": 2,
|
||||
"percent": 84.61538461538461
|
||||
"covered": 12,
|
||||
"notcovered": 1,
|
||||
"percent": 92.3076923076923
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 19,
|
||||
"covered": 16,
|
||||
"percent": 84.21052631578947
|
||||
"covered": 17,
|
||||
"percent": 89.47368421052632
|
||||
},
|
||||
"regions": {
|
||||
"count": 13,
|
||||
"covered": 11,
|
||||
"notcovered": 2,
|
||||
"percent": 84.61538461538461
|
||||
"covered": 12,
|
||||
"notcovered": 1,
|
||||
"percent": 92.3076923076923
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,14 +42,14 @@
|
||||
},
|
||||
"lines": {
|
||||
"count": 19,
|
||||
"covered": 16,
|
||||
"percent": 84.21052631578947
|
||||
"covered": 17,
|
||||
"percent": 89.47368421052632
|
||||
},
|
||||
"regions": {
|
||||
"count": 13,
|
||||
"covered": 11,
|
||||
"notcovered": 2,
|
||||
"percent": 84.61538461538461
|
||||
"covered": 12,
|
||||
"notcovered": 1,
|
||||
"percent": 92.3076923076923
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,13 @@
|
||||
8| |
|
||||
9| 1|fn main() -> Result<(),u8> {
|
||||
10| 1| let mut countdown = 10;
|
||||
11| 10| while countdown > 0 {
|
||||
12| 10| if countdown == 1 {
|
||||
13| 0| might_fail_assert(3);
|
||||
11| 11| while countdown > 0 {
|
||||
12| 11| if countdown == 1 {
|
||||
13| 1| might_fail_assert(3);
|
||||
14| 10| } else if countdown < 5 {
|
||||
15| 3| might_fail_assert(2);
|
||||
16| 6| }
|
||||
17| 9| countdown -= 1;
|
||||
17| 10| countdown -= 1;
|
||||
18| | }
|
||||
19| 0| Ok(())
|
||||
20| 0|}
|
||||
|
@ -14,15 +14,15 @@
|
||||
14| |
|
||||
15| 1|fn main() -> Result<(),u8> {
|
||||
16| 1| let mut countdown = 10;
|
||||
17| 10| while countdown > 0 {
|
||||
18| 10| if countdown == 1 {
|
||||
19| 0| let result = might_overflow(10);
|
||||
20| 0| println!("Result: {}", result);
|
||||
17| 11| while countdown > 0 {
|
||||
18| 11| if countdown == 1 {
|
||||
19| 1| let result = might_overflow(10);
|
||||
20| 1| println!("Result: {}", result);
|
||||
21| 10| } else if countdown < 5 {
|
||||
22| 3| let result = might_overflow(1);
|
||||
23| 3| println!("Result: {}", result);
|
||||
24| 6| }
|
||||
25| 9| countdown -= 1;
|
||||
25| 10| countdown -= 1;
|
||||
26| | }
|
||||
27| 0| Ok(())
|
||||
28| 0|}
|
||||
|
@ -12,13 +12,13 @@
|
||||
12| |
|
||||
13| 1|fn main() -> Result<(), u8> {
|
||||
14| 1| let mut countdown = 10;
|
||||
15| 10| while countdown > 0 {
|
||||
16| 10| if countdown == 1 {
|
||||
17| 0| might_panic(true);
|
||||
15| 11| while countdown > 0 {
|
||||
16| 11| if countdown == 1 {
|
||||
17| 1| might_panic(true);
|
||||
18| 10| } else if countdown < 5 {
|
||||
19| 3| might_panic(false);
|
||||
20| 6| }
|
||||
21| 9| countdown -= 1;
|
||||
21| 10| countdown -= 1;
|
||||
22| | }
|
||||
23| 0| Ok(())
|
||||
24| 0|}
|
||||
|
@ -20,13 +20,13 @@ Combined regions:
|
||||
6:37 -> 6:61 (count=1)
|
||||
7:1 -> 7:2 (count=3)
|
||||
9:1 -> 10:27 (count=1)
|
||||
11:11 -> 11:24 (count=10)
|
||||
12:12 -> 12:26 (count=10)
|
||||
12:27 -> 14:10 (count=0)
|
||||
11:11 -> 11:24 (count=11)
|
||||
12:12 -> 12:26 (count=11)
|
||||
12:27 -> 14:10 (count=1)
|
||||
14:19 -> 14:32 (count=10)
|
||||
14:33 -> 16:10 (count=3)
|
||||
16:10 -> 16:11 (count=6)
|
||||
17:9 -> 17:23 (count=9)
|
||||
17:9 -> 17:23 (count=10)
|
||||
19:5 -> 20:2 (count=0)
|
||||
Segment at 4:1 (count = 4), RegionEntry
|
||||
Segment at 4:41 (count = 0), Skipped
|
||||
@ -40,18 +40,18 @@ Segment at 7:1 (count = 3), RegionEntry
|
||||
Segment at 7:2 (count = 0), Skipped
|
||||
Segment at 9:1 (count = 1), RegionEntry
|
||||
Segment at 10:27 (count = 0), Skipped
|
||||
Segment at 11:11 (count = 10), RegionEntry
|
||||
Segment at 11:11 (count = 11), RegionEntry
|
||||
Segment at 11:24 (count = 0), Skipped
|
||||
Segment at 12:12 (count = 10), RegionEntry
|
||||
Segment at 12:12 (count = 11), RegionEntry
|
||||
Segment at 12:26 (count = 0), Skipped
|
||||
Segment at 12:27 (count = 0), RegionEntry
|
||||
Segment at 12:27 (count = 1), RegionEntry
|
||||
Segment at 14:10 (count = 0), Skipped
|
||||
Segment at 14:19 (count = 10), RegionEntry
|
||||
Segment at 14:32 (count = 0), Skipped
|
||||
Segment at 14:33 (count = 3), RegionEntry
|
||||
Segment at 16:10 (count = 6), RegionEntry
|
||||
Segment at 16:11 (count = 0), Skipped
|
||||
Segment at 17:9 (count = 9), RegionEntry
|
||||
Segment at 17:9 (count = 10), RegionEntry
|
||||
Segment at 17:23 (count = 0), Skipped
|
||||
Segment at 19:5 (count = 0), RegionEntry
|
||||
Segment at 20:2 (count = 0), Skipped
|
||||
|
@ -18,13 +18,13 @@ Combined regions:
|
||||
7:6 -> 7:7 (count=3)
|
||||
8:9 -> 13:2 (count=4)
|
||||
15:1 -> 16:27 (count=1)
|
||||
17:11 -> 17:24 (count=10)
|
||||
18:12 -> 18:26 (count=10)
|
||||
18:27 -> 21:10 (count=0)
|
||||
17:11 -> 17:24 (count=11)
|
||||
18:12 -> 18:26 (count=11)
|
||||
18:27 -> 21:10 (count=1)
|
||||
21:19 -> 21:32 (count=10)
|
||||
21:33 -> 24:10 (count=3)
|
||||
24:10 -> 24:11 (count=6)
|
||||
25:9 -> 25:23 (count=9)
|
||||
25:9 -> 25:23 (count=10)
|
||||
27:5 -> 28:2 (count=0)
|
||||
Segment at 4:1 (count = 4), RegionEntry
|
||||
Segment at 5:18 (count = 0), Skipped
|
||||
@ -35,18 +35,18 @@ Segment at 8:9 (count = 4), RegionEntry
|
||||
Segment at 13:2 (count = 0), Skipped
|
||||
Segment at 15:1 (count = 1), RegionEntry
|
||||
Segment at 16:27 (count = 0), Skipped
|
||||
Segment at 17:11 (count = 10), RegionEntry
|
||||
Segment at 17:11 (count = 11), RegionEntry
|
||||
Segment at 17:24 (count = 0), Skipped
|
||||
Segment at 18:12 (count = 10), RegionEntry
|
||||
Segment at 18:12 (count = 11), RegionEntry
|
||||
Segment at 18:26 (count = 0), Skipped
|
||||
Segment at 18:27 (count = 0), RegionEntry
|
||||
Segment at 18:27 (count = 1), RegionEntry
|
||||
Segment at 21:10 (count = 0), Skipped
|
||||
Segment at 21:19 (count = 10), RegionEntry
|
||||
Segment at 21:32 (count = 0), Skipped
|
||||
Segment at 21:33 (count = 3), RegionEntry
|
||||
Segment at 24:10 (count = 6), RegionEntry
|
||||
Segment at 24:11 (count = 0), Skipped
|
||||
Segment at 25:9 (count = 9), RegionEntry
|
||||
Segment at 25:9 (count = 10), RegionEntry
|
||||
Segment at 25:23 (count = 0), Skipped
|
||||
Segment at 27:5 (count = 0), RegionEntry
|
||||
Segment at 28:2 (count = 0), Skipped
|
||||
|
@ -18,13 +18,13 @@ Combined regions:
|
||||
6:9 -> 7:26 (count=1)
|
||||
8:12 -> 11:2 (count=3)
|
||||
13:1 -> 14:27 (count=1)
|
||||
15:11 -> 15:24 (count=10)
|
||||
16:12 -> 16:26 (count=10)
|
||||
16:27 -> 18:10 (count=0)
|
||||
15:11 -> 15:24 (count=11)
|
||||
16:12 -> 16:26 (count=11)
|
||||
16:27 -> 18:10 (count=1)
|
||||
18:19 -> 18:32 (count=10)
|
||||
18:33 -> 20:10 (count=3)
|
||||
20:10 -> 20:11 (count=6)
|
||||
21:9 -> 21:23 (count=9)
|
||||
21:9 -> 21:23 (count=10)
|
||||
23:5 -> 24:2 (count=0)
|
||||
Segment at 4:1 (count = 4), RegionEntry
|
||||
Segment at 4:36 (count = 0), Skipped
|
||||
@ -36,18 +36,18 @@ Segment at 8:12 (count = 3), RegionEntry
|
||||
Segment at 11:2 (count = 0), Skipped
|
||||
Segment at 13:1 (count = 1), RegionEntry
|
||||
Segment at 14:27 (count = 0), Skipped
|
||||
Segment at 15:11 (count = 10), RegionEntry
|
||||
Segment at 15:11 (count = 11), RegionEntry
|
||||
Segment at 15:24 (count = 0), Skipped
|
||||
Segment at 16:12 (count = 10), RegionEntry
|
||||
Segment at 16:12 (count = 11), RegionEntry
|
||||
Segment at 16:26 (count = 0), Skipped
|
||||
Segment at 16:27 (count = 0), RegionEntry
|
||||
Segment at 16:27 (count = 1), RegionEntry
|
||||
Segment at 18:10 (count = 0), Skipped
|
||||
Segment at 18:19 (count = 10), RegionEntry
|
||||
Segment at 18:32 (count = 0), Skipped
|
||||
Segment at 18:33 (count = 3), RegionEntry
|
||||
Segment at 20:10 (count = 6), RegionEntry
|
||||
Segment at 20:11 (count = 0), Skipped
|
||||
Segment at 21:9 (count = 9), RegionEntry
|
||||
Segment at 21:9 (count = 10), RegionEntry
|
||||
Segment at 21:23 (count = 0), Skipped
|
||||
Segment at 23:5 (count = 0), RegionEntry
|
||||
Segment at 24:2 (count = 0), Skipped
|
||||
|
@ -4,8 +4,16 @@
|
||||
|
||||
// @has rustc_deprecated_future/index.html '//*[@class="stab deprecated"]' \
|
||||
// 'Deprecation planned'
|
||||
// @has rustc_deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \
|
||||
// @has rustc_deprecated_future/struct.S1.html '//*[@class="stab deprecated"]' \
|
||||
// 'Deprecating in 99.99.99: effectively never'
|
||||
#[rustc_deprecated(since = "99.99.99", reason = "effectively never")]
|
||||
#[stable(feature = "rustc_deprecated-future-test", since = "1.0.0")]
|
||||
pub struct S;
|
||||
pub struct S1;
|
||||
|
||||
// @has rustc_deprecated_future/index.html '//*[@class="stab deprecated"]' \
|
||||
// 'Deprecation planned'
|
||||
// @has rustc_deprecated_future/struct.S2.html '//*[@class="stab deprecated"]' \
|
||||
// 'Deprecating in a future Rust version: literally never'
|
||||
#[rustc_deprecated(since = "TBD", reason = "literally never")]
|
||||
#[stable(feature = "rustc_deprecated-future-test", since = "1.0.0")]
|
||||
pub struct S2;
|
||||
|
@ -8,8 +8,13 @@
|
||||
|
||||
#[rustc_deprecated(since = "99.99.99", reason = "effectively never")]
|
||||
#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
|
||||
pub struct S;
|
||||
pub struct S1;
|
||||
|
||||
#[rustc_deprecated(since = "TBD", reason = "literally never")]
|
||||
#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
|
||||
pub struct S2;
|
||||
|
||||
fn main() {
|
||||
let _ = S; //~ ERROR use of unit struct `S` that will be deprecated in future version 99.99.99: effectively never
|
||||
let _ = S1; //~ ERROR use of unit struct `S1` that will be deprecated in future version 99.99.99: effectively never
|
||||
let _ = S2; //~ ERROR use of unit struct `S2` that will be deprecated in a future Rust version: literally never
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: use of unit struct `S` that will be deprecated in future version 99.99.99: effectively never
|
||||
--> $DIR/rustc_deprecation-in-future.rs:14:13
|
||||
error: use of unit struct `S1` that will be deprecated in future version 99.99.99: effectively never
|
||||
--> $DIR/rustc_deprecation-in-future.rs:18:13
|
||||
|
|
||||
LL | let _ = S;
|
||||
| ^
|
||||
LL | let _ = S1;
|
||||
| ^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/rustc_deprecation-in-future.rs:3:9
|
||||
@ -10,5 +10,11 @@ note: the lint level is defined here
|
||||
LL | #![deny(deprecated_in_future)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: use of unit struct `S2` that will be deprecated in a future Rust version: literally never
|
||||
--> $DIR/rustc_deprecation-in-future.rs:19:13
|
||||
|
|
||||
LL | let _ = S2;
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
// Thus, `&'_ u8` should be included in type signature
|
||||
// of the underlying generator.
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
async fn f() -> u8 { 1 }
|
||||
async fn foo() -> [bool; 10] { [false; 10] }
|
||||
|
||||
@ -36,8 +39,16 @@ async fn i(x: u8) {
|
||||
}
|
||||
}
|
||||
|
||||
async fn j(x: u8) {
|
||||
match x {
|
||||
y if let (1, 42) = (f().await, y) => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = g(10);
|
||||
let _ = h(9);
|
||||
let _ = i(8);
|
||||
let _ = j(7);
|
||||
}
|
||||
|
16
src/test/ui/mir/issue-78496.rs
Normal file
16
src/test/ui/mir/issue-78496.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// run-pass
|
||||
// compile-flags: -Z mir-opt-level=2 -C opt-level=0
|
||||
|
||||
// example from #78496
|
||||
pub enum E<'a> {
|
||||
Empty,
|
||||
Some(&'a E<'a>),
|
||||
}
|
||||
|
||||
fn f(e: &E) -> u32 {
|
||||
if let E::Some(E::Some(_)) = e { 1 } else { 2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(f(&E::Empty), 2);
|
||||
}
|
13
src/test/ui/no-std-macros.rs
Normal file
13
src/test/ui/no-std-macros.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// compile-flags: --crate-type=lib
|
||||
// check-pass
|
||||
// issue #55482
|
||||
#![no_std]
|
||||
|
||||
macro_rules! foo {
|
||||
($e:expr) => {
|
||||
$crate::core::assert!($e);
|
||||
$crate::core::assert_eq!($e, true);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn foo() { foo!(true); }
|
10
src/test/ui/rfc-2294-if-let-guard/bindings.rs
Normal file
10
src/test/ui/rfc-2294-if-let-guard/bindings.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
match Some(None) {
|
||||
Some(x) if let Some(y) = x => (x, y),
|
||||
_ => y, //~ ERROR cannot find value `y`
|
||||
}
|
||||
y //~ ERROR cannot find value `y`
|
||||
}
|
15
src/test/ui/rfc-2294-if-let-guard/bindings.stderr
Normal file
15
src/test/ui/rfc-2294-if-let-guard/bindings.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0425]: cannot find value `y` in this scope
|
||||
--> $DIR/bindings.rs:7:14
|
||||
|
|
||||
LL | _ => y,
|
||||
| ^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `y` in this scope
|
||||
--> $DIR/bindings.rs:9:5
|
||||
|
|
||||
LL | y
|
||||
| ^ not found in this scope
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
@ -6,7 +6,6 @@ fn _if_let_guard() {
|
||||
match () {
|
||||
() if let 0 = 1 => {}
|
||||
//~^ ERROR `if let` guard is not implemented
|
||||
//~| ERROR `let` expressions are not supported here
|
||||
|
||||
() if (let 0 = 1) => {}
|
||||
//~^ ERROR `let` expressions in this position are experimental
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: no rules expected the token `let`
|
||||
--> $DIR/feature-gate.rs:81:15
|
||||
--> $DIR/feature-gate.rs:80:15
|
||||
|
|
||||
LL | macro_rules! use_expr {
|
||||
| --------------------- when calling this macro
|
||||
@ -17,7 +17,7 @@ LL | () if let 0 = 1 => {}
|
||||
= help: add `#![feature(if_let_guard)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `if let` guard is not implemented
|
||||
--> $DIR/feature-gate.rs:77:12
|
||||
--> $DIR/feature-gate.rs:76:12
|
||||
|
|
||||
LL | () if let 0 = 1 => {}
|
||||
| ^^^^^^^^^^^^
|
||||
@ -26,7 +26,7 @@ LL | () if let 0 = 1 => {}
|
||||
= help: add `#![feature(if_let_guard)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:11:16
|
||||
--> $DIR/feature-gate.rs:10:16
|
||||
|
|
||||
LL | () if (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -35,7 +35,7 @@ LL | () if (let 0 = 1) => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:15:18
|
||||
--> $DIR/feature-gate.rs:14:18
|
||||
|
|
||||
LL | () if (((let 0 = 1))) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -44,7 +44,7 @@ LL | () if (((let 0 = 1))) => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:19:23
|
||||
--> $DIR/feature-gate.rs:18:23
|
||||
|
|
||||
LL | () if true && let 0 = 1 => {}
|
||||
| ^^^^^^^^^
|
||||
@ -53,7 +53,7 @@ LL | () if true && let 0 = 1 => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:23:15
|
||||
--> $DIR/feature-gate.rs:22:15
|
||||
|
|
||||
LL | () if let 0 = 1 && true => {}
|
||||
| ^^^^^^^^^
|
||||
@ -62,7 +62,7 @@ LL | () if let 0 = 1 && true => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:27:16
|
||||
--> $DIR/feature-gate.rs:26:16
|
||||
|
|
||||
LL | () if (let 0 = 1) && true => {}
|
||||
| ^^^^^^^^^
|
||||
@ -71,7 +71,7 @@ LL | () if (let 0 = 1) && true => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:31:24
|
||||
--> $DIR/feature-gate.rs:30:24
|
||||
|
|
||||
LL | () if true && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -80,7 +80,7 @@ LL | () if true && (let 0 = 1) => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:35:16
|
||||
--> $DIR/feature-gate.rs:34:16
|
||||
|
|
||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -89,7 +89,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:35:31
|
||||
--> $DIR/feature-gate.rs:34:31
|
||||
|
|
||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -98,7 +98,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:41:15
|
||||
--> $DIR/feature-gate.rs:40:15
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -107,7 +107,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:41:28
|
||||
--> $DIR/feature-gate.rs:40:28
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -116,7 +116,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:41:42
|
||||
--> $DIR/feature-gate.rs:40:42
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -125,7 +125,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:41:55
|
||||
--> $DIR/feature-gate.rs:40:55
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -134,7 +134,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:41:68
|
||||
--> $DIR/feature-gate.rs:40:68
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -143,7 +143,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:53:15
|
||||
--> $DIR/feature-gate.rs:52:15
|
||||
|
|
||||
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -152,7 +152,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:69:16
|
||||
--> $DIR/feature-gate.rs:68:16
|
||||
|
|
||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
||||
| ^^^^^^^^^
|
||||
@ -161,7 +161,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `let` expressions in this position are experimental
|
||||
--> $DIR/feature-gate.rs:72:16
|
||||
--> $DIR/feature-gate.rs:71:16
|
||||
|
|
||||
LL | use_expr!((let 0 = 1));
|
||||
| ^^^^^^^^^
|
||||
@ -170,16 +170,7 @@ LL | use_expr!((let 0 = 1));
|
||||
= help: add `#![feature(let_chains)]` to the crate attributes to enable
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:7:15
|
||||
|
|
||||
LL | () if let 0 = 1 => {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: only supported directly in conditions of `if`- and `while`-expressions
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:11:16
|
||||
--> $DIR/feature-gate.rs:10:16
|
||||
|
|
||||
LL | () if (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -188,7 +179,7 @@ LL | () if (let 0 = 1) => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:15:18
|
||||
--> $DIR/feature-gate.rs:14:18
|
||||
|
|
||||
LL | () if (((let 0 = 1))) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -197,7 +188,7 @@ LL | () if (((let 0 = 1))) => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:19:23
|
||||
--> $DIR/feature-gate.rs:18:23
|
||||
|
|
||||
LL | () if true && let 0 = 1 => {}
|
||||
| ^^^^^^^^^
|
||||
@ -206,7 +197,7 @@ LL | () if true && let 0 = 1 => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:23:15
|
||||
--> $DIR/feature-gate.rs:22:15
|
||||
|
|
||||
LL | () if let 0 = 1 && true => {}
|
||||
| ^^^^^^^^^
|
||||
@ -215,7 +206,7 @@ LL | () if let 0 = 1 && true => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:27:16
|
||||
--> $DIR/feature-gate.rs:26:16
|
||||
|
|
||||
LL | () if (let 0 = 1) && true => {}
|
||||
| ^^^^^^^^^
|
||||
@ -224,7 +215,7 @@ LL | () if (let 0 = 1) && true => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:31:24
|
||||
--> $DIR/feature-gate.rs:30:24
|
||||
|
|
||||
LL | () if true && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -233,7 +224,7 @@ LL | () if true && (let 0 = 1) => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:35:16
|
||||
--> $DIR/feature-gate.rs:34:16
|
||||
|
|
||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -242,7 +233,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:35:31
|
||||
--> $DIR/feature-gate.rs:34:31
|
||||
|
|
||||
LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -251,7 +242,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:41:15
|
||||
--> $DIR/feature-gate.rs:40:15
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -260,7 +251,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:41:28
|
||||
--> $DIR/feature-gate.rs:40:28
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -269,7 +260,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:41:42
|
||||
--> $DIR/feature-gate.rs:40:42
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -278,7 +269,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:41:55
|
||||
--> $DIR/feature-gate.rs:40:55
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -287,7 +278,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:41:68
|
||||
--> $DIR/feature-gate.rs:40:68
|
||||
|
|
||||
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
|
||||
| ^^^^^^^^^
|
||||
@ -296,7 +287,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:53:15
|
||||
--> $DIR/feature-gate.rs:52:15
|
||||
|
|
||||
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -305,7 +296,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:69:16
|
||||
--> $DIR/feature-gate.rs:68:16
|
||||
|
|
||||
LL | use_expr!((let 0 = 1 && 0 == 0));
|
||||
| ^^^^^^^^^
|
||||
@ -314,7 +305,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: `let` expressions are not supported here
|
||||
--> $DIR/feature-gate.rs:72:16
|
||||
--> $DIR/feature-gate.rs:71:16
|
||||
|
|
||||
LL | use_expr!((let 0 = 1));
|
||||
| ^^^^^^^^^
|
||||
@ -322,6 +313,6 @@ LL | use_expr!((let 0 = 1));
|
||||
= note: only supported directly in conditions of `if`- and `while`-expressions
|
||||
= note: as well as when nested within `&&` and parenthesis in those conditions
|
||||
|
||||
error: aborting due to 36 previous errors
|
||||
error: aborting due to 35 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
34
src/test/ui/rfc-2294-if-let-guard/run-pass.rs
Normal file
34
src/test/ui/rfc-2294-if-let-guard/run-pass.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
Qux(u8),
|
||||
}
|
||||
|
||||
fn bar(x: bool) -> Foo {
|
||||
if x { Foo::Baz } else { Foo::Bar }
|
||||
}
|
||||
|
||||
fn baz(x: u8) -> Foo {
|
||||
if x % 2 == 0 { Foo::Bar } else { Foo::Baz }
|
||||
}
|
||||
|
||||
fn qux(x: u8) -> Foo {
|
||||
Foo::Qux(x.rotate_left(1))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match Some((true, 3)) {
|
||||
Some((x, _)) if let Foo::Bar = bar(x) => panic!(),
|
||||
Some((_, x)) if let Foo::Baz = baz(x) => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
match Some(42) {
|
||||
Some(x) if let Foo::Qux(y) = qux(x) => assert_eq!(y, 84),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
16
src/test/ui/rfc-2294-if-let-guard/typeck.rs
Normal file
16
src/test/ui/rfc-2294-if-let-guard/typeck.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn ok() -> Result<Option<bool>, ()> {
|
||||
Ok(Some(true))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match ok() {
|
||||
Ok(x) if let Err(_) = x => {},
|
||||
//~^ ERROR mismatched types
|
||||
Ok(x) if let 0 = x => {},
|
||||
//~^ ERROR mismatched types
|
||||
_ => {}
|
||||
}
|
||||
}
|
21
src/test/ui/rfc-2294-if-let-guard/typeck.stderr
Normal file
21
src/test/ui/rfc-2294-if-let-guard/typeck.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/typeck.rs:10:22
|
||||
|
|
||||
LL | Ok(x) if let Err(_) = x => {},
|
||||
| ^^^^^^ expected enum `Option`, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected enum `Option<bool>`
|
||||
found enum `std::result::Result<_, _>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/typeck.rs:12:22
|
||||
|
|
||||
LL | Ok(x) if let 0 = x => {},
|
||||
| ^ expected enum `Option`, found integer
|
||||
|
|
||||
= note: expected enum `Option<bool>`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
22
src/test/ui/rfc-2294-if-let-guard/warns.rs
Normal file
22
src/test/ui/rfc-2294-if-let-guard/warns.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#![feature(if_let_guard)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#[deny(irrefutable_let_patterns)]
|
||||
fn irrefutable_let_guard() {
|
||||
match Some(()) {
|
||||
Some(x) if let () = x => {}
|
||||
//~^ ERROR irrefutable if-let guard
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[deny(unreachable_patterns)]
|
||||
fn unreachable_pattern() {
|
||||
match Some(()) {
|
||||
x if let None | None = x => {}
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
26
src/test/ui/rfc-2294-if-let-guard/warns.stderr
Normal file
26
src/test/ui/rfc-2294-if-let-guard/warns.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: irrefutable if-let guard
|
||||
--> $DIR/warns.rs:7:24
|
||||
|
|
||||
LL | Some(x) if let () = x => {}
|
||||
| ^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/warns.rs:4:8
|
||||
|
|
||||
LL | #[deny(irrefutable_let_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/warns.rs:16:25
|
||||
|
|
||||
LL | x if let None | None = x => {}
|
||||
| ^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/warns.rs:13:8
|
||||
|
|
||||
LL | #[deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -63,7 +63,11 @@ fn multiple3() { }
|
||||
#[rustc_const_unstable(feature = "c", issue = "none")]
|
||||
#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
|
||||
pub const fn multiple4() { }
|
||||
//~^ ERROR Invalid stability or deprecation version found
|
||||
//~^ ERROR Invalid stability version found
|
||||
|
||||
#[stable(feature = "a", since = "1.0.0")]
|
||||
#[rustc_deprecated(since = "invalid", reason = "text")]
|
||||
fn invalid_deprecation_version() {} //~ ERROR Invalid deprecation version found
|
||||
|
||||
#[rustc_deprecated(since = "a", reason = "text")]
|
||||
fn deprecated_without_unstable_or_stable() { }
|
||||
|
@ -96,19 +96,25 @@ error[E0544]: multiple stability levels
|
||||
LL | #[rustc_const_unstable(feature = "d", issue = "none")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Invalid stability or deprecation version found
|
||||
error: Invalid stability version found
|
||||
--> $DIR/stability-attribute-sanity.rs:65:1
|
||||
|
|
||||
LL | pub const fn multiple4() { }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Invalid deprecation version found
|
||||
--> $DIR/stability-attribute-sanity.rs:70:1
|
||||
|
|
||||
LL | fn invalid_deprecation_version() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0549]: rustc_deprecated attribute must be paired with either stable or unstable attribute
|
||||
--> $DIR/stability-attribute-sanity.rs:68:1
|
||||
--> $DIR/stability-attribute-sanity.rs:72:1
|
||||
|
|
||||
LL | #[rustc_deprecated(since = "a", reason = "text")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0539, E0541, E0546, E0550.
|
||||
For more information about an error, try `rustc --explain E0539`.
|
||||
|
@ -342,6 +342,10 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
|
||||
if let Some(ref guard) = arm.guard {
|
||||
match guard {
|
||||
Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
|
||||
Guard::IfLet(guard_pat, guard_expr) => {
|
||||
check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings);
|
||||
check_expr(cx, guard_expr, bindings);
|
||||
},
|
||||
}
|
||||
}
|
||||
check_expr(cx, &arm.body, bindings);
|
||||
|
@ -372,6 +372,18 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
self.current = if_expr_pat;
|
||||
self.visit_expr(if_expr);
|
||||
},
|
||||
hir::Guard::IfLet(ref if_let_pat, ref if_let_expr) => {
|
||||
let if_let_pat_pat = self.next("pat");
|
||||
let if_let_expr_pat = self.next("expr");
|
||||
println!(
|
||||
" if let Guard::IfLet(ref {}, ref {}) = {};",
|
||||
if_let_pat_pat, if_let_expr_pat, guard_pat
|
||||
);
|
||||
self.current = if_let_expr_pat;
|
||||
self.visit_expr(if_let_expr);
|
||||
self.current = if_let_pat_pat;
|
||||
self.visit_pat(if_let_pat);
|
||||
},
|
||||
}
|
||||
}
|
||||
self.current = format!("{}[{}].pat", arms_pat, i);
|
||||
@ -730,6 +742,7 @@ fn desugaring_name(des: hir::MatchSource) -> String {
|
||||
"MatchSource::IfLetDesugar {{ contains_else_clause: {} }}",
|
||||
contains_else_clause
|
||||
),
|
||||
hir::MatchSource::IfLetGuardDesugar => "MatchSource::IfLetGuardDesugar".to_string(),
|
||||
hir::MatchSource::IfDesugar { contains_else_clause } => format!(
|
||||
"MatchSource::IfDesugar {{ contains_else_clause: {} }}",
|
||||
contains_else_clause
|
||||
|
@ -169,6 +169,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
|
||||
fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
|
||||
match (left, right) {
|
||||
(Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
|
||||
(Guard::IfLet(lp, le), Guard::IfLet(rp, re)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -669,7 +671,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||
|
||||
pub fn hash_guard(&mut self, g: &Guard<'_>) {
|
||||
match g {
|
||||
Guard::If(ref expr) => {
|
||||
Guard::If(ref expr) | Guard::IfLet(_, ref expr) => {
|
||||
self.hash_expr(expr);
|
||||
},
|
||||
}
|
||||
|
@ -560,5 +560,10 @@ fn print_guard(cx: &LateContext<'_>, guard: &hir::Guard<'_>, indent: usize) {
|
||||
println!("{}If", ind);
|
||||
print_expr(cx, expr, indent + 1);
|
||||
},
|
||||
hir::Guard::IfLet(pat, expr) => {
|
||||
println!("{}IfLet", ind);
|
||||
print_pat(cx, pat, indent + 1);
|
||||
print_expr(cx, expr, indent + 1);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,8 @@ impl App {
|
||||
let content = std::fs::read_to_string(source)
|
||||
.with_context(|| format!("failed to read {}", self.path(source)))?;
|
||||
|
||||
let mut buf = HEADER_MESSAGE.replace("{source}", &self.path(source).to_string());
|
||||
let mut buf =
|
||||
HEADER_MESSAGE.replace("{source}", &self.path(source).to_string().replace("\\", "/"));
|
||||
|
||||
let documents = YamlLoader::load_from_str(&content)
|
||||
.with_context(|| format!("failed to parse {}", self.path(source)))?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user