Skip to content

Commit 453ae2e

Browse files
committed
Support range MIR lowering
1 parent 9ad83de commit 453ae2e

File tree

4 files changed

+65
-8
lines changed

4 files changed

+65
-8
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,18 @@ fn for_loops() {
561561
);
562562
}
563563

564+
#[test]
565+
fn ranges() {
566+
check_number(
567+
r#"
568+
//- minicore: range
569+
const GOAL: i32 = (1..2).start + (20..10).end + (100..=200).start + (2000..=1000).end
570+
+ (10000..).start + (..100000).end + (..=1000000).end;
571+
"#,
572+
1111111,
573+
);
574+
}
575+
564576
#[test]
565577
fn recursion() {
566578
check_number(

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -633,15 +633,18 @@ impl<'a> InferenceTable<'a> {
633633
) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
634634
match ty.callable_sig(self.db) {
635635
Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
636-
None => self.callable_sig_from_fn_trait(ty, num_args),
636+
None => {
637+
let (f, args_ty, return_ty) = self.callable_sig_from_fn_trait(ty, num_args)?;
638+
Some((Some(f), args_ty, return_ty))
639+
}
637640
}
638641
}
639642

640643
fn callable_sig_from_fn_trait(
641644
&mut self,
642645
ty: &Ty,
643646
num_args: usize,
644-
) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
647+
) -> Option<(FnTrait, Vec<Ty>, Ty)> {
645648
let krate = self.trait_env.krate;
646649
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
647650
let trait_data = self.db.trait_data(fn_once_trait);
@@ -693,7 +696,7 @@ impl<'a> InferenceTable<'a> {
693696
};
694697
let canonical = self.canonicalize(obligation.clone());
695698
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
696-
return Some((Some(fn_x), arg_tys, return_ty));
699+
return Some((fn_x, arg_tys, return_ty));
697700
}
698701
}
699702
unreachable!("It should at least implement FnOnce at this point");

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

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use hir_def::{
1414
layout::LayoutError,
1515
path::Path,
1616
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
17-
DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, LocalFieldId, TraitId,
17+
AdtId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, LocalFieldId, TraitId,
1818
};
1919
use hir_expand::name::Name;
2020
use la_arena::ArenaMap;
@@ -643,7 +643,7 @@ impl MirLowerCtx<'_> {
643643
},
644644
}
645645
}).collect(),
646-
None => operands.into_iter().map(|x| x).collect::<Option<_>>().ok_or(
646+
None => operands.into_iter().collect::<Option<_>>().ok_or(
647647
MirLowerError::TypeError("missing field in record literal"),
648648
)?,
649649
},
@@ -761,7 +761,49 @@ impl MirLowerCtx<'_> {
761761
);
762762
Ok(Some(current))
763763
}
764-
Expr::Range { .. } => not_supported!("range"),
764+
&Expr::Range { lhs, rhs, range_type: _ } => {
765+
let ty = self.expr_ty(expr_id);
766+
let Some((adt, subst)) = ty.as_adt() else {
767+
return Err(MirLowerError::TypeError("Range type is not adt"));
768+
};
769+
let AdtId::StructId(st) = adt else {
770+
return Err(MirLowerError::TypeError("Range type is not struct"));
771+
};
772+
let mut lp = None;
773+
let mut rp = None;
774+
if let Some(x) = lhs {
775+
let Some((o, c)) = self.lower_expr_to_some_operand(x, current)? else {
776+
return Ok(None);
777+
};
778+
lp = Some(o);
779+
current = c;
780+
}
781+
if let Some(x) = rhs {
782+
let Some((o, c)) = self.lower_expr_to_some_operand(x, current)? else {
783+
return Ok(None);
784+
};
785+
rp = Some(o);
786+
current = c;
787+
}
788+
self.push_assignment(
789+
current,
790+
place,
791+
Rvalue::Aggregate(
792+
AggregateKind::Adt(st.into(), subst.clone()),
793+
self.db.struct_data(st).variant_data.fields().iter().map(|x| {
794+
let o = match x.1.name.as_str() {
795+
Some("start") => lp.take(),
796+
Some("end") => rp.take(),
797+
Some("exhausted") => Some(Operand::from_bytes(vec![0], TyBuilder::bool())),
798+
_ => None,
799+
};
800+
o.ok_or(MirLowerError::UnresolvedField)
801+
}).collect::<Result<_>>()?,
802+
),
803+
expr_id.into(),
804+
);
805+
Ok(Some(current))
806+
},
765807
Expr::Closure { .. } => not_supported!("closure"),
766808
Expr::Tuple { exprs, is_assignee_expr: _ } => {
767809
let Some(values) = exprs

crates/hir-ty/src/traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,15 @@ impl FnTrait {
188188
}
189189
}
190190

191-
pub fn method_name(&self) -> Name {
191+
pub fn method_name(self) -> Name {
192192
match self {
193193
FnTrait::FnOnce => name!(call_once),
194194
FnTrait::FnMut => name!(call_mut),
195195
FnTrait::Fn => name!(call),
196196
}
197197
}
198198

199-
pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
199+
pub fn get_id(self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
200200
let target = db.lang_item(krate, self.lang_item())?;
201201
match target {
202202
LangItemTarget::Trait(t) => Some(t),

0 commit comments

Comments
 (0)