Skip to content

Commit 6377d50

Browse files
committed
Support "for loop" MIR lowering
1 parent ac04bfd commit 6377d50

File tree

8 files changed

+292
-79
lines changed

8 files changed

+292
-79
lines changed

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,43 @@ fn loops() {
415415
);
416416
}
417417

418+
#[test]
419+
fn for_loops() {
420+
check_number(
421+
r#"
422+
//- minicore: iterator
423+
424+
struct Range {
425+
start: u8,
426+
end: u8,
427+
}
428+
429+
impl Iterator for Range {
430+
type Item = u8;
431+
fn next(&mut self) -> Option<u8> {
432+
if self.start >= self.end {
433+
None
434+
} else {
435+
let r = self.start;
436+
self.start = self.start + 1;
437+
Some(r)
438+
}
439+
}
440+
}
441+
442+
const GOAL: u8 = {
443+
let mut sum = 0;
444+
let ar = Range { start: 1, end: 11 };
445+
for i in ar {
446+
sum = sum + i;
447+
}
448+
sum
449+
};
450+
"#,
451+
55,
452+
);
453+
}
454+
418455
#[test]
419456
fn recursion() {
420457
check_number(
@@ -518,6 +555,33 @@ fn tuples() {
518555
);
519556
}
520557

558+
#[test]
559+
fn path_pattern_matching() {
560+
check_number(
561+
r#"
562+
enum Season {
563+
Spring,
564+
Summer,
565+
Fall,
566+
Winter,
567+
}
568+
569+
use Season::*;
570+
571+
const fn f(x: Season) -> i32 {
572+
match x {
573+
Spring => 1,
574+
Summer => 2,
575+
Fall => 3,
576+
Winter => 4,
577+
}
578+
}
579+
const GOAL: i32 = f(Spring) + 10 * f(Summer) + 100 * f(Fall) + 1000 * f(Winter);
580+
"#,
581+
4321,
582+
);
583+
}
584+
521585
#[test]
522586
fn pattern_matching_ergonomics() {
523587
check_number(

crates/hir-ty/src/infer.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ pub struct InferenceResult {
354354
pub type_of_pat: ArenaMap<PatId, Ty>,
355355
pub type_of_binding: ArenaMap<BindingId, Ty>,
356356
pub type_of_rpit: ArenaMap<RpitId, Ty>,
357+
/// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
358+
pub type_of_for_iterator: ArenaMap<ExprId, Ty>,
357359
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
358360
/// Interned common types to return references to.
359361
standard_types: InternedStandardTypes,
@@ -549,6 +551,9 @@ impl<'a> InferenceContext<'a> {
549551
for ty in result.type_of_rpit.values_mut() {
550552
*ty = table.resolve_completely(ty.clone());
551553
}
554+
for ty in result.type_of_for_iterator.values_mut() {
555+
*ty = table.resolve_completely(ty.clone());
556+
}
552557
for mismatch in result.type_mismatches.values_mut() {
553558
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
554559
mismatch.actual = table.resolve_completely(mismatch.actual.clone());

crates/hir-ty/src/infer/expr.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,10 @@ impl<'a> InferenceContext<'a> {
242242
let iterable_ty = self.infer_expr(iterable, &Expectation::none());
243243
let into_iter_ty =
244244
self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
245-
let pat_ty =
246-
self.resolve_associated_type(into_iter_ty, self.resolve_iterator_item());
245+
let pat_ty = self
246+
.resolve_associated_type(into_iter_ty.clone(), self.resolve_iterator_item());
247+
248+
self.result.type_of_for_iterator.insert(tgt_expr, into_iter_ty);
247249

248250
self.infer_top_pat(pat, &pat_ty);
249251
self.with_breakable_ctx(BreakableKind::Loop, None, label, |this| {

crates/hir-ty/src/mir.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ impl Operand {
8383
fn from_bytes(data: Vec<u8>, ty: Ty) -> Self {
8484
Operand::from_concrete_const(data, MemoryMap::default(), ty)
8585
}
86+
87+
fn const_zst(ty: Ty) -> Operand {
88+
Self::from_bytes(vec![], ty)
89+
}
8690
}
8791

8892
#[derive(Debug, PartialEq, Eq, Clone)]

crates/hir-ty/src/mir/eval.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,12 @@ impl Evaluator<'_> {
11221122
}
11231123

11241124
fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> {
1125-
lang_attr(self.db.upcast(), def)
1125+
let candidate = lang_attr(self.db.upcast(), def)?;
1126+
// filter normal lang functions out
1127+
if [LangItem::IntoIterIntoIter, LangItem::IteratorNext].contains(&candidate) {
1128+
return None;
1129+
}
1130+
Some(candidate)
11261131
}
11271132

11281133
fn create_memory_map(&self, bytes: &[u8], ty: &Ty, locals: &Locals<'_>) -> Result<MemoryMap> {

0 commit comments

Comments
 (0)