parent
4ce3749235
commit
fe94f78b9b
@ -116,22 +116,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// it is usually better to focus on `the_value` rather
|
||||
// than the entirety of block(s) surrounding it.
|
||||
let adjusted_span = (|| {
|
||||
if let ExprKind::Block { body } = &expr.kind {
|
||||
if let Some(tail_expr) = body.expr {
|
||||
let mut expr = &this.thir[tail_expr];
|
||||
while let ExprKind::Block {
|
||||
body: Block { expr: Some(nested_expr), .. },
|
||||
}
|
||||
| ExprKind::Scope { value: nested_expr, .. } = expr.kind
|
||||
{
|
||||
expr = &this.thir[nested_expr];
|
||||
}
|
||||
this.block_context.push(BlockFrame::TailExpr {
|
||||
tail_result_is_ignored: true,
|
||||
span: expr.span,
|
||||
});
|
||||
return Some(expr.span);
|
||||
if let ExprKind::Block { body } = &expr.kind && let Some(tail_ex) = body.expr {
|
||||
let mut expr = &this.thir[tail_ex];
|
||||
while let ExprKind::Block {
|
||||
body: Block { expr: Some(nested_expr), .. },
|
||||
}
|
||||
| ExprKind::Scope { value: nested_expr, .. } = expr.kind
|
||||
{
|
||||
expr = &this.thir[nested_expr];
|
||||
}
|
||||
this.block_context.push(BlockFrame::TailExpr {
|
||||
tail_result_is_ignored: true,
|
||||
span: expr.span,
|
||||
});
|
||||
return Some(expr.span);
|
||||
}
|
||||
None
|
||||
})();
|
||||
|
@ -1597,13 +1597,11 @@ fn test_candidates<'pat, 'b, 'c>(
|
||||
}
|
||||
|
||||
// Insert a Shallow borrow of any places that is switched on.
|
||||
if let Some(fb) = fake_borrows {
|
||||
if let Ok(match_place_resolved) =
|
||||
match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||
{
|
||||
let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results);
|
||||
fb.insert(resolved_place);
|
||||
}
|
||||
if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
|
||||
match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||
{
|
||||
let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results);
|
||||
fb.insert(resolved_place);
|
||||
}
|
||||
|
||||
// perform the test, branching to one of N blocks. For each of
|
||||
|
@ -877,14 +877,12 @@ fn args_and_body(
|
||||
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||
|
||||
// If this is a simple binding pattern, give debuginfo a nice name.
|
||||
if let Some(arg) = arg_opt {
|
||||
if let Some(ident) = arg.pat.simple_ident() {
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
name: ident.name,
|
||||
source_info,
|
||||
value: VarDebugInfoContents::Place(arg_local.into()),
|
||||
});
|
||||
}
|
||||
if let Some(arg) = arg_opt && let Some(ident) = arg.pat.simple_ident() {
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
name: ident.name,
|
||||
source_info,
|
||||
value: VarDebugInfoContents::Place(arg_local.into()),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,23 +416,21 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
||||
}
|
||||
ExprKind::Field { lhs, .. } => {
|
||||
let lhs = &self.thir[lhs];
|
||||
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
|
||||
if adt_def.is_union() {
|
||||
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
|
||||
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
|
||||
if !(assigned_ty
|
||||
.ty_adt_def()
|
||||
.map_or(false, |adt| adt.is_manually_drop())
|
||||
|| assigned_ty
|
||||
.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env))
|
||||
{
|
||||
self.requires_unsafe(assignment_span, AssignToDroppingUnionField);
|
||||
} else {
|
||||
// write to non-drop union field, safe
|
||||
}
|
||||
if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
|
||||
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
|
||||
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
|
||||
if !(assigned_ty
|
||||
.ty_adt_def()
|
||||
.map_or(false, |adt| adt.is_manually_drop())
|
||||
|| assigned_ty
|
||||
.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env))
|
||||
{
|
||||
self.requires_unsafe(assignment_span, AssignToDroppingUnionField);
|
||||
} else {
|
||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||
// write to non-drop union field, safe
|
||||
}
|
||||
} else {
|
||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,10 +474,8 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
||||
}
|
||||
ExprKind::Let { expr: expr_id, .. } => {
|
||||
let let_expr = &self.thir[expr_id];
|
||||
if let ty::Adt(adt_def, _) = let_expr.ty.kind() {
|
||||
if adt_def.is_union() {
|
||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||
}
|
||||
if let ty::Adt(adt_def, _) = let_expr.ty.kind() && adt_def.is_union() {
|
||||
self.requires_unsafe(expr.span, AccessToUnionField);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1,15 +1,16 @@
|
||||
//! Construction of MIR from HIR.
|
||||
//!
|
||||
//! This crate also contains the match exhaustiveness and usefulness checking.
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(once_cell)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
@ -315,47 +315,43 @@ fn check_for_bindings_named_same_as_variants(
|
||||
rf: RefutableFlag,
|
||||
) {
|
||||
pat.walk_always(|p| {
|
||||
if let hir::PatKind::Binding(_, _, ident, None) = p.kind {
|
||||
if let Some(ty::BindByValue(hir::Mutability::Not)) =
|
||||
if let hir::PatKind::Binding(_, _, ident, None) = p.kind
|
||||
&& let Some(ty::BindByValue(hir::Mutability::Not)) =
|
||||
cx.typeck_results.extract_binding_mode(cx.tcx.sess, p.hir_id, p.span)
|
||||
{
|
||||
let pat_ty = cx.typeck_results.pat_ty(p).peel_refs();
|
||||
if let ty::Adt(edef, _) = pat_ty.kind() {
|
||||
if edef.is_enum()
|
||||
&& edef.variants.iter().any(|variant| {
|
||||
variant.ident(cx.tcx) == ident && variant.ctor_kind == CtorKind::Const
|
||||
})
|
||||
{
|
||||
let variant_count = edef.variants.len();
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
BINDINGS_WITH_VARIANT_NAME,
|
||||
p.hir_id,
|
||||
&& let pat_ty = cx.typeck_results.pat_ty(p).peel_refs()
|
||||
&& let ty::Adt(edef, _) = pat_ty.kind()
|
||||
&& edef.is_enum()
|
||||
&& edef.variants.iter().any(|variant| {
|
||||
variant.ident(cx.tcx) == ident && variant.ctor_kind == CtorKind::Const
|
||||
})
|
||||
{
|
||||
let variant_count = edef.variants.len();
|
||||
cx.tcx.struct_span_lint_hir(
|
||||
BINDINGS_WITH_VARIANT_NAME,
|
||||
p.hir_id,
|
||||
p.span,
|
||||
|lint| {
|
||||
let ty_path = cx.tcx.def_path_str(edef.did);
|
||||
let mut err = lint.build(&format!(
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
ident, ty_path
|
||||
));
|
||||
err.code(error_code!(E0170));
|
||||
// If this is an irrefutable pattern, and there's > 1 variant,
|
||||
// then we can't actually match on this. Applying the below
|
||||
// suggestion would produce code that breaks on `check_irrefutable`.
|
||||
if rf == Refutable || variant_count == 1 {
|
||||
err.span_suggestion(
|
||||
p.span,
|
||||
|lint| {
|
||||
let ty_path = cx.tcx.def_path_str(edef.did);
|
||||
let mut err = lint.build(&format!(
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
ident, ty_path
|
||||
));
|
||||
err.code(error_code!(E0170));
|
||||
// If this is an irrefutable pattern, and there's > 1 variant,
|
||||
// then we can't actually match on this. Applying the below
|
||||
// suggestion would produce code that breaks on `check_irrefutable`.
|
||||
if rf == Refutable || variant_count == 1 {
|
||||
err.span_suggestion(
|
||||
p.span,
|
||||
"to match on the variant, qualify the path",
|
||||
format!("{}::{}", ty_path, ident),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
},
|
||||
)
|
||||
"to match on the variant, qualify the path",
|
||||
format!("{}::{}", ty_path, ident),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
},
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -622,10 +618,8 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
|
||||
let mut covered = vec![];
|
||||
for pattern in patterns {
|
||||
if let Variant(variant_index) = pattern.ctor() {
|
||||
if let ty::Adt(this_def, _) = pattern.ty().kind() {
|
||||
if this_def.did != def.did {
|
||||
continue;
|
||||
}
|
||||
if let ty::Adt(this_def, _) = pattern.ty().kind() && this_def.did != def.did {
|
||||
continue;
|
||||
}
|
||||
let sp = def.variants[*variant_index].ident(cx.tcx).span;
|
||||
if covered.contains(&sp) {
|
||||
|
@ -680,15 +680,13 @@ fn as_slice(&self) -> Option<Slice> {
|
||||
///
|
||||
/// This means that the variant has a stdlib unstable feature marking it.
|
||||
pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
|
||||
if let Constructor::Variant(idx) = self {
|
||||
if let ty::Adt(adt, _) = pcx.ty.kind() {
|
||||
let variant_def_id = adt.variants[*idx].def_id;
|
||||
// Filter variants that depend on a disabled unstable feature.
|
||||
return matches!(
|
||||
pcx.cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None),
|
||||
EvalResult::Deny { .. }
|
||||
);
|
||||
}
|
||||
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
|
||||
let variant_def_id = adt.variants[*idx].def_id;
|
||||
// Filter variants that depend on a disabled unstable feature.
|
||||
return matches!(
|
||||
pcx.cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None),
|
||||
EvalResult::Deny { .. }
|
||||
);
|
||||
}
|
||||
false
|
||||
}
|
||||
@ -696,11 +694,9 @@ pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
|
||||
/// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]`
|
||||
/// attribute.
|
||||
pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
|
||||
if let Constructor::Variant(idx) = self {
|
||||
if let ty::Adt(adt, _) = pcx.ty.kind() {
|
||||
let variant_def_id = adt.variants[*idx].def_id;
|
||||
return pcx.cx.tcx.is_doc_hidden(variant_def_id);
|
||||
}
|
||||
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
|
||||
let variant_def_id = adt.variants[*idx].def_id;
|
||||
return pcx.cx.tcx.is_doc_hidden(variant_def_id);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -790,16 +790,14 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
};
|
||||
}
|
||||
|
||||
if let ty::Str = ty.kind() {
|
||||
if let (
|
||||
ty::ConstKind::Value(a_val @ ConstValue::Slice { .. }),
|
||||
ty::ConstKind::Value(b_val @ ConstValue::Slice { .. }),
|
||||
) = (a.val(), b.val())
|
||||
{
|
||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||
return from_bool(a_bytes == b_bytes);
|
||||
}
|
||||
if let ty::Str = ty.kind() && let (
|
||||
ty::ConstKind::Value(a_val @ ConstValue::Slice { .. }),
|
||||
ty::ConstKind::Value(b_val @ ConstValue::Slice { .. }),
|
||||
) = (a.val(), b.val())
|
||||
{
|
||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||
return from_bool(a_bytes == b_bytes);
|
||||
}
|
||||
fallback()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user