Store binding mode for each instance independently
This commit is contained in:
parent
7c11399b6b
commit
8b82ea4f51
@ -1159,6 +1159,20 @@ const fn f(x: &[usize]) -> usize {
|
||||
"#,
|
||||
33213,
|
||||
);
|
||||
check_number(
|
||||
r#"
|
||||
//- minicore: slice, index, coerce_unsized, copy
|
||||
const fn f(mut slice: &[u32]) -> usize {
|
||||
slice = match slice {
|
||||
[0, rest @ ..] | rest => rest,
|
||||
};
|
||||
slice.len()
|
||||
}
|
||||
const GOAL: usize = f(&[]) + f(&[10]) + f(&[0, 100])
|
||||
+ f(&[1000, 1000, 1000]) + f(&[0, 57, 34, 46, 10000, 10000]);
|
||||
"#,
|
||||
10,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -147,7 +147,7 @@ fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat {
|
||||
}
|
||||
|
||||
hir_def::hir::Pat::Bind { id, subpat, .. } => {
|
||||
let bm = self.infer.binding_modes[id];
|
||||
let bm = self.infer.binding_modes[pat];
|
||||
ty = &self.infer[id];
|
||||
let name = &self.body.bindings[id].name;
|
||||
match (bm, ty.kind(Interner)) {
|
||||
|
@ -420,7 +420,19 @@ pub struct InferenceResult {
|
||||
standard_types: InternedStandardTypes,
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
||||
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
|
||||
pub binding_modes: ArenaMap<BindingId, BindingMode>,
|
||||
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
|
||||
///
|
||||
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
|
||||
/// or pattern can have multiple binding modes. For example:
|
||||
/// ```
|
||||
/// fn foo(mut slice: &[u32]) -> usize {
|
||||
/// slice = match slice {
|
||||
/// [0, rest @ ..] | rest => rest,
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
|
||||
pub binding_modes: ArenaMap<PatId, BindingMode>,
|
||||
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
|
||||
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
|
||||
// FIXME: remove this field
|
||||
|
@ -679,7 +679,7 @@ fn walk_pat_inner(
|
||||
| Pat::Range { .. } => {
|
||||
update_result(CaptureKind::ByRef(BorrowKind::Shared));
|
||||
}
|
||||
Pat::Bind { id, .. } => match self.result.binding_modes[*id] {
|
||||
Pat::Bind { id, .. } => match self.result.binding_modes[p] {
|
||||
crate::BindingMode::Move => {
|
||||
if self.is_ty_copy(self.result.type_of_binding[*id].clone()) {
|
||||
update_result(CaptureKind::ByRef(BorrowKind::Shared));
|
||||
@ -838,8 +838,8 @@ fn consume_with_pat(&mut self, mut place: HirPlace, pat: PatId) {
|
||||
| Pat::ConstBlock(_)
|
||||
| Pat::Path(_)
|
||||
| Pat::Lit(_) => self.consume_place(place, pat.into()),
|
||||
Pat::Bind { id, subpat: _ } => {
|
||||
let mode = self.result.binding_modes[*id];
|
||||
Pat::Bind { id: _, subpat: _ } => {
|
||||
let mode = self.result.binding_modes[pat];
|
||||
let capture_kind = match mode {
|
||||
BindingMode::Move => {
|
||||
self.consume_place(place, pat.into());
|
||||
|
@ -421,7 +421,7 @@ fn infer_bind_pat(
|
||||
} else {
|
||||
BindingMode::convert(mode)
|
||||
};
|
||||
self.result.binding_modes.insert(binding, mode);
|
||||
self.result.binding_modes.insert(pat, mode);
|
||||
|
||||
let inner_ty = match subpat {
|
||||
Some(subpat) => self.infer_pat(subpat, &expected, default_bm),
|
||||
|
@ -284,6 +284,7 @@ fn pattern_match_inner(
|
||||
);
|
||||
(current, current_else) = self.pattern_match_binding(
|
||||
id,
|
||||
*slice,
|
||||
next_place,
|
||||
(*slice).into(),
|
||||
current,
|
||||
@ -395,6 +396,7 @@ fn pattern_match_inner(
|
||||
if mode == MatchingMode::Bind {
|
||||
self.pattern_match_binding(
|
||||
*id,
|
||||
pattern,
|
||||
cond_place,
|
||||
pattern.into(),
|
||||
current,
|
||||
@ -431,13 +433,14 @@ fn pattern_match_inner(
|
||||
fn pattern_match_binding(
|
||||
&mut self,
|
||||
id: BindingId,
|
||||
pat: PatId,
|
||||
cond_place: Place,
|
||||
span: MirSpan,
|
||||
current: BasicBlockId,
|
||||
current_else: Option<BasicBlockId>,
|
||||
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
|
||||
let target_place = self.binding_local(id)?;
|
||||
let mode = self.infer.binding_modes[id];
|
||||
let mode = self.infer.binding_modes[pat];
|
||||
self.push_storage_live(id, current)?;
|
||||
self.push_assignment(
|
||||
current,
|
||||
|
@ -236,9 +236,9 @@ pub(crate) fn binding_mode_of_pat(
|
||||
_db: &dyn HirDatabase,
|
||||
pat: &ast::IdentPat,
|
||||
) -> Option<BindingMode> {
|
||||
let binding_id = self.binding_id_of_pat(pat)?;
|
||||
let id = self.pat_id(&pat.clone().into())?;
|
||||
let infer = self.infer.as_ref()?;
|
||||
infer.binding_modes.get(binding_id).map(|bm| match bm {
|
||||
infer.binding_modes.get(id).map(|bm| match bm {
|
||||
hir_ty::BindingMode::Move => BindingMode::Move,
|
||||
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
|
||||
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
|
||||
|
@ -175,4 +175,19 @@ fn main() {
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_15787() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: coerce_unsized, slice, copy
|
||||
fn foo(mut slice: &[u32]) -> usize {
|
||||
slice = match slice {
|
||||
[0, rest @ ..] | rest => rest,
|
||||
};
|
||||
slice.len()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user