From 453ae2e00e2f3bcd96a2fa78626296e14641dae8 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sat, 18 Mar 2023 02:06:36 +0330 Subject: [PATCH] Support range MIR lowering --- crates/hir-ty/src/consteval/tests.rs | 12 +++++++ crates/hir-ty/src/infer/unify.rs | 9 ++++-- crates/hir-ty/src/mir/lower.rs | 48 ++++++++++++++++++++++++++-- crates/hir-ty/src/traits.rs | 4 +-- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 944912b6c26..97c8d62860c 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -561,6 +561,18 @@ fn for_loops() { ); } +#[test] +fn ranges() { + check_number( + r#" + //- minicore: range + const GOAL: i32 = (1..2).start + (20..10).end + (100..=200).start + (2000..=1000).end + + (10000..).start + (..100000).end + (..=1000000).end; + "#, + 1111111, + ); +} + #[test] fn recursion() { check_number( diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 2a07dd708c2..0e516b9399a 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -633,7 +633,10 @@ impl<'a> InferenceTable<'a> { ) -> Option<(Option, Vec, Ty)> { match ty.callable_sig(self.db) { Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())), - None => self.callable_sig_from_fn_trait(ty, num_args), + None => { + let (f, args_ty, return_ty) = self.callable_sig_from_fn_trait(ty, num_args)?; + Some((Some(f), args_ty, return_ty)) + } } } @@ -641,7 +644,7 @@ impl<'a> InferenceTable<'a> { &mut self, ty: &Ty, num_args: usize, - ) -> Option<(Option, Vec, Ty)> { + ) -> Option<(FnTrait, Vec, Ty)> { let krate = self.trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; let trait_data = self.db.trait_data(fn_once_trait); @@ -693,7 +696,7 @@ impl<'a> InferenceTable<'a> { }; let canonical = self.canonicalize(obligation.clone()); if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() { - return Some((Some(fn_x), arg_tys, return_ty)); + return Some((fn_x, arg_tys, return_ty)); } } unreachable!("It should at least implement FnOnce at this point"); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 04175fb4d95..4b43e44a8ec 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -14,7 +14,7 @@ use hir_def::{ layout::LayoutError, path::Path, resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, - DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, LocalFieldId, TraitId, + AdtId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, LocalFieldId, TraitId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -643,7 +643,7 @@ impl MirLowerCtx<'_> { }, } }).collect(), - None => operands.into_iter().map(|x| x).collect::>().ok_or( + None => operands.into_iter().collect::>().ok_or( MirLowerError::TypeError("missing field in record literal"), )?, }, @@ -761,7 +761,49 @@ impl MirLowerCtx<'_> { ); Ok(Some(current)) } - Expr::Range { .. } => not_supported!("range"), + &Expr::Range { lhs, rhs, range_type: _ } => { + let ty = self.expr_ty(expr_id); + let Some((adt, subst)) = ty.as_adt() else { + return Err(MirLowerError::TypeError("Range type is not adt")); + }; + let AdtId::StructId(st) = adt else { + return Err(MirLowerError::TypeError("Range type is not struct")); + }; + let mut lp = None; + let mut rp = None; + if let Some(x) = lhs { + let Some((o, c)) = self.lower_expr_to_some_operand(x, current)? else { + return Ok(None); + }; + lp = Some(o); + current = c; + } + if let Some(x) = rhs { + let Some((o, c)) = self.lower_expr_to_some_operand(x, current)? else { + return Ok(None); + }; + rp = Some(o); + current = c; + } + self.push_assignment( + current, + place, + Rvalue::Aggregate( + AggregateKind::Adt(st.into(), subst.clone()), + self.db.struct_data(st).variant_data.fields().iter().map(|x| { + let o = match x.1.name.as_str() { + Some("start") => lp.take(), + Some("end") => rp.take(), + Some("exhausted") => Some(Operand::from_bytes(vec![0], TyBuilder::bool())), + _ => None, + }; + o.ok_or(MirLowerError::UnresolvedField) + }).collect::>()?, + ), + expr_id.into(), + ); + Ok(Some(current)) + }, Expr::Closure { .. } => not_supported!("closure"), Expr::Tuple { exprs, is_assignee_expr: _ } => { let Some(values) = exprs diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index aebf59f3152..e7fffc4cc7d 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -188,7 +188,7 @@ impl FnTrait { } } - pub fn method_name(&self) -> Name { + pub fn method_name(self) -> Name { match self { FnTrait::FnOnce => name!(call_once), FnTrait::FnMut => name!(call_mut), @@ -196,7 +196,7 @@ impl FnTrait { } } - pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option { + pub fn get_id(self, db: &dyn HirDatabase, krate: CrateId) -> Option { let target = db.lang_item(krate, self.lang_item())?; match target { LangItemTarget::Trait(t) => Some(t),