Skip to content

Commit a25710b

Browse files
committed
Add need-mut and unused-mut diagnostics
1 parent c0a0664 commit a25710b

File tree

10 files changed

+1089
-277
lines changed

10 files changed

+1089
-277
lines changed

crates/hir-def/src/body.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,13 @@ impl Body {
422422
}
423423
}
424424

425+
pub fn walk_child_bindings(&self, pat: PatId, f: &mut impl FnMut(BindingId)) {
426+
if let Pat::Bind { id, .. } = self[pat] {
427+
f(id)
428+
}
429+
self[pat].walk_child_pats(|p| self.walk_child_bindings(p, f));
430+
}
431+
425432
pub fn pretty_print(&self, db: &dyn DefDatabase, owner: DefWithBodyId) -> String {
426433
pretty::print_body_hir(db, self, owner)
427434
}

crates/hir-ty/src/consteval/tests.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ fn references() {
103103
"#,
104104
5,
105105
);
106+
check_number(
107+
r#"
108+
struct Foo(i32);
109+
impl Foo {
110+
fn method(&mut self, x: i32) {
111+
self.0 = 2 * self.0 + x;
112+
}
113+
}
114+
const GOAL: i32 = {
115+
let mut x = Foo(3);
116+
x.method(5);
117+
x.0
118+
};
119+
"#,
120+
11,
121+
);
106122
}
107123

108124
#[test]
@@ -358,15 +374,15 @@ fn ifs() {
358374
if a < b { b } else { a }
359375
}
360376
361-
const GOAL: u8 = max(max(1, max(10, 3)), 0-122);
377+
const GOAL: i32 = max(max(1, max(10, 3)), 0-122);
362378
"#,
363379
10,
364380
);
365381

366382
check_number(
367383
r#"
368384
const fn max(a: &i32, b: &i32) -> &i32 {
369-
if a < b { b } else { a }
385+
if *a < *b { b } else { a }
370386
}
371387
372388
const GOAL: i32 = *max(max(&1, max(&10, &3)), &5);
@@ -464,6 +480,16 @@ fn tuples() {
464480
"#,
465481
20,
466482
);
483+
check_number(
484+
r#"
485+
const GOAL: u8 = {
486+
let mut a = (10, 20, 3, 15);
487+
a.1 = 2;
488+
a.0 + a.1 + a.2 + a.3
489+
};
490+
"#,
491+
30,
492+
);
467493
check_number(
468494
r#"
469495
struct TupleLike(i32, u8, i64, u16);
@@ -539,7 +565,7 @@ fn let_else() {
539565
let Some(x) = x else { return 10 };
540566
2 * x
541567
}
542-
const GOAL: u8 = f(Some(1000)) + f(None);
568+
const GOAL: i32 = f(Some(1000)) + f(None);
543569
"#,
544570
2010,
545571
);
@@ -615,7 +641,7 @@ fn options() {
615641
0
616642
}
617643
}
618-
const GOAL: u8 = f(Some(Some(10))) + f(Some(None)) + f(None);
644+
const GOAL: i32 = f(Some(Some(10))) + f(Some(None)) + f(None);
619645
"#,
620646
11,
621647
);
@@ -746,24 +772,24 @@ fn enums() {
746772
r#"
747773
enum E {
748774
F1 = 1,
749-
F2 = 2 * E::F1 as u8,
750-
F3 = 3 * E::F2 as u8,
775+
F2 = 2 * E::F1 as isize, // Rustc expects an isize here
776+
F3 = 3 * E::F2 as isize,
751777
}
752-
const GOAL: i32 = E::F3 as u8;
778+
const GOAL: u8 = E::F3 as u8;
753779
"#,
754780
6,
755781
);
756782
check_number(
757783
r#"
758784
enum E { F1 = 1, F2, }
759-
const GOAL: i32 = E::F2 as u8;
785+
const GOAL: u8 = E::F2 as u8;
760786
"#,
761787
2,
762788
);
763789
check_number(
764790
r#"
765791
enum E { F1, }
766-
const GOAL: i32 = E::F1 as u8;
792+
const GOAL: u8 = E::F1 as u8;
767793
"#,
768794
0,
769795
);
@@ -894,8 +920,22 @@ fn exec_limits() {
894920
}
895921
sum
896922
}
897-
const GOAL: usize = f(10000);
923+
const GOAL: i32 = f(10000);
898924
"#,
899925
10000 * 10000,
900926
);
901927
}
928+
929+
#[test]
930+
fn type_error() {
931+
let e = eval_goal(
932+
r#"
933+
const GOAL: u8 = {
934+
let x: u16 = 2;
935+
let y: (u8, u8) = x;
936+
y.0
937+
};
938+
"#,
939+
);
940+
assert!(matches!(e, Err(ConstEvalError::MirLowerError(MirLowerError::TypeMismatch(_)))));
941+
}

crates/hir-ty/src/mir.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ use crate::{
77
};
88
use chalk_ir::Mutability;
99
use hir_def::{
10-
expr::{Expr, Ordering},
10+
expr::{BindingId, Expr, ExprId, Ordering, PatId},
1111
DefWithBodyId, FieldId, UnionId, VariantId,
1212
};
13-
use la_arena::{Arena, Idx, RawIdx};
13+
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
1414

1515
mod eval;
1616
mod lower;
17+
pub mod borrowck;
1718

1819
pub use eval::{interpret_mir, pad16, Evaluator, MirEvalError};
1920
pub use lower::{lower_to_mir, mir_body_query, mir_body_recover, MirLowerError};
2021
use smallvec::{smallvec, SmallVec};
22+
use stdx::impl_from;
2123

2224
use super::consteval::{intern_const_scalar, try_const_usize};
2325

@@ -181,6 +183,11 @@ impl SwitchTargets {
181183
iter::zip(&self.values, &self.targets).map(|(x, y)| (*x, *y))
182184
}
183185

186+
/// Returns a slice with all possible jump targets (including the fallback target).
187+
pub fn all_targets(&self) -> &[BasicBlockId] {
188+
&self.targets
189+
}
190+
184191
/// Finds the `BasicBlock` to which this `SwitchInt` will branch given the
185192
/// specific value. This cannot fail, as it'll return the `otherwise`
186193
/// branch if there's not a specific match for the value.
@@ -758,7 +765,7 @@ pub enum Rvalue {
758765
}
759766

760767
#[derive(Debug, PartialEq, Eq, Clone)]
761-
pub enum Statement {
768+
pub enum StatementKind {
762769
Assign(Place, Rvalue),
763770
//FakeRead(Box<(FakeReadCause, Place)>),
764771
//SetDiscriminant {
@@ -773,6 +780,17 @@ pub enum Statement {
773780
//Intrinsic(Box<NonDivergingIntrinsic>),
774781
Nop,
775782
}
783+
impl StatementKind {
784+
fn with_span(self, span: MirSpan) -> Statement {
785+
Statement { kind: self, span }
786+
}
787+
}
788+
789+
#[derive(Debug, PartialEq, Eq, Clone)]
790+
pub struct Statement {
791+
pub kind: StatementKind,
792+
pub span: MirSpan,
793+
}
776794

777795
#[derive(Debug, Default, PartialEq, Eq)]
778796
pub struct BasicBlock {
@@ -803,10 +821,20 @@ pub struct MirBody {
803821
pub start_block: BasicBlockId,
804822
pub owner: DefWithBodyId,
805823
pub arg_count: usize,
824+
pub binding_locals: ArenaMap<BindingId, LocalId>,
806825
}
807826

808827
impl MirBody {}
809828

810829
fn const_as_usize(c: &Const) -> usize {
811830
try_const_usize(c).unwrap() as usize
812831
}
832+
833+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
834+
pub enum MirSpan {
835+
ExprId(ExprId),
836+
PatId(PatId),
837+
Unknown,
838+
}
839+
840+
impl_from!(ExprId, PatId for MirSpan);

0 commit comments

Comments
 (0)