mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 22:31:43 +00:00
Support range MIR lowering
This commit is contained in:
parent
9ad83deecc
commit
453ae2e00e
4 changed files with 65 additions and 8 deletions
|
@ -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]
|
#[test]
|
||||||
fn recursion() {
|
fn recursion() {
|
||||||
check_number(
|
check_number(
|
||||||
|
|
|
@ -633,7 +633,10 @@ impl<'a> InferenceTable<'a> {
|
||||||
) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
|
) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
|
||||||
match ty.callable_sig(self.db) {
|
match ty.callable_sig(self.db) {
|
||||||
Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
|
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,
|
&mut self,
|
||||||
ty: &Ty,
|
ty: &Ty,
|
||||||
num_args: usize,
|
num_args: usize,
|
||||||
) -> Option<(Option<FnTrait>, Vec<Ty>, Ty)> {
|
) -> Option<(FnTrait, Vec<Ty>, Ty)> {
|
||||||
let krate = self.trait_env.krate;
|
let krate = self.trait_env.krate;
|
||||||
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
||||||
let trait_data = self.db.trait_data(fn_once_trait);
|
let trait_data = self.db.trait_data(fn_once_trait);
|
||||||
|
@ -693,7 +696,7 @@ impl<'a> InferenceTable<'a> {
|
||||||
};
|
};
|
||||||
let canonical = self.canonicalize(obligation.clone());
|
let canonical = self.canonicalize(obligation.clone());
|
||||||
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
|
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");
|
unreachable!("It should at least implement FnOnce at this point");
|
||||||
|
|
|
@ -14,7 +14,7 @@ use hir_def::{
|
||||||
layout::LayoutError,
|
layout::LayoutError,
|
||||||
path::Path,
|
path::Path,
|
||||||
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
|
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 hir_expand::name::Name;
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
|
@ -643,7 +643,7 @@ impl MirLowerCtx<'_> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}).collect(),
|
}).collect(),
|
||||||
None => operands.into_iter().map(|x| x).collect::<Option<_>>().ok_or(
|
None => operands.into_iter().collect::<Option<_>>().ok_or(
|
||||||
MirLowerError::TypeError("missing field in record literal"),
|
MirLowerError::TypeError("missing field in record literal"),
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
|
@ -761,7 +761,49 @@ impl MirLowerCtx<'_> {
|
||||||
);
|
);
|
||||||
Ok(Some(current))
|
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::<Result<_>>()?,
|
||||||
|
),
|
||||||
|
expr_id.into(),
|
||||||
|
);
|
||||||
|
Ok(Some(current))
|
||||||
|
},
|
||||||
Expr::Closure { .. } => not_supported!("closure"),
|
Expr::Closure { .. } => not_supported!("closure"),
|
||||||
Expr::Tuple { exprs, is_assignee_expr: _ } => {
|
Expr::Tuple { exprs, is_assignee_expr: _ } => {
|
||||||
let Some(values) = exprs
|
let Some(values) = exprs
|
||||||
|
|
|
@ -188,7 +188,7 @@ impl FnTrait {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn method_name(&self) -> Name {
|
pub fn method_name(self) -> Name {
|
||||||
match self {
|
match self {
|
||||||
FnTrait::FnOnce => name!(call_once),
|
FnTrait::FnOnce => name!(call_once),
|
||||||
FnTrait::FnMut => name!(call_mut),
|
FnTrait::FnMut => name!(call_mut),
|
||||||
|
@ -196,7 +196,7 @@ impl FnTrait {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
|
pub fn get_id(self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
|
||||||
let target = db.lang_item(krate, self.lang_item())?;
|
let target = db.lang_item(krate, self.lang_item())?;
|
||||||
match target {
|
match target {
|
||||||
LangItemTarget::Trait(t) => Some(t),
|
LangItemTarget::Trait(t) => Some(t),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue