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