Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 15 additions & 33 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2312,12 +2312,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
tcx: TyCtxt<'hir>,
issue_span: Span,
expr_span: Span,
body_expr: Option<&'hir hir::Expr<'hir>>,
loop_bind: Option<&'hir Ident>,
loop_span: Option<Span>,
head_span: Option<Span>,
pat_span: Option<Span>,
head: Option<&'hir hir::Expr<'hir>>,
body_expr: Option<&'hir hir::Expr<'hir>> = None,
loop_bind: Option<&'hir Ident> = None,
loop_span: Option<Span> = None,
head_span: Option<Span> = None,
pat_span: Option<Span> = None,
head: Option<&'hir hir::Expr<'hir>> = None,
}
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
Expand Down Expand Up @@ -2383,17 +2383,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
hir::intravisit::walk_expr(self, ex);
}
}
let mut finder = ExprFinder {
tcx,
expr_span: span,
issue_span,
loop_bind: None,
body_expr: None,
head_span: None,
loop_span: None,
pat_span: None,
head: None,
};
let mut finder = ExprFinder { tcx, expr_span: span, issue_span, .. };
finder.visit_expr(tcx.hir_body(body_id).value);

if let Some(body_expr) = finder.body_expr
Expand Down Expand Up @@ -2628,13 +2618,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {

struct ExpressionFinder<'tcx> {
capture_span: Span,
closure_change_spans: Vec<Span>,
closure_arg_span: Option<Span>,
in_closure: bool,
suggest_arg: String,
closure_change_spans: Vec<Span> = vec![],
closure_arg_span: Option<Span> = None,
in_closure: bool = false,
suggest_arg: String = String::new(),
tcx: TyCtxt<'tcx>,
closure_local_id: Option<hir::HirId>,
closure_call_changes: Vec<(Span, String)>,
closure_local_id: Option<hir::HirId> = None,
closure_call_changes: Vec<(Span, String)> = vec![],
}
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
Expand Down Expand Up @@ -2715,16 +2705,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}) = self.infcx.tcx.hir_node(self.mir_hir_id())
&& let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id)
{
let mut finder = ExpressionFinder {
capture_span: *capture_kind_span,
closure_change_spans: vec![],
closure_arg_span: None,
in_closure: false,
suggest_arg: String::new(),
closure_local_id: None,
closure_call_changes: vec![],
tcx: self.infcx.tcx,
};
let mut finder =
ExpressionFinder { capture_span: *capture_kind_span, tcx: self.infcx.tcx, .. };
finder.visit_expr(expr);

if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![allow(internal_features)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(default_field_values)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(negative_impls)]
Expand Down
18 changes: 5 additions & 13 deletions compiler/rustc_hir_analysis/src/hir_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
struct HirWfCheck<'tcx> {
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
cause: Option<ObligationCause<'tcx>>,
cause_depth: usize,
cause: Option<ObligationCause<'tcx>> = None,
cause_depth: usize = 0,
icx: ItemCtxt<'tcx>,
def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
depth: usize,
depth: usize = 0,
}

impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
Expand Down Expand Up @@ -124,16 +124,8 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
}
}

let mut visitor = HirWfCheck {
tcx,
predicate,
cause: None,
cause_depth: 0,
icx,
def_id,
param_env: tcx.param_env(def_id.to_def_id()),
depth: 0,
};
let param_env = tcx.param_env(def_id.to_def_id());
let mut visitor = HirWfCheck { tcx, predicate, icx, def_id, param_env, .. };

// Get the starting `hir::Ty` using our `WellFormedLoc`.
// We will walk 'into' this type to try to find
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ This API is completely unstable and subject to change.
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(assert_matches)]
#![feature(default_field_values)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
Expand Down
16 changes: 1 addition & 15 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::sync::Arc;

use rustc_abi::FieldIdx;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};

Expand Down Expand Up @@ -160,10 +159,7 @@ impl<'tcx> MatchPairTree<'tcx> {
}

PatKind::Constant { value } => {
// CAUTION: The type of the pattern node (`pattern.ty`) is
// _often_ the same as the type of the const value (`value.ty`),
// but there are some cases where those types differ
// (e.g. when `deref!(..)` patterns interact with `String`).
assert_eq!(pattern.ty, value.ty);

// Classify the constant-pattern into further kinds, to
// reduce the number of ad-hoc type tests needed later on.
Expand All @@ -175,16 +171,6 @@ impl<'tcx> MatchPairTree<'tcx> {
} else if pat_ty.is_floating_point() {
PatConstKind::Float
} else if pat_ty.is_str() {
// Deref-patterns can cause string-literal patterns to have
// type `str` instead of the usual `&str`.
if !cx.tcx.features().deref_patterns() {
span_bug!(
pattern.span,
"const pattern has type `str` but deref_patterns is not enabled"
);
}
PatConstKind::String
} else if pat_ty.is_imm_ref_str() {
PatConstKind::String
} else {
// FIXME(Zalathar): This still covers several different
Expand Down
12 changes: 3 additions & 9 deletions compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1339,19 +1339,13 @@ enum TestKind<'tcx> {

/// Tests the place against a string constant using string equality.
StringEq {
/// Constant `&str` value to test against.
/// Constant string value to test against.
/// Note that this value has type `str` (not `&str`).
value: ty::Value<'tcx>,
/// Type of the corresponding pattern node. Usually `&str`, but could
/// be `str` for patterns like `deref!("..."): String`.
pat_ty: Ty<'tcx>,
},

/// Tests the place against a constant using scalar equality.
ScalarEq {
value: ty::Value<'tcx>,
/// Type of the corresponding pattern node.
pat_ty: Ty<'tcx>,
},
ScalarEq { value: ty::Value<'tcx> },

/// Test whether the value falls within an inclusive or exclusive range.
Range(Arc<PatRange<'tcx>>),
Expand Down
74 changes: 28 additions & 46 deletions compiler/rustc_mir_build/src/builder/matches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use std::sync::Arc;

use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::{LangItem, RangeEnd};
use rustc_middle::bug;
use rustc_middle::mir::*;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
Expand All @@ -39,10 +39,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TestKind::SwitchInt
}
TestableCase::Constant { value, kind: PatConstKind::String } => {
TestKind::StringEq { value, pat_ty: match_pair.pattern_ty }
TestKind::StringEq { value }
}
TestableCase::Constant { value, kind: PatConstKind::Float | PatConstKind::Other } => {
TestKind::ScalarEq { value, pat_ty: match_pair.pattern_ty }
TestKind::ScalarEq { value }
}

TestableCase::Range(ref range) => {
Expand Down Expand Up @@ -141,47 +141,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.terminate(block, self.source_info(match_start_span), terminator);
}

TestKind::StringEq { value, pat_ty } => {
TestKind::StringEq { value } => {
let tcx = self.tcx;
let success_block = target_block(TestBranch::Success);
let fail_block = target_block(TestBranch::Failure);

let expected_value_ty = value.ty;
let expected_value_operand =
self.literal_operand(test.span, Const::from_ty_value(tcx, value));
let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, tcx.types.str_);
assert!(ref_str_ty.is_imm_ref_str(), "{ref_str_ty:?}");

let mut actual_value_ty = pat_ty;
let mut actual_value_place = place;

match pat_ty.kind() {
ty::Str => {
// String literal patterns may have type `str` if `deref_patterns` is
// enabled, in order to allow `deref!("..."): String`. In this case, `value`
// is of type `&str`, so we compare it to `&place`.
if !tcx.features().deref_patterns() {
span_bug!(
test.span,
"matching on `str` went through without enabling deref_patterns"
);
}
let re_erased = tcx.lifetimes.re_erased;
let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
let ref_place = self.temp(ref_str_ty, test.span);
// `let ref_place: &str = &place;`
self.cfg.push_assign(
block,
self.source_info(test.span),
ref_place,
Rvalue::Ref(re_erased, BorrowKind::Shared, place),
);
actual_value_place = ref_place;
actual_value_ty = ref_str_ty;
}
_ => {}
}
// The string constant we're testing against has type `str`, but
// calling `<str as PartialEq>::eq` requires `&str` operands.
//
// Because `str` and `&str` have the same valtree representation,
// we can "cast" to the desired type by just replacing the type.
assert!(value.ty.is_str(), "unexpected value type for StringEq test: {value:?}");
let expected_value = ty::Value { ty: ref_str_ty, valtree: value.valtree };
let expected_value_operand =
self.literal_operand(test.span, Const::from_ty_value(tcx, expected_value));

assert_eq!(expected_value_ty, actual_value_ty);
assert!(actual_value_ty.is_imm_ref_str());
// Similarly, the scrutinized place has type `str`, but we need `&str`.
// Get a reference by doing `let actual_value_ref_place: &str = &place`.
let actual_value_ref_place = self.temp(ref_str_ty, test.span);
self.cfg.push_assign(
block,
self.source_info(test.span),
actual_value_ref_place,
Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, place),
);

// Compare two strings using `<str as std::cmp::PartialEq>::eq`.
// (Interestingly this means that exhaustiveness analysis relies, for soundness,
Expand All @@ -192,11 +178,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fail_block,
source_info,
expected_value_operand,
Operand::Copy(actual_value_place),
Operand::Copy(actual_value_ref_place),
);
}

TestKind::ScalarEq { value, pat_ty } => {
TestKind::ScalarEq { value } => {
let tcx = self.tcx;
let success_block = target_block(TestBranch::Success);
let fail_block = target_block(TestBranch::Failure);
Expand All @@ -205,12 +191,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut expected_value_operand =
self.literal_operand(test.span, Const::from_ty_value(tcx, value));

let mut actual_value_ty = pat_ty;
let mut actual_value_place = place;

match pat_ty.kind() {
match value.ty.kind() {
&ty::Pat(base, _) => {
assert_eq!(pat_ty, value.ty);
assert!(base.is_trivially_pure_clone_copy());

let transmuted_place = self.temp(base, test.span);
Expand All @@ -234,15 +218,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);

actual_value_place = transmuted_place;
actual_value_ty = base;
expected_value_operand = Operand::Copy(transmuted_expect);
expected_value_ty = base;
}
_ => {}
}

assert_eq!(expected_value_ty, actual_value_ty);
assert!(actual_value_ty.is_scalar());
assert!(expected_value_ty.is_scalar());

self.compare(
block,
Expand Down
45 changes: 21 additions & 24 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,32 +289,29 @@ impl<'tcx> ConstToPat<'tcx> {
suffix: Box::new([]),
},
ty::Str => {
// String literal patterns may have type `str` if `deref_patterns` is enabled, in
// order to allow `deref!("..."): String`. Since we need a `&str` for the comparison
// when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
// This works because `str` and `&str` have the same valtree representation.
let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
PatKind::Constant { value: ty::Value { ty: ref_str_ty, valtree: cv } }
// Constant/literal patterns of type `&str` are lowered to a
// `PatKind::Deref` wrapping a `PatKind::Constant` of type `str`.
// This pattern node is the `str` constant part.
//
// Under `feature(deref_patterns)`, string literal patterns can also
// have type `str` directly, without the `&`, in order to allow things
// like `deref!("...")` to work when the scrutinee is `String`.
PatKind::Constant { value: ty::Value { ty, valtree: cv } }
}
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// `&str` is represented as a valtree, let's keep using this
// optimization for now.
ty::Str => PatKind::Constant { value: ty::Value { ty, valtree: cv } },
// All other references are converted into deref patterns and then recursively
// convert the dereferenced constant to a pattern that is the sub-pattern of the
// deref pattern.
_ => {
if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() {
return self.mk_err(
tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
ty,
);
} else {
// References have the same valtree representation as their pointee.
PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
}
ty::Ref(_, pointee_ty, ..) => {
if pointee_ty.is_str()
|| pointee_ty.is_slice()
|| pointee_ty.is_sized(tcx, self.typing_env)
{
// References have the same valtree representation as their pointee.
PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
} else {
return self.mk_err(
tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
ty,
);
}
},
}
ty::Float(flt) => {
let v = cv.to_leaf();
let is_nan = match flt {
Expand Down
Loading
Loading