mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 21:13:37 +00:00
Auto merge of #15206 - Veykril:let-else-fmt, r=Veykril
internal: Format let-else As nightly finally got support for it I went ahead and formatted r-a with the latest nightly, then with the latest stable (in case other stuff changed)
This commit is contained in:
commit
daba334611
38 changed files with 572 additions and 306 deletions
|
@ -137,13 +137,16 @@ impl Attrs {
|
|||
|
||||
let cfg_options = &crate_graph[krate].cfg_options;
|
||||
|
||||
let Some(variant) = enum_.variants.clone().filter(|variant| {
|
||||
let attrs = item_tree.attrs(db, krate, (*variant).into());
|
||||
attrs.is_cfg_enabled(cfg_options)
|
||||
})
|
||||
.zip(0u32..)
|
||||
.find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx)))
|
||||
.map(|(variant, _idx)| variant)
|
||||
let Some(variant) = enum_
|
||||
.variants
|
||||
.clone()
|
||||
.filter(|variant| {
|
||||
let attrs = item_tree.attrs(db, krate, (*variant).into());
|
||||
attrs.is_cfg_enabled(cfg_options)
|
||||
})
|
||||
.zip(0u32..)
|
||||
.find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx)))
|
||||
.map(|(variant, _idx)| variant)
|
||||
else {
|
||||
return Arc::new(res);
|
||||
};
|
||||
|
|
|
@ -1451,9 +1451,7 @@ impl ExprCollector<'_> {
|
|||
&self,
|
||||
lifetime: Option<ast::Lifetime>,
|
||||
) -> Result<Option<LabelId>, BodyDiagnostic> {
|
||||
let Some(lifetime) = lifetime else {
|
||||
return Ok(None)
|
||||
};
|
||||
let Some(lifetime) = lifetime else { return Ok(None) };
|
||||
let name = Name::new_lifetime(&lifetime);
|
||||
|
||||
for (rib_idx, rib) in self.label_ribs.iter().enumerate().rev() {
|
||||
|
|
|
@ -2235,8 +2235,12 @@ impl ModCollector<'_, '_> {
|
|||
}
|
||||
|
||||
fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
|
||||
let Some((source, target)) = Self::borrow_modules(self.def_collector.def_map.modules.as_mut(), module_id, self.module_id) else {
|
||||
return
|
||||
let Some((source, target)) = Self::borrow_modules(
|
||||
self.def_collector.def_map.modules.as_mut(),
|
||||
module_id,
|
||||
self.module_id,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (name, macs) in source.scope.legacy_macros() {
|
||||
|
|
|
@ -135,10 +135,7 @@ impl Path {
|
|||
|
||||
pub fn segments(&self) -> PathSegments<'_> {
|
||||
let Path::Normal { mod_path, generic_args, .. } = self else {
|
||||
return PathSegments {
|
||||
segments: &[],
|
||||
generic_args: None,
|
||||
};
|
||||
return PathSegments { segments: &[], generic_args: None };
|
||||
};
|
||||
let s =
|
||||
PathSegments { segments: mod_path.segments(), generic_args: generic_args.as_deref() };
|
||||
|
|
|
@ -74,8 +74,8 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
|
|||
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
|
||||
Some(trait_ref) => {
|
||||
let Path::Normal { mod_path, generic_args: path_generic_args, .. } =
|
||||
Path::from_src(trait_ref.path()?, ctx)? else
|
||||
{
|
||||
Path::from_src(trait_ref.path()?, ctx)?
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let num_segments = mod_path.segments().len();
|
||||
|
|
|
@ -692,7 +692,7 @@ pub(crate) fn include_arg_to_tt(
|
|||
arg_id: MacroCallId,
|
||||
) -> Result<(triomphe::Arc<(::tt::Subtree<::tt::TokenId>, TokenMap)>, FileId), ExpandError> {
|
||||
let loc = db.lookup_intern_macro_call(arg_id);
|
||||
let Some(EagerCallInfo {arg, arg_id: Some(arg_id), .. }) = loc.eager.as_deref() else {
|
||||
let Some(EagerCallInfo { arg, arg_id: Some(arg_id), .. }) = loc.eager.as_deref() else {
|
||||
panic!("include_arg_to_tt called on non include macro call: {:?}", &loc.eager);
|
||||
};
|
||||
let path = parse_string(&arg.0)?;
|
||||
|
|
|
@ -471,17 +471,13 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
|
|||
};
|
||||
let Some(macro_arg) = db.macro_arg(id) else {
|
||||
return ExpandResult {
|
||||
value: Arc::new(
|
||||
tt::Subtree {
|
||||
delimiter: tt::Delimiter::UNSPECIFIED,
|
||||
token_trees: Vec::new(),
|
||||
},
|
||||
),
|
||||
value: Arc::new(tt::Subtree {
|
||||
delimiter: tt::Delimiter::UNSPECIFIED,
|
||||
token_trees: Vec::new(),
|
||||
}),
|
||||
// FIXME: We should make sure to enforce an invariant that invalid macro
|
||||
// calls do not reach this call path!
|
||||
err: Some(ExpandError::other(
|
||||
"invalid token tree"
|
||||
)),
|
||||
err: Some(ExpandError::other("invalid token tree")),
|
||||
};
|
||||
};
|
||||
let (arg_tt, arg_tm, undo_info) = &*macro_arg;
|
||||
|
@ -510,9 +506,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
|
|||
delimiter: tt::Delimiter::UNSPECIFIED,
|
||||
token_trees: Vec::new(),
|
||||
}),
|
||||
err: Some(ExpandError::other(
|
||||
"invalid token tree"
|
||||
)),
|
||||
err: Some(ExpandError::other("invalid token tree")),
|
||||
};
|
||||
};
|
||||
let (arg_tt, arg_tm, undo_info) = &*macro_arg;
|
||||
|
|
|
@ -42,10 +42,9 @@ pub fn expand_eager_macro_input(
|
|||
let token_tree = macro_call.value.token_tree();
|
||||
|
||||
let Some(token_tree) = token_tree else {
|
||||
return Ok(ExpandResult { value: None, err:
|
||||
Some(ExpandError::other(
|
||||
"invalid token tree"
|
||||
)),
|
||||
return Ok(ExpandResult {
|
||||
value: None,
|
||||
err: Some(ExpandError::other("invalid token tree")),
|
||||
});
|
||||
};
|
||||
let (parsed_args, arg_token_map) = mbe::syntax_node_to_token_tree(token_tree.syntax());
|
||||
|
@ -85,7 +84,7 @@ pub fn expand_eager_macro_input(
|
|||
resolver,
|
||||
)?;
|
||||
let Some(expanded_eager_input) = expanded_eager_input else {
|
||||
return Ok(ExpandResult { value: None, err })
|
||||
return Ok(ExpandResult { value: None, err });
|
||||
};
|
||||
let (mut subtree, token_map) = mbe::syntax_node_to_token_tree(&expanded_eager_input);
|
||||
subtree.delimiter = crate::tt::Delimiter::unspecified();
|
||||
|
|
|
@ -343,7 +343,8 @@ impl TyExt for Ty {
|
|||
|
||||
fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool {
|
||||
let crate_id = owner.module(db.upcast()).krate();
|
||||
let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|x| x.as_trait()) else {
|
||||
let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|x| x.as_trait())
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build();
|
||||
|
|
|
@ -636,7 +636,8 @@ fn render_const_scalar(
|
|||
}
|
||||
hir_def::AdtId::EnumId(e) => {
|
||||
let Some((var_id, var_layout)) =
|
||||
detect_variant_from_bytes(&layout, f.db, krate, b, e) else {
|
||||
detect_variant_from_bytes(&layout, f.db, krate, b, e)
|
||||
else {
|
||||
return f.write_str("<failed-to-detect-variant>");
|
||||
};
|
||||
let data = &f.db.enum_data(e).variants[var_id];
|
||||
|
|
|
@ -1232,7 +1232,9 @@ impl<'a> InferenceContext<'a> {
|
|||
.as_function()?
|
||||
.lookup(self.db.upcast())
|
||||
.container
|
||||
else { return None };
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
self.resolve_output_on(trait_)
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,9 @@ pub fn layout_of_ty_query(
|
|||
ty: Ty,
|
||||
krate: CrateId,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
|
||||
let Some(target) = db.target_data_layout(krate) else {
|
||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||
};
|
||||
let cx = LayoutCx { krate, target: &target };
|
||||
let dl = &*cx.current_data_layout();
|
||||
let trait_env = Arc::new(TraitEnvironment::empty(krate));
|
||||
|
|
|
@ -31,7 +31,9 @@ pub fn layout_of_adt_query(
|
|||
subst: Substitution,
|
||||
krate: CrateId,
|
||||
) -> Result<Arc<Layout>, LayoutError> {
|
||||
let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
|
||||
let Some(target) = db.target_data_layout(krate) else {
|
||||
return Err(LayoutError::TargetLayoutNotAvailable);
|
||||
};
|
||||
let cx = LayoutCx { krate, target: &target };
|
||||
let dl = cx.current_data_layout();
|
||||
let handle_variant = |def: VariantId, var: &VariantData| {
|
||||
|
|
|
@ -689,7 +689,7 @@ pub fn lookup_impl_method(
|
|||
fn_subst: Substitution,
|
||||
) -> (FunctionId, Substitution) {
|
||||
let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
|
||||
return (func, fn_subst)
|
||||
return (func, fn_subst);
|
||||
};
|
||||
let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
|
||||
let fn_params = fn_subst.len(Interner) - trait_params;
|
||||
|
@ -699,8 +699,8 @@ pub fn lookup_impl_method(
|
|||
};
|
||||
|
||||
let name = &db.function_data(func).name;
|
||||
let Some((impl_fn, impl_subst)) = lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name)
|
||||
.and_then(|assoc| {
|
||||
let Some((impl_fn, impl_subst)) =
|
||||
lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name).and_then(|assoc| {
|
||||
if let (AssocItemId::FunctionId(id), subst) = assoc {
|
||||
Some((id, subst))
|
||||
} else {
|
||||
|
|
|
@ -271,7 +271,10 @@ fn ever_initialized_map(
|
|||
}
|
||||
}
|
||||
let Some(terminator) = &block.terminator else {
|
||||
never!("Terminator should be none only in construction.\nThe body:\n{}", body.pretty_print(db));
|
||||
never!(
|
||||
"Terminator should be none only in construction.\nThe body:\n{}",
|
||||
body.pretty_print(db)
|
||||
);
|
||||
return;
|
||||
};
|
||||
let targets = match &terminator.kind {
|
||||
|
|
|
@ -1226,8 +1226,8 @@ impl Evaluator<'_> {
|
|||
}
|
||||
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||
let Some(target_data_layout) = self.db.target_data_layout(self.crate_id) else {
|
||||
not_supported!("missing target data layout");
|
||||
};
|
||||
not_supported!("missing target data layout");
|
||||
};
|
||||
let size = tag.size(&*target_data_layout).bytes_usize();
|
||||
let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field
|
||||
match tag_encoding {
|
||||
|
@ -1344,7 +1344,9 @@ impl Evaluator<'_> {
|
|||
AdtId::UnionId(_) => not_supported!("unsizing unions"),
|
||||
AdtId::EnumId(_) => not_supported!("unsizing enums"),
|
||||
};
|
||||
let Some((last_field, _)) = self.db.struct_data(id).variant_data.fields().iter().rev().next() else {
|
||||
let Some((last_field, _)) =
|
||||
self.db.struct_data(id).variant_data.fields().iter().rev().next()
|
||||
else {
|
||||
not_supported!("unsizing struct without field");
|
||||
};
|
||||
let target_last_field = self.db.field_types(id.into())[last_field]
|
||||
|
|
|
@ -327,7 +327,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"pthread_getspecific" => {
|
||||
let Some(arg0) = args.get(0) else {
|
||||
return Err(MirEvalError::TypeError("pthread_getspecific arg0 is not provided"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"pthread_getspecific arg0 is not provided",
|
||||
));
|
||||
};
|
||||
let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]);
|
||||
let value = self.thread_local_storage.get_key(key)?;
|
||||
|
@ -336,11 +338,15 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"pthread_setspecific" => {
|
||||
let Some(arg0) = args.get(0) else {
|
||||
return Err(MirEvalError::TypeError("pthread_setspecific arg0 is not provided"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"pthread_setspecific arg0 is not provided",
|
||||
));
|
||||
};
|
||||
let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]);
|
||||
let Some(arg1) = args.get(1) else {
|
||||
return Err(MirEvalError::TypeError("pthread_setspecific arg1 is not provided"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"pthread_setspecific arg1 is not provided",
|
||||
));
|
||||
};
|
||||
let value = from_bytes!(u128, pad16(arg1.get(self)?, false));
|
||||
self.thread_local_storage.set_key(key, value)?;
|
||||
|
@ -390,7 +396,9 @@ impl Evaluator<'_> {
|
|||
"sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs"
|
||||
| "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => {
|
||||
let [arg] = args else {
|
||||
return Err(MirEvalError::TypeError("f64 intrinsic signature doesn't match fn (f64) -> f64"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"f64 intrinsic signature doesn't match fn (f64) -> f64",
|
||||
));
|
||||
};
|
||||
let arg = from_bytes!(f64, arg.get(self)?);
|
||||
match name {
|
||||
|
@ -416,7 +424,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"pow" | "minnum" | "maxnum" | "copysign" => {
|
||||
let [arg1, arg2] = args else {
|
||||
return Err(MirEvalError::TypeError("f64 intrinsic signature doesn't match fn (f64, f64) -> f64"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"f64 intrinsic signature doesn't match fn (f64, f64) -> f64",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f64, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(f64, arg2.get(self)?);
|
||||
|
@ -430,7 +440,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"powi" => {
|
||||
let [arg1, arg2] = args else {
|
||||
return Err(MirEvalError::TypeError("powif64 signature doesn't match fn (f64, i32) -> f64"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"powif64 signature doesn't match fn (f64, i32) -> f64",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f64, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(i32, arg2.get(self)?);
|
||||
|
@ -438,7 +450,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"fma" => {
|
||||
let [arg1, arg2, arg3] = args else {
|
||||
return Err(MirEvalError::TypeError("fmaf64 signature doesn't match fn (f64, f64, f64) -> f64"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"fmaf64 signature doesn't match fn (f64, f64, f64) -> f64",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f64, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(f64, arg2.get(self)?);
|
||||
|
@ -454,7 +468,9 @@ impl Evaluator<'_> {
|
|||
"sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs"
|
||||
| "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => {
|
||||
let [arg] = args else {
|
||||
return Err(MirEvalError::TypeError("f32 intrinsic signature doesn't match fn (f32) -> f32"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"f32 intrinsic signature doesn't match fn (f32) -> f32",
|
||||
));
|
||||
};
|
||||
let arg = from_bytes!(f32, arg.get(self)?);
|
||||
match name {
|
||||
|
@ -480,7 +496,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"pow" | "minnum" | "maxnum" | "copysign" => {
|
||||
let [arg1, arg2] = args else {
|
||||
return Err(MirEvalError::TypeError("f32 intrinsic signature doesn't match fn (f32, f32) -> f32"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"f32 intrinsic signature doesn't match fn (f32, f32) -> f32",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f32, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(f32, arg2.get(self)?);
|
||||
|
@ -494,7 +512,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"powi" => {
|
||||
let [arg1, arg2] = args else {
|
||||
return Err(MirEvalError::TypeError("powif32 signature doesn't match fn (f32, i32) -> f32"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"powif32 signature doesn't match fn (f32, i32) -> f32",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f32, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(i32, arg2.get(self)?);
|
||||
|
@ -502,7 +522,9 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"fma" => {
|
||||
let [arg1, arg2, arg3] = args else {
|
||||
return Err(MirEvalError::TypeError("fmaf32 signature doesn't match fn (f32, f32, f32) -> f32"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"fmaf32 signature doesn't match fn (f32, f32, f32) -> f32",
|
||||
));
|
||||
};
|
||||
let arg1 = from_bytes!(f32, arg1.get(self)?);
|
||||
let arg2 = from_bytes!(f32, arg2.get(self)?);
|
||||
|
@ -515,14 +537,16 @@ impl Evaluator<'_> {
|
|||
}
|
||||
match name {
|
||||
"size_of" => {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
|
||||
};
|
||||
let size = self.size_of_sized(ty, locals, "size_of arg")?;
|
||||
destination.write_from_bytes(self, &size.to_le_bytes()[0..destination.size])
|
||||
}
|
||||
"size_of_val" => {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("size_of_val generic arg is not provided"));
|
||||
};
|
||||
let [arg] = args else {
|
||||
|
@ -549,14 +573,16 @@ impl Evaluator<'_> {
|
|||
destination.write_from_bytes(self, &size.to_le_bytes())
|
||||
}
|
||||
"min_align_of" | "pref_align_of" => {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("align_of generic arg is not provided"));
|
||||
};
|
||||
let align = self.layout(ty)?.align.abi.bytes();
|
||||
destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size])
|
||||
}
|
||||
"needs_drop" => {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
|
||||
};
|
||||
let result = !ty.clone().is_copy(self.db, locals.body.owner);
|
||||
|
@ -697,10 +723,15 @@ impl Evaluator<'_> {
|
|||
}
|
||||
"copy" | "copy_nonoverlapping" => {
|
||||
let [src, dst, offset] = args else {
|
||||
return Err(MirEvalError::TypeError("copy_nonoverlapping args are not provided"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"copy_nonoverlapping args are not provided",
|
||||
));
|
||||
};
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
return Err(MirEvalError::TypeError("copy_nonoverlapping generic arg is not provided"));
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"copy_nonoverlapping generic arg is not provided",
|
||||
));
|
||||
};
|
||||
let src = Address::from_bytes(src.get(self)?)?;
|
||||
let dst = Address::from_bytes(dst.get(self)?)?;
|
||||
|
@ -715,7 +746,8 @@ impl Evaluator<'_> {
|
|||
let [ptr, offset] = args else {
|
||||
return Err(MirEvalError::TypeError("offset args are not provided"));
|
||||
};
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("offset generic arg is not provided"));
|
||||
};
|
||||
let ptr = u128::from_le_bytes(pad16(ptr.get(self)?, false));
|
||||
|
@ -824,8 +856,11 @@ impl Evaluator<'_> {
|
|||
let [arg] = args else {
|
||||
return Err(MirEvalError::TypeError("discriminant_value arg is not provided"));
|
||||
};
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner)) else {
|
||||
return Err(MirEvalError::TypeError("discriminant_value generic arg is not provided"));
|
||||
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|x| x.ty(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"discriminant_value generic arg is not provided",
|
||||
));
|
||||
};
|
||||
let addr = Address::from_bytes(arg.get(self)?)?;
|
||||
let size = self.size_of_sized(ty, locals, "discriminant_value ptr type")?;
|
||||
|
|
|
@ -23,7 +23,8 @@ impl Evaluator<'_> {
|
|||
fn detect_simd_ty(&self, ty: &Ty) -> Result<usize> {
|
||||
match ty.kind(Interner) {
|
||||
TyKind::Adt(_, subst) => {
|
||||
let Some(len) = subst.as_slice(Interner).get(1).and_then(|x| x.constant(Interner)) else {
|
||||
let Some(len) = subst.as_slice(Interner).get(1).and_then(|x| x.constant(Interner))
|
||||
else {
|
||||
return Err(MirEvalError::TypeError("simd type without len param"));
|
||||
};
|
||||
match try_const_usize(self.db, len) {
|
||||
|
@ -89,7 +90,9 @@ impl Evaluator<'_> {
|
|||
return Err(MirEvalError::TypeError("simd_shuffle args are not provided"));
|
||||
};
|
||||
let TyKind::Array(_, index_len) = index.ty.kind(Interner) else {
|
||||
return Err(MirEvalError::TypeError("simd_shuffle index argument has non-array type"));
|
||||
return Err(MirEvalError::TypeError(
|
||||
"simd_shuffle index argument has non-array type",
|
||||
));
|
||||
};
|
||||
let index_len = match try_const_usize(self.db, index_len) {
|
||||
Some(x) => x as usize,
|
||||
|
|
|
@ -310,24 +310,30 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
self.lower_expr_to_place_with_adjust(expr_id, temp.into(), current, rest)
|
||||
}
|
||||
Adjust::Deref(_) => {
|
||||
let Some((p, current)) = self.lower_expr_as_place_with_adjust(current, expr_id, true, adjustments)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((p, current)) =
|
||||
self.lower_expr_as_place_with_adjust(current, expr_id, true, adjustments)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
|
||||
Ok(Some(current))
|
||||
}
|
||||
Adjust::Borrow(AutoBorrow::Ref(m) | AutoBorrow::RawPtr(m)) => {
|
||||
let Some((p, current)) = self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((p, current)) =
|
||||
self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let bk = BorrowKind::from_chalk(*m);
|
||||
self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into());
|
||||
Ok(Some(current))
|
||||
}
|
||||
Adjust::Pointer(cast) => {
|
||||
let Some((p, current)) = self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((p, current)) =
|
||||
self.lower_expr_as_place_with_adjust(current, expr_id, true, rest)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(
|
||||
current,
|
||||
place,
|
||||
|
@ -373,45 +379,49 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
}
|
||||
Err(MirLowerError::IncompleteExpr)
|
||||
},
|
||||
}
|
||||
Expr::Path(p) => {
|
||||
let pr = if let Some((assoc, subst)) = self
|
||||
.infer
|
||||
.assoc_resolutions_for_expr(expr_id)
|
||||
{
|
||||
match assoc {
|
||||
hir_def::AssocItemId::ConstId(c) => {
|
||||
self.lower_const(c.into(), current, place, subst, expr_id.into(), self.expr_ty_without_adjust(expr_id))?;
|
||||
return Ok(Some(current))
|
||||
},
|
||||
hir_def::AssocItemId::FunctionId(_) => {
|
||||
// FnDefs are zero sized, no action is needed.
|
||||
return Ok(Some(current))
|
||||
let pr =
|
||||
if let Some((assoc, subst)) = self.infer.assoc_resolutions_for_expr(expr_id) {
|
||||
match assoc {
|
||||
hir_def::AssocItemId::ConstId(c) => {
|
||||
self.lower_const(
|
||||
c.into(),
|
||||
current,
|
||||
place,
|
||||
subst,
|
||||
expr_id.into(),
|
||||
self.expr_ty_without_adjust(expr_id),
|
||||
)?;
|
||||
return Ok(Some(current));
|
||||
}
|
||||
hir_def::AssocItemId::FunctionId(_) => {
|
||||
// FnDefs are zero sized, no action is needed.
|
||||
return Ok(Some(current));
|
||||
}
|
||||
hir_def::AssocItemId::TypeAliasId(_) => {
|
||||
// FIXME: If it is unreachable, use proper error instead of `not_supported`.
|
||||
not_supported!("associated functions and types")
|
||||
}
|
||||
}
|
||||
hir_def::AssocItemId::TypeAliasId(_) => {
|
||||
// FIXME: If it is unreachable, use proper error instead of `not_supported`.
|
||||
not_supported!("associated functions and types")
|
||||
},
|
||||
}
|
||||
} else if let Some(variant) = self
|
||||
.infer
|
||||
.variant_resolution_for_expr(expr_id)
|
||||
{
|
||||
match variant {
|
||||
VariantId::EnumVariantId(e) => ValueNs::EnumVariantId(e),
|
||||
VariantId::StructId(s) => ValueNs::StructId(s),
|
||||
VariantId::UnionId(_) => implementation_error!("Union variant as path"),
|
||||
}
|
||||
} else {
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, p);
|
||||
let resolver = resolver_for_expr(self.db.upcast(), self.owner, expr_id);
|
||||
resolver
|
||||
.resolve_path_in_value_ns_fully(self.db.upcast(), p)
|
||||
.ok_or_else(unresolved_name)?
|
||||
};
|
||||
} else if let Some(variant) = self.infer.variant_resolution_for_expr(expr_id) {
|
||||
match variant {
|
||||
VariantId::EnumVariantId(e) => ValueNs::EnumVariantId(e),
|
||||
VariantId::StructId(s) => ValueNs::StructId(s),
|
||||
VariantId::UnionId(_) => implementation_error!("Union variant as path"),
|
||||
}
|
||||
} else {
|
||||
let unresolved_name = || MirLowerError::unresolved_path(self.db, p);
|
||||
let resolver = resolver_for_expr(self.db.upcast(), self.owner, expr_id);
|
||||
resolver
|
||||
.resolve_path_in_value_ns_fully(self.db.upcast(), p)
|
||||
.ok_or_else(unresolved_name)?
|
||||
};
|
||||
match pr {
|
||||
ValueNs::LocalBinding(_) | ValueNs::StaticId(_) => {
|
||||
let Some((temp, current)) = self.lower_expr_as_place_without_adjust(current, expr_id, false)? else {
|
||||
let Some((temp, current)) =
|
||||
self.lower_expr_as_place_without_adjust(current, expr_id, false)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(
|
||||
|
@ -423,11 +433,19 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Ok(Some(current))
|
||||
}
|
||||
ValueNs::ConstId(const_id) => {
|
||||
self.lower_const(const_id.into(), current, place, Substitution::empty(Interner), expr_id.into(), self.expr_ty_without_adjust(expr_id))?;
|
||||
self.lower_const(
|
||||
const_id.into(),
|
||||
current,
|
||||
place,
|
||||
Substitution::empty(Interner),
|
||||
expr_id.into(),
|
||||
self.expr_ty_without_adjust(expr_id),
|
||||
)?;
|
||||
Ok(Some(current))
|
||||
}
|
||||
ValueNs::EnumVariantId(variant_id) => {
|
||||
let variant_data = &self.db.enum_data(variant_id.parent).variants[variant_id.local_id];
|
||||
let variant_data =
|
||||
&self.db.enum_data(variant_id.parent).variants[variant_id.local_id];
|
||||
if variant_data.variant_data.kind() == StructKind::Unit {
|
||||
let ty = self.infer.type_of_expr[expr_id].clone();
|
||||
current = self.lower_enum_variant(
|
||||
|
@ -478,7 +496,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
}
|
||||
Expr::If { condition, then_branch, else_branch } => {
|
||||
let Some((discr, current)) = self.lower_expr_to_some_operand(*condition, current)? else {
|
||||
let Some((discr, current)) =
|
||||
self.lower_expr_to_some_operand(*condition, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let start_of_then = self.new_basic_block();
|
||||
|
@ -501,15 +521,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Ok(self.merge_blocks(end_of_then, end_of_else, expr_id.into()))
|
||||
}
|
||||
Expr::Let { pat, expr } => {
|
||||
let Some((cond_place, current)) = self.lower_expr_as_place(current, *expr, true)? else {
|
||||
let Some((cond_place, current)) = self.lower_expr_as_place(current, *expr, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let (then_target, else_target) = self.pattern_match(
|
||||
current,
|
||||
None,
|
||||
cond_place,
|
||||
*pat,
|
||||
)?;
|
||||
let (then_target, else_target) =
|
||||
self.pattern_match(current, None, cond_place, *pat)?;
|
||||
self.write_bytes_to_place(
|
||||
then_target,
|
||||
place.clone(),
|
||||
|
@ -533,31 +550,47 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
Expr::Block { id: _, statements, tail, label } => {
|
||||
if let Some(label) = label {
|
||||
self.lower_loop(current, place.clone(), Some(*label), expr_id.into(), |this, begin| {
|
||||
if let Some(current) = this.lower_block_to_place(statements, begin, *tail, place, expr_id.into())? {
|
||||
let end = this.current_loop_end()?;
|
||||
this.set_goto(current, end, expr_id.into());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
self.lower_loop(
|
||||
current,
|
||||
place.clone(),
|
||||
Some(*label),
|
||||
expr_id.into(),
|
||||
|this, begin| {
|
||||
if let Some(current) = this.lower_block_to_place(
|
||||
statements,
|
||||
begin,
|
||||
*tail,
|
||||
place,
|
||||
expr_id.into(),
|
||||
)? {
|
||||
let end = this.current_loop_end()?;
|
||||
this.set_goto(current, end, expr_id.into());
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
} else {
|
||||
self.lower_block_to_place(statements, current, *tail, place, expr_id.into())
|
||||
}
|
||||
}
|
||||
Expr::Loop { body, label } => self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
|
||||
let scope = this.push_drop_scope();
|
||||
if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? {
|
||||
current = scope.pop_and_drop(this, current);
|
||||
this.set_goto(current, begin, expr_id.into());
|
||||
} else {
|
||||
scope.pop_assume_dropped(this);
|
||||
}
|
||||
Ok(())
|
||||
}),
|
||||
Expr::While { condition, body, label } => {
|
||||
self.lower_loop(current, place, *label, expr_id.into(),|this, begin| {
|
||||
Expr::Loop { body, label } => {
|
||||
self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
|
||||
let scope = this.push_drop_scope();
|
||||
let Some((discr, to_switch)) = this.lower_expr_to_some_operand(*condition, begin)? else {
|
||||
if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? {
|
||||
current = scope.pop_and_drop(this, current);
|
||||
this.set_goto(current, begin, expr_id.into());
|
||||
} else {
|
||||
scope.pop_assume_dropped(this);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
Expr::While { condition, body, label } => {
|
||||
self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
|
||||
let scope = this.push_drop_scope();
|
||||
let Some((discr, to_switch)) =
|
||||
this.lower_expr_to_some_operand(*condition, begin)?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let fail_cond = this.new_basic_block();
|
||||
|
@ -583,8 +616,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
})
|
||||
}
|
||||
Expr::Call { callee, args, .. } => {
|
||||
if let Some((func_id, generic_args)) =
|
||||
self.infer.method_resolution(expr_id) {
|
||||
if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) {
|
||||
let ty = chalk_ir::TyKind::FnDef(
|
||||
CallableDefId::FunctionId(func_id).to_chalk(self.db),
|
||||
generic_args,
|
||||
|
@ -604,21 +636,43 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
match &callee_ty.data(Interner).kind {
|
||||
chalk_ir::TyKind::FnDef(..) => {
|
||||
let func = Operand::from_bytes(vec![], callee_ty.clone());
|
||||
self.lower_call_and_args(func, args.iter().copied(), place, current, self.is_uninhabited(expr_id), expr_id.into())
|
||||
self.lower_call_and_args(
|
||||
func,
|
||||
args.iter().copied(),
|
||||
place,
|
||||
current,
|
||||
self.is_uninhabited(expr_id),
|
||||
expr_id.into(),
|
||||
)
|
||||
}
|
||||
chalk_ir::TyKind::Function(_) => {
|
||||
let Some((func, current)) = self.lower_expr_to_some_operand(*callee, current)? else {
|
||||
let Some((func, current)) =
|
||||
self.lower_expr_to_some_operand(*callee, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.lower_call_and_args(func, args.iter().copied(), place, current, self.is_uninhabited(expr_id), expr_id.into())
|
||||
self.lower_call_and_args(
|
||||
func,
|
||||
args.iter().copied(),
|
||||
place,
|
||||
current,
|
||||
self.is_uninhabited(expr_id),
|
||||
expr_id.into(),
|
||||
)
|
||||
}
|
||||
TyKind::Error => {
|
||||
return Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id))
|
||||
}
|
||||
TyKind::Error => return Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id)),
|
||||
_ => return Err(MirLowerError::TypeError("function call on bad type")),
|
||||
}
|
||||
}
|
||||
Expr::MethodCall { receiver, args, method_name, .. } => {
|
||||
let (func_id, generic_args) =
|
||||
self.infer.method_resolution(expr_id).ok_or_else(|| MirLowerError::UnresolvedMethod(method_name.display(self.db.upcast()).to_string()))?;
|
||||
self.infer.method_resolution(expr_id).ok_or_else(|| {
|
||||
MirLowerError::UnresolvedMethod(
|
||||
method_name.display(self.db.upcast()).to_string(),
|
||||
)
|
||||
})?;
|
||||
let func = Operand::from_fn(self.db, func_id, generic_args);
|
||||
self.lower_call_and_args(
|
||||
func,
|
||||
|
@ -630,23 +684,27 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
)
|
||||
}
|
||||
Expr::Match { expr, arms } => {
|
||||
let Some((cond_place, mut current)) = self.lower_expr_as_place(current, *expr, true)?
|
||||
let Some((cond_place, mut current)) =
|
||||
self.lower_expr_as_place(current, *expr, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let mut end = None;
|
||||
for MatchArm { pat, guard, expr } in arms.iter() {
|
||||
let (then, mut otherwise) = self.pattern_match(
|
||||
current,
|
||||
None,
|
||||
cond_place.clone(),
|
||||
*pat,
|
||||
)?;
|
||||
let (then, mut otherwise) =
|
||||
self.pattern_match(current, None, cond_place.clone(), *pat)?;
|
||||
let then = if let &Some(guard) = guard {
|
||||
let next = self.new_basic_block();
|
||||
let o = otherwise.get_or_insert_with(|| self.new_basic_block());
|
||||
if let Some((discr, c)) = self.lower_expr_to_some_operand(guard, then)? {
|
||||
self.set_terminator(c, TerminatorKind::SwitchInt { discr, targets: SwitchTargets::static_if(1, next, *o) }, expr_id.into());
|
||||
self.set_terminator(
|
||||
c,
|
||||
TerminatorKind::SwitchInt {
|
||||
discr,
|
||||
targets: SwitchTargets::static_if(1, next, *o),
|
||||
},
|
||||
expr_id.into(),
|
||||
);
|
||||
}
|
||||
next
|
||||
} else {
|
||||
|
@ -672,33 +730,53 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
Expr::Continue { label } => {
|
||||
let loop_data = match label {
|
||||
Some(l) => self.labeled_loop_blocks.get(l).ok_or(MirLowerError::UnresolvedLabel)?,
|
||||
None => self.current_loop_blocks.as_ref().ok_or(MirLowerError::ContinueWithoutLoop)?,
|
||||
Some(l) => {
|
||||
self.labeled_loop_blocks.get(l).ok_or(MirLowerError::UnresolvedLabel)?
|
||||
}
|
||||
None => self
|
||||
.current_loop_blocks
|
||||
.as_ref()
|
||||
.ok_or(MirLowerError::ContinueWithoutLoop)?,
|
||||
};
|
||||
let begin = loop_data.begin;
|
||||
current = self.drop_until_scope(loop_data.drop_scope_index, current);
|
||||
self.set_goto(current, begin, expr_id.into());
|
||||
Ok(None)
|
||||
},
|
||||
}
|
||||
&Expr::Break { expr, label } => {
|
||||
if let Some(expr) = expr {
|
||||
let loop_data = match label {
|
||||
Some(l) => self.labeled_loop_blocks.get(&l).ok_or(MirLowerError::UnresolvedLabel)?,
|
||||
None => self.current_loop_blocks.as_ref().ok_or(MirLowerError::BreakWithoutLoop)?,
|
||||
Some(l) => self
|
||||
.labeled_loop_blocks
|
||||
.get(&l)
|
||||
.ok_or(MirLowerError::UnresolvedLabel)?,
|
||||
None => self
|
||||
.current_loop_blocks
|
||||
.as_ref()
|
||||
.ok_or(MirLowerError::BreakWithoutLoop)?,
|
||||
};
|
||||
let Some(c) = self.lower_expr_to_place(expr, loop_data.place.clone(), current)? else {
|
||||
let Some(c) =
|
||||
self.lower_expr_to_place(expr, loop_data.place.clone(), current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
}
|
||||
let (end, drop_scope) = match label {
|
||||
Some(l) => {
|
||||
let loop_blocks = self.labeled_loop_blocks.get(&l).ok_or(MirLowerError::UnresolvedLabel)?;
|
||||
(loop_blocks.end.expect("We always generate end for labeled loops"), loop_blocks.drop_scope_index)
|
||||
},
|
||||
None => {
|
||||
(self.current_loop_end()?, self.current_loop_blocks.as_ref().unwrap().drop_scope_index)
|
||||
},
|
||||
let loop_blocks = self
|
||||
.labeled_loop_blocks
|
||||
.get(&l)
|
||||
.ok_or(MirLowerError::UnresolvedLabel)?;
|
||||
(
|
||||
loop_blocks.end.expect("We always generate end for labeled loops"),
|
||||
loop_blocks.drop_scope_index,
|
||||
)
|
||||
}
|
||||
None => (
|
||||
self.current_loop_end()?,
|
||||
self.current_loop_blocks.as_ref().unwrap().drop_scope_index,
|
||||
),
|
||||
};
|
||||
current = self.drop_until_scope(drop_scope, current);
|
||||
self.set_goto(current, end, expr_id.into());
|
||||
|
@ -706,7 +784,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
Expr::Return { expr } => {
|
||||
if let Some(expr) = expr {
|
||||
if let Some(c) = self.lower_expr_to_place(*expr, return_slot().into(), current)? {
|
||||
if let Some(c) =
|
||||
self.lower_expr_to_place(*expr, return_slot().into(), current)?
|
||||
{
|
||||
current = c;
|
||||
} else {
|
||||
return Ok(None);
|
||||
|
@ -725,13 +805,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
};
|
||||
current = c;
|
||||
Some(p)
|
||||
},
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let variant_id = self
|
||||
.infer
|
||||
.variant_resolution_for_expr(expr_id)
|
||||
.ok_or_else(|| match path {
|
||||
let variant_id =
|
||||
self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path {
|
||||
Some(p) => MirLowerError::UnresolvedName(p.display(self.db).to_string()),
|
||||
None => MirLowerError::RecordLiteralWithoutPath,
|
||||
})?;
|
||||
|
@ -746,7 +824,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
for RecordLitField { name, expr } in fields.iter() {
|
||||
let field_id =
|
||||
variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
|
||||
let Some((op, c)) = self.lower_expr_to_some_operand(*expr, current)? else {
|
||||
let Some((op, c)) = self.lower_expr_to_some_operand(*expr, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
|
@ -758,18 +837,23 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Rvalue::Aggregate(
|
||||
AggregateKind::Adt(variant_id, subst),
|
||||
match spread_place {
|
||||
Some(sp) => operands.into_iter().enumerate().map(|(i, x)| {
|
||||
match x {
|
||||
Some(sp) => operands
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| match x {
|
||||
Some(x) => x,
|
||||
None => {
|
||||
let p = sp.project(ProjectionElem::Field(FieldId {
|
||||
parent: variant_id,
|
||||
local_id: LocalFieldId::from_raw(RawIdx::from(i as u32)),
|
||||
}));
|
||||
let p =
|
||||
sp.project(ProjectionElem::Field(FieldId {
|
||||
parent: variant_id,
|
||||
local_id: LocalFieldId::from_raw(
|
||||
RawIdx::from(i as u32),
|
||||
),
|
||||
}));
|
||||
Operand::Copy(p)
|
||||
},
|
||||
}
|
||||
}).collect(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
None => operands.into_iter().collect::<Option<_>>().ok_or(
|
||||
MirLowerError::TypeError("missing field in record literal"),
|
||||
)?,
|
||||
|
@ -785,7 +869,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
};
|
||||
let local_id =
|
||||
variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
|
||||
let place = place.project(PlaceElem::Field(FieldId { parent: union_id.into(), local_id }));
|
||||
let place = place.project(PlaceElem::Field(FieldId {
|
||||
parent: union_id.into(),
|
||||
local_id,
|
||||
}));
|
||||
self.lower_expr_to_place(*expr, place, current)
|
||||
}
|
||||
}
|
||||
|
@ -795,9 +882,16 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Expr::Async { .. } => not_supported!("async block"),
|
||||
&Expr::Const(id) => {
|
||||
let subst = self.placeholder_subst();
|
||||
self.lower_const(id.into(), current, place, subst, expr_id.into(), self.expr_ty_without_adjust(expr_id))?;
|
||||
self.lower_const(
|
||||
id.into(),
|
||||
current,
|
||||
place,
|
||||
subst,
|
||||
expr_id.into(),
|
||||
self.expr_ty_without_adjust(expr_id),
|
||||
)?;
|
||||
Ok(Some(current))
|
||||
},
|
||||
}
|
||||
Expr::Cast { expr, type_ref: _ } => {
|
||||
let Some((x, current)) = self.lower_expr_to_some_operand(*expr, current)? else {
|
||||
return Ok(None);
|
||||
|
@ -822,23 +916,37 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
Expr::Box { expr } => {
|
||||
let ty = self.expr_ty_after_adjustments(*expr);
|
||||
self.push_assignment(current, place.clone(), Rvalue::ShallowInitBoxWithAlloc(ty), expr_id.into());
|
||||
let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)? else {
|
||||
self.push_assignment(
|
||||
current,
|
||||
place.clone(),
|
||||
Rvalue::ShallowInitBoxWithAlloc(ty),
|
||||
expr_id.into(),
|
||||
);
|
||||
let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let p = place.project(ProjectionElem::Deref);
|
||||
self.push_assignment(current, p, operand.into(), expr_id.into());
|
||||
Ok(Some(current))
|
||||
},
|
||||
Expr::Field { .. } | Expr::Index { .. } | Expr::UnaryOp { op: hir_def::hir::UnaryOp::Deref, .. } => {
|
||||
let Some((p, current)) = self.lower_expr_as_place_without_adjust(current, expr_id, true)? else {
|
||||
}
|
||||
Expr::Field { .. }
|
||||
| Expr::Index { .. }
|
||||
| Expr::UnaryOp { op: hir_def::hir::UnaryOp::Deref, .. } => {
|
||||
let Some((p, current)) =
|
||||
self.lower_expr_as_place_without_adjust(current, expr_id, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
|
||||
Ok(Some(current))
|
||||
}
|
||||
Expr::UnaryOp { expr, op: op @ (hir_def::hir::UnaryOp::Not | hir_def::hir::UnaryOp::Neg) } => {
|
||||
let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)? else {
|
||||
Expr::UnaryOp {
|
||||
expr,
|
||||
op: op @ (hir_def::hir::UnaryOp::Not | hir_def::hir::UnaryOp::Neg),
|
||||
} => {
|
||||
let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let operation = match op {
|
||||
|
@ -853,7 +961,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
expr_id.into(),
|
||||
);
|
||||
Ok(Some(current))
|
||||
},
|
||||
}
|
||||
Expr::BinaryOp { lhs, rhs, op } => {
|
||||
let op = op.ok_or(MirLowerError::IncompleteExpr)?;
|
||||
let is_builtin = 'b: {
|
||||
|
@ -861,16 +969,19 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
// for binary operator, and use without adjust to simplify our conditions.
|
||||
let lhs_ty = self.expr_ty_without_adjust(*lhs);
|
||||
let rhs_ty = self.expr_ty_without_adjust(*rhs);
|
||||
if matches!(op ,BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. })) {
|
||||
if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. })) {
|
||||
if lhs_ty.as_raw_ptr().is_some() && rhs_ty.as_raw_ptr().is_some() {
|
||||
break 'b true;
|
||||
}
|
||||
}
|
||||
let builtin_inequal_impls = matches!(
|
||||
op,
|
||||
BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) | BinaryOp::Assignment { op: Some(ArithOp::Shl | ArithOp::Shr) }
|
||||
BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr)
|
||||
| BinaryOp::Assignment { op: Some(ArithOp::Shl | ArithOp::Shr) }
|
||||
);
|
||||
lhs_ty.is_scalar() && rhs_ty.is_scalar() && (lhs_ty == rhs_ty || builtin_inequal_impls)
|
||||
lhs_ty.is_scalar()
|
||||
&& rhs_ty.is_scalar()
|
||||
&& (lhs_ty == rhs_ty || builtin_inequal_impls)
|
||||
};
|
||||
if !is_builtin {
|
||||
if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) {
|
||||
|
@ -894,32 +1005,43 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
.get(lhs)
|
||||
.and_then(|x| x.split_last())
|
||||
.map(|x| x.1)
|
||||
.ok_or(MirLowerError::TypeError("adjustment of binary op was missing"))?;
|
||||
.ok_or(MirLowerError::TypeError(
|
||||
"adjustment of binary op was missing",
|
||||
))?;
|
||||
let Some((lhs_place, current)) =
|
||||
self.lower_expr_as_place_with_adjust(current, *lhs, false, adjusts)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((rhs_op, current)) = self.lower_expr_to_some_operand(*rhs, current)? else {
|
||||
let Some((rhs_op, current)) =
|
||||
self.lower_expr_to_some_operand(*rhs, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let r_value = Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place.clone()), rhs_op);
|
||||
let r_value = Rvalue::CheckedBinaryOp(
|
||||
op.into(),
|
||||
Operand::Copy(lhs_place.clone()),
|
||||
rhs_op,
|
||||
);
|
||||
self.push_assignment(current, lhs_place, r_value, expr_id.into());
|
||||
return Ok(Some(current));
|
||||
} else {
|
||||
let Some((lhs_place, current)) =
|
||||
self.lower_expr_as_place(current, *lhs, false)?
|
||||
self.lower_expr_as_place(current, *lhs, false)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((rhs_op, current)) = self.lower_expr_to_some_operand(*rhs, current)? else {
|
||||
let Some((rhs_op, current)) =
|
||||
self.lower_expr_to_some_operand(*rhs, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(current, lhs_place, rhs_op.into(), expr_id.into());
|
||||
return Ok(Some(current));
|
||||
}
|
||||
}
|
||||
let Some((lhs_op, current)) = self.lower_expr_to_some_operand(*lhs, current)? else {
|
||||
let Some((lhs_op, current)) = self.lower_expr_to_some_operand(*lhs, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
if let hir_def::hir::BinaryOp::LogicOp(op) = op {
|
||||
|
@ -928,22 +1050,31 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
syntax::ast::LogicOp::Or => 1,
|
||||
};
|
||||
let start_of_then = self.new_basic_block();
|
||||
self.push_assignment(start_of_then, place.clone(), lhs_op.clone().into(), expr_id.into());
|
||||
self.push_assignment(
|
||||
start_of_then,
|
||||
place.clone(),
|
||||
lhs_op.clone().into(),
|
||||
expr_id.into(),
|
||||
);
|
||||
let end_of_then = Some(start_of_then);
|
||||
let start_of_else = self.new_basic_block();
|
||||
let end_of_else =
|
||||
self.lower_expr_to_place(*rhs, place, start_of_else)?;
|
||||
let end_of_else = self.lower_expr_to_place(*rhs, place, start_of_else)?;
|
||||
self.set_terminator(
|
||||
current,
|
||||
TerminatorKind::SwitchInt {
|
||||
discr: lhs_op,
|
||||
targets: SwitchTargets::static_if(value_to_short, start_of_then, start_of_else),
|
||||
targets: SwitchTargets::static_if(
|
||||
value_to_short,
|
||||
start_of_then,
|
||||
start_of_else,
|
||||
),
|
||||
},
|
||||
expr_id.into(),
|
||||
);
|
||||
return Ok(self.merge_blocks(end_of_then, end_of_else, expr_id.into()));
|
||||
}
|
||||
let Some((rhs_op, current)) = self.lower_expr_to_some_operand(*rhs, current)? else {
|
||||
let Some((rhs_op, current)) = self.lower_expr_to_some_operand(*rhs, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.push_assignment(
|
||||
|
@ -995,20 +1126,28 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
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<_>>()?,
|
||||
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 { .. } => {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
let TyKind::Closure(id, _) = ty.kind(Interner) else {
|
||||
|
@ -1020,22 +1159,33 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
for capture in captures.iter() {
|
||||
let p = Place {
|
||||
local: self.binding_local(capture.place.local)?,
|
||||
projection: capture.place.projections.clone().into_iter().map(|x| {
|
||||
match x {
|
||||
projection: capture
|
||||
.place
|
||||
.projections
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|x| match x {
|
||||
ProjectionElem::Deref => ProjectionElem::Deref,
|
||||
ProjectionElem::Field(x) => ProjectionElem::Field(x),
|
||||
ProjectionElem::TupleOrClosureField(x) => ProjectionElem::TupleOrClosureField(x),
|
||||
ProjectionElem::ConstantIndex { offset, from_end } => ProjectionElem::ConstantIndex { offset, from_end },
|
||||
ProjectionElem::Subslice { from, to } => ProjectionElem::Subslice { from, to },
|
||||
ProjectionElem::TupleOrClosureField(x) => {
|
||||
ProjectionElem::TupleOrClosureField(x)
|
||||
}
|
||||
ProjectionElem::ConstantIndex { offset, from_end } => {
|
||||
ProjectionElem::ConstantIndex { offset, from_end }
|
||||
}
|
||||
ProjectionElem::Subslice { from, to } => {
|
||||
ProjectionElem::Subslice { from, to }
|
||||
}
|
||||
ProjectionElem::OpaqueCast(x) => ProjectionElem::OpaqueCast(x),
|
||||
ProjectionElem::Index(x) => match x { },
|
||||
}
|
||||
}).collect(),
|
||||
ProjectionElem::Index(x) => match x {},
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
match &capture.kind {
|
||||
CaptureKind::ByRef(bk) => {
|
||||
let placeholder_subst = self.placeholder_subst();
|
||||
let tmp_ty = capture.ty.clone().substitute(Interner, &placeholder_subst);
|
||||
let tmp_ty =
|
||||
capture.ty.clone().substitute(Interner, &placeholder_subst);
|
||||
let tmp: Place = self.temp(tmp_ty, current, capture.span)?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
|
@ -1044,7 +1194,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
capture.span,
|
||||
);
|
||||
operands.push(Operand::Move(tmp));
|
||||
},
|
||||
}
|
||||
CaptureKind::ByValue => operands.push(Operand::Move(p)),
|
||||
}
|
||||
}
|
||||
|
@ -1055,18 +1205,18 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
expr_id.into(),
|
||||
);
|
||||
Ok(Some(current))
|
||||
},
|
||||
}
|
||||
Expr::Tuple { exprs, is_assignee_expr: _ } => {
|
||||
let Some(values) = exprs
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let Some((o, c)) = self.lower_expr_to_some_operand(*x, current)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
Ok(Some(o))
|
||||
})
|
||||
.collect::<Result<Option<_>>>()?
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let Some((o, c)) = self.lower_expr_to_some_operand(*x, current)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
Ok(Some(o))
|
||||
})
|
||||
.collect::<Result<Option<_>>>()?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
@ -1088,27 +1238,26 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
}
|
||||
};
|
||||
let Some(values) = elements
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let Some((o, c)) = self.lower_expr_to_some_operand(*x, current)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
Ok(Some(o))
|
||||
})
|
||||
.collect::<Result<Option<_>>>()?
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let Some((o, c)) = self.lower_expr_to_some_operand(*x, current)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
Ok(Some(o))
|
||||
})
|
||||
.collect::<Result<Option<_>>>()?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let r = Rvalue::Aggregate(
|
||||
AggregateKind::Array(elem_ty),
|
||||
values,
|
||||
);
|
||||
let r = Rvalue::Aggregate(AggregateKind::Array(elem_ty), values);
|
||||
self.push_assignment(current, place, r, expr_id.into());
|
||||
Ok(Some(current))
|
||||
}
|
||||
Array::Repeat { initializer, .. } => {
|
||||
let Some((init, current)) = self.lower_expr_to_some_operand(*initializer, current)? else {
|
||||
let Some((init, current)) =
|
||||
self.lower_expr_to_some_operand(*initializer, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let len = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind {
|
||||
|
@ -1122,7 +1271,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
let r = Rvalue::Repeat(init, len);
|
||||
self.push_assignment(current, place, r, expr_id.into());
|
||||
Ok(Some(current))
|
||||
},
|
||||
}
|
||||
},
|
||||
Expr::Literal(l) => {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
|
|
|
@ -18,7 +18,9 @@ impl MirLowerCtx<'_> {
|
|||
) -> Result<Option<(Place, BasicBlockId)>> {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
let place = self.temp(ty, prev_block, expr_id.into())?;
|
||||
let Some(current) = self.lower_expr_to_place_without_adjust(expr_id, place.into(), prev_block)? else {
|
||||
let Some(current) =
|
||||
self.lower_expr_to_place_without_adjust(expr_id, place.into(), prev_block)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some((place.into(), current)))
|
||||
|
@ -35,7 +37,9 @@ impl MirLowerCtx<'_> {
|
|||
.map(|x| x.target.clone())
|
||||
.unwrap_or_else(|| self.expr_ty_without_adjust(expr_id));
|
||||
let place = self.temp(ty, prev_block, expr_id.into())?;
|
||||
let Some(current) = self.lower_expr_to_place_with_adjust(expr_id, place.into(), prev_block, adjustments)? else {
|
||||
let Some(current) =
|
||||
self.lower_expr_to_place_with_adjust(expr_id, place.into(), prev_block, adjustments)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some((place.into(), current)))
|
||||
|
@ -62,7 +66,8 @@ impl MirLowerCtx<'_> {
|
|||
expr_id,
|
||||
upgrade_rvalue,
|
||||
rest,
|
||||
)? else {
|
||||
)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
x.0 = x.0.project(ProjectionElem::Deref);
|
||||
|
@ -74,7 +79,8 @@ impl MirLowerCtx<'_> {
|
|||
expr_id,
|
||||
upgrade_rvalue,
|
||||
rest,
|
||||
)? else {
|
||||
)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.lower_overloaded_deref(
|
||||
|
@ -165,7 +171,8 @@ impl MirLowerCtx<'_> {
|
|||
_ => false,
|
||||
};
|
||||
if !is_builtin {
|
||||
let Some((p, current)) = self.lower_expr_as_place(current, *expr, true)? else {
|
||||
let Some((p, current)) = self.lower_expr_as_place(current, *expr, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
return self.lower_overloaded_deref(
|
||||
|
@ -192,7 +199,8 @@ impl MirLowerCtx<'_> {
|
|||
},
|
||||
);
|
||||
}
|
||||
let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else {
|
||||
let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
r = r.project(ProjectionElem::Deref);
|
||||
|
@ -217,12 +225,18 @@ impl MirLowerCtx<'_> {
|
|||
)
|
||||
{
|
||||
let Some(index_fn) = self.infer.method_resolution(expr_id) else {
|
||||
return Err(MirLowerError::UnresolvedMethod("[overloaded index]".to_string()));
|
||||
return Err(MirLowerError::UnresolvedMethod(
|
||||
"[overloaded index]".to_string(),
|
||||
));
|
||||
};
|
||||
let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
|
||||
let Some((base_place, current)) =
|
||||
self.lower_expr_as_place(current, *base, true)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some((index_operand, current)) = self.lower_expr_to_some_operand(*index, current)? else {
|
||||
let Some((index_operand, current)) =
|
||||
self.lower_expr_to_some_operand(*index, current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
return self.lower_overloaded_index(
|
||||
|
@ -249,7 +263,8 @@ impl MirLowerCtx<'_> {
|
|||
};
|
||||
let l_index =
|
||||
self.temp(self.expr_ty_after_adjustments(*index), current, expr_id.into())?;
|
||||
let Some(current) = self.lower_expr_to_place(*index, l_index.into(), current)? else {
|
||||
let Some(current) = self.lower_expr_to_place(*index, l_index.into(), current)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
p_base = p_base.project(ProjectionElem::Index(l_index));
|
||||
|
@ -282,7 +297,15 @@ impl MirLowerCtx<'_> {
|
|||
)
|
||||
.intern(Interner),
|
||||
);
|
||||
let Some(current) = self.lower_call(index_fn_op, Box::new([Operand::Copy(place), index_operand]), result.clone(), current, false, span)? else {
|
||||
let Some(current) = self.lower_call(
|
||||
index_fn_op,
|
||||
Box::new([Operand::Copy(place), index_operand]),
|
||||
result.clone(),
|
||||
current,
|
||||
false,
|
||||
span,
|
||||
)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
result = result.project(ProjectionElem::Deref);
|
||||
|
@ -329,7 +352,15 @@ impl MirLowerCtx<'_> {
|
|||
.intern(Interner),
|
||||
);
|
||||
let mut result: Place = self.temp(target_ty_ref, current, span)?.into();
|
||||
let Some(current) = self.lower_call(deref_fn_op, Box::new([Operand::Copy(ref_place)]), result.clone(), current, false, span)? else {
|
||||
let Some(current) = self.lower_call(
|
||||
deref_fn_op,
|
||||
Box::new([Operand::Copy(ref_place)]),
|
||||
result.clone(),
|
||||
current,
|
||||
false,
|
||||
span,
|
||||
)?
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
result = result.project(ProjectionElem::Deref);
|
||||
|
|
|
@ -206,7 +206,9 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
|
|||
let Some(node) = (match expr_or_pat {
|
||||
hir_def::hir::ExprOrPatId::ExprId(expr) => expr_node(&body_source_map, expr, &db),
|
||||
hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db),
|
||||
}) else { continue; };
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
let range = node.as_ref().original_file_range(&db);
|
||||
let actual = format!(
|
||||
"expected {}, got {}",
|
||||
|
|
|
@ -701,9 +701,9 @@ fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>
|
|||
let id = macro_id_to_def_id(db.upcast(), m.id);
|
||||
if let Err(e) = db.macro_def(id) {
|
||||
let Some(ast) = id.ast_id().left() else {
|
||||
never!("MacroDefError for proc-macro: {:?}", e);
|
||||
return;
|
||||
};
|
||||
never!("MacroDefError for proc-macro: {:?}", e);
|
||||
return;
|
||||
};
|
||||
emit_def_diagnostic_(
|
||||
db,
|
||||
acc,
|
||||
|
|
|
@ -1494,7 +1494,11 @@ impl<'db> SemanticsImpl<'db> {
|
|||
}
|
||||
|
||||
fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool {
|
||||
let Some(enclosing_item) = expr.syntax().ancestors().find_map(Either::<ast::Item, ast::Variant>::cast) else { return false };
|
||||
let Some(enclosing_item) =
|
||||
expr.syntax().ancestors().find_map(Either::<ast::Item, ast::Variant>::cast)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let def = match &enclosing_item {
|
||||
Either::Left(ast::Item::Fn(it)) if it.unsafe_token().is_some() => return true,
|
||||
|
|
|
@ -27,7 +27,9 @@ use crate::{
|
|||
pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
||||
let comment = ctx.find_token_at_offset::<ast::Comment>()?;
|
||||
// Only allow doc comments
|
||||
let Some(placement) = comment.kind().doc else { return None; };
|
||||
let Some(placement) = comment.kind().doc else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// Only allow comments which are alone on their line
|
||||
if let Some(prev) = comment.syntax().prev_token() {
|
||||
|
|
|
@ -40,12 +40,16 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
|
|||
let qualifier = path.qualifier()?;
|
||||
let name_ref = path.segment()?.name_ref()?;
|
||||
let qualifier_res = ctx.sema.resolve_path(&qualifier)?;
|
||||
let PathResolution::Def(ModuleDef::Module(module)) = qualifier_res else { return None; };
|
||||
let PathResolution::Def(ModuleDef::Module(module)) = qualifier_res else {
|
||||
return None;
|
||||
};
|
||||
let (_, def) = module
|
||||
.scope(ctx.db(), None)
|
||||
.into_iter()
|
||||
.find(|(name, _)| name.to_smol_str() == name_ref.text().as_str())?;
|
||||
let ScopeDef::ModuleDef(def) = def else { return None; };
|
||||
let ScopeDef::ModuleDef(def) = def else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let current_module = ctx.sema.scope(path.syntax())?.module();
|
||||
let target_module = def.module(ctx.db())?;
|
||||
|
|
|
@ -88,7 +88,9 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
|||
let adt = ast::Adt::Struct(strukt.clone());
|
||||
let name = name.display(ctx.db()).to_string();
|
||||
// if `find_struct_impl` returns None, that means that a function named `name` already exists.
|
||||
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else { continue; };
|
||||
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
|
||||
continue;
|
||||
};
|
||||
acc.add_group(
|
||||
&GroupLabel("Generate delegate methods…".to_owned()),
|
||||
AssistId("generate_delegate_methods", AssistKind::Generate),
|
||||
|
|
|
@ -623,7 +623,9 @@ fn fn_generic_params(
|
|||
fn params_and_where_preds_in_scope(
|
||||
ctx: &AssistContext<'_>,
|
||||
) -> (Vec<ast::GenericParam>, Vec<ast::WherePred>) {
|
||||
let Some(body) = containing_body(ctx) else { return Default::default(); };
|
||||
let Some(body) = containing_body(ctx) else {
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
let mut generic_params = Vec::new();
|
||||
let mut where_clauses = Vec::new();
|
||||
|
|
|
@ -54,7 +54,11 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
|||
// NOTE: We can technically provide this assist for default methods in trait definitions, but
|
||||
// it's somewhat complex to handle it correctly when the const's name conflicts with
|
||||
// supertrait's item. We may want to consider implementing it in the future.
|
||||
let AssocItemContainer::Impl(impl_) = ctx.sema.to_def(&parent_fn)?.as_assoc_item(db)?.container(db) else { return None; };
|
||||
let AssocItemContainer::Impl(impl_) =
|
||||
ctx.sema.to_def(&parent_fn)?.as_assoc_item(db)?.container(db)
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if impl_.trait_(db).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -38,14 +38,18 @@ pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext<'
|
|||
};
|
||||
|
||||
let type_ref = &ret_type.ty()?;
|
||||
let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else { return None; };
|
||||
let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else {
|
||||
return None;
|
||||
};
|
||||
let result_enum =
|
||||
FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
|
||||
if ret_enum != result_enum {
|
||||
return None;
|
||||
}
|
||||
|
||||
let Some(ok_type) = unwrap_result_type(type_ref) else { return None; };
|
||||
let Some(ok_type) = unwrap_result_type(type_ref) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
acc.add(
|
||||
AssistId("unwrap_result_return_type", AssistKind::RefactorRewrite),
|
||||
|
@ -130,12 +134,16 @@ fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
|
|||
|
||||
// Tries to extract `T` from `Result<T, E>`.
|
||||
fn unwrap_result_type(ty: &ast::Type) -> Option<ast::Type> {
|
||||
let ast::Type::PathType(path_ty) = ty else { return None; };
|
||||
let ast::Type::PathType(path_ty) = ty else {
|
||||
return None;
|
||||
};
|
||||
let path = path_ty.path()?;
|
||||
let segment = path.first_segment()?;
|
||||
let generic_arg_list = segment.generic_arg_list()?;
|
||||
let generic_args: Vec<_> = generic_arg_list.generic_args().collect();
|
||||
let ast::GenericArg::TypeArg(ok_type) = generic_args.first()? else { return None; };
|
||||
let ast::GenericArg::TypeArg(ok_type) = generic_args.first()? else {
|
||||
return None;
|
||||
};
|
||||
ok_type.ty()
|
||||
}
|
||||
|
||||
|
|
|
@ -463,7 +463,9 @@ impl CompletionContext<'_> {
|
|||
|
||||
/// Checks whether this item should be listed in regards to stability. Returns `true` if we should.
|
||||
pub(crate) fn check_stability(&self, attrs: Option<&hir::Attrs>) -> bool {
|
||||
let Some(attrs) = attrs else { return true; };
|
||||
let Some(attrs) = attrs else {
|
||||
return true;
|
||||
};
|
||||
!attrs.is_unstable() || self.is_nightly
|
||||
}
|
||||
|
||||
|
|
|
@ -243,10 +243,7 @@ fn analyze(
|
|||
|
||||
let Some(name_like) = find_node_at_offset(&speculative_file, offset) else {
|
||||
let analysis = if let Some(original) = ast::String::cast(original_token.clone()) {
|
||||
CompletionAnalysis::String {
|
||||
original,
|
||||
expanded: ast::String::cast(self_token.clone()),
|
||||
}
|
||||
CompletionAnalysis::String { original, expanded: ast::String::cast(self_token.clone()) }
|
||||
} else {
|
||||
// Fix up trailing whitespace problem
|
||||
// #[attr(foo = $0
|
||||
|
|
|
@ -119,10 +119,11 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
|
|||
stack.pop();
|
||||
'crates: for &krate in ctx.sema.db.relevant_crates(parent_id).iter() {
|
||||
let crate_def_map = ctx.sema.db.crate_def_map(krate);
|
||||
let Some((_, module)) =
|
||||
crate_def_map.modules()
|
||||
.find(|(_, module)| module.origin.file_id() == Some(parent_id) && !module.origin.is_inline())
|
||||
else { continue };
|
||||
let Some((_, module)) = crate_def_map.modules().find(|(_, module)| {
|
||||
module.origin.file_id() == Some(parent_id) && !module.origin.is_inline()
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if stack.is_empty() {
|
||||
return make_fixes(
|
||||
|
|
|
@ -330,7 +330,9 @@ fn get_doc_links(
|
|||
base_url.and_then(|url| url.join(path).ok())
|
||||
};
|
||||
|
||||
let Some((target, file, frag)) = filename_and_frag_for_def(db, def) else { return Default::default(); };
|
||||
let Some((target, file, frag)) = filename_and_frag_for_def(db, def) else {
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
let (mut web_url, mut local_url) = get_doc_base_urls(db, target, target_dir, sysroot);
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool,
|
|||
}
|
||||
})() else {
|
||||
never!("broken syntax tree?\n{:?}\n{:?}", expr, dummy_expr);
|
||||
return (true, true)
|
||||
return (true, true);
|
||||
};
|
||||
|
||||
// At this point
|
||||
|
|
|
@ -274,10 +274,12 @@ impl flags::AnalysisStats {
|
|||
continue;
|
||||
}
|
||||
all += 1;
|
||||
let Err(e)
|
||||
= db.layout_of_adt(hir_def::AdtId::from(a).into(), Substitution::empty(Interner), a.krate(db).into())
|
||||
else {
|
||||
continue
|
||||
let Err(e) = db.layout_of_adt(
|
||||
hir_def::AdtId::from(a).into(),
|
||||
Substitution::empty(Interner),
|
||||
a.krate(db).into(),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
if verbosity.is_spammy() {
|
||||
let full_name = full_name_of_item(db, a.module(db), a.name(db));
|
||||
|
|
|
@ -1331,7 +1331,9 @@ pub(crate) fn handle_code_lens_resolve(
|
|||
snap: GlobalStateSnapshot,
|
||||
code_lens: CodeLens,
|
||||
) -> anyhow::Result<CodeLens> {
|
||||
let Some(annotation) = from_proto::annotation(&snap, code_lens.clone())? else { return Ok(code_lens) };
|
||||
let Some(annotation) = from_proto::annotation(&snap, code_lens.clone())? else {
|
||||
return Ok(code_lens);
|
||||
};
|
||||
let annotation = snap.analysis.resolve_annotation(annotation)?;
|
||||
|
||||
let mut acc = Vec::new();
|
||||
|
@ -1632,9 +1634,9 @@ pub(crate) fn handle_open_docs(
|
|||
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
|
||||
return if snap.config.local_docs() {
|
||||
Ok(ExternalDocsResponse::WithLocal(Default::default()))
|
||||
} else {
|
||||
} else {
|
||||
Ok(ExternalDocsResponse::Simple(None))
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok());
|
||||
|
|
|
@ -334,7 +334,11 @@ impl GlobalState {
|
|||
let _p = profile::span("GlobalState::switch_workspaces");
|
||||
tracing::info!(%cause, "will switch workspaces");
|
||||
|
||||
let Some((workspaces, force_reload_crate_graph)) = self.fetch_workspaces_queue.last_op_result() else { return; };
|
||||
let Some((workspaces, force_reload_crate_graph)) =
|
||||
self.fetch_workspaces_queue.last_op_result()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Err(_) = self.fetch_workspace_error() {
|
||||
if !self.workspaces.is_empty() {
|
||||
|
@ -525,7 +529,7 @@ impl GlobalState {
|
|||
let mut buf = String::new();
|
||||
|
||||
let Some((last_op_result, _)) = self.fetch_workspaces_queue.last_op_result() else {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
};
|
||||
if last_op_result.is_empty() {
|
||||
stdx::format_to!(buf, "rust-analyzer failed to discover workspace");
|
||||
|
|
|
@ -61,7 +61,9 @@ impl CommentBlock {
|
|||
let mut blocks = CommentBlock::extract_untagged(text);
|
||||
blocks.retain_mut(|block| {
|
||||
let first = block.contents.remove(0);
|
||||
let Some(id) = first.strip_prefix(&tag) else { return false; };
|
||||
let Some(id) = first.strip_prefix(&tag) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if block.is_doc {
|
||||
panic!("Use plain (non-doc) comments with tags like {tag}:\n {first}");
|
||||
|
|
Loading…
Reference in a new issue