Remove weird nesting of effect blocks in hir

This commit is contained in:
Lukas Wirth 2023-03-04 14:45:57 +01:00
parent 24ba1bed04
commit 1b5bc83118
9 changed files with 285 additions and 247 deletions

View file

@ -37,7 +37,7 @@ use crate::{
item_scope::BuiltinShadowMode, item_scope::BuiltinShadowMode,
path::{GenericArgs, Path}, path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef}, type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockLoc, ModuleDefId, UnresolvedMacro, AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
}; };
pub struct LowerCtx<'a> { pub struct LowerCtx<'a> {
@ -238,33 +238,32 @@ impl ExprCollector<'_> {
} }
ast::Expr::BlockExpr(e) => match e.modifier() { ast::Expr::BlockExpr(e) => match e.modifier() {
Some(ast::BlockModifier::Try(_)) => { Some(ast::BlockModifier::Try(_)) => {
let body = self.collect_block(e); self.collect_block_(e, |id, statements, tail| Expr::TryBlock {
self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) id,
statements,
tail,
})
} }
Some(ast::BlockModifier::Unsafe(_)) => { Some(ast::BlockModifier::Unsafe(_)) => {
let body = self.collect_block(e); self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
self.alloc_expr(Expr::Unsafe { body }, syntax_ptr) id,
statements,
tail,
})
} }
// FIXME: we need to record these effects somewhere...
Some(ast::BlockModifier::Label(label)) => { Some(ast::BlockModifier::Label(label)) => {
let label = self.collect_label(label); let label = self.collect_label(label);
let res = self.collect_block(e); self.collect_block_(e, |id, statements, tail| Expr::Block {
match &mut self.body.exprs[res] { id,
Expr::Block { label: block_label, .. } => { statements,
*block_label = Some(label); tail,
} label: Some(label),
_ => unreachable!(), })
}
res
}
Some(ast::BlockModifier::Async(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::Async { body }, syntax_ptr)
}
Some(ast::BlockModifier::Const(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::Const { body }, syntax_ptr)
} }
Some(ast::BlockModifier::Async(_)) => self
.collect_block_(e, |id, statements, tail| Expr::Async { id, statements, tail }),
Some(ast::BlockModifier::Const(_)) => self
.collect_block_(e, |id, statements, tail| Expr::Const { id, statements, tail }),
None => self.collect_block(e), None => self.collect_block(e),
}, },
ast::Expr::LoopExpr(e) => { ast::Expr::LoopExpr(e) => {
@ -737,6 +736,19 @@ impl ExprCollector<'_> {
} }
fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
self.collect_block_(block, |id, statements, tail| Expr::Block {
id,
statements,
tail,
label: None,
})
}
fn collect_block_(
&mut self,
block: ast::BlockExpr,
mk_block: impl FnOnce(BlockId, Box<[Statement]>, Option<ExprId>) -> Expr,
) -> ExprId {
let file_local_id = self.ast_id_map.ast_id(&block); let file_local_id = self.ast_id_map.ast_id(&block);
let ast_id = AstId::new(self.expander.current_file_id, file_local_id); let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
let block_loc = let block_loc =
@ -769,15 +781,8 @@ impl ExprCollector<'_> {
}); });
let syntax_node_ptr = AstPtr::new(&block.into()); let syntax_node_ptr = AstPtr::new(&block.into());
let expr_id = self.alloc_expr( let expr_id = self
Expr::Block { .alloc_expr(mk_block(block_id, statements.into_boxed_slice(), tail), syntax_node_ptr);
id: block_id,
statements: statements.into_boxed_slice(),
tail,
label: None,
},
syntax_node_ptr,
);
self.expander.def_map = prev_def_map; self.expander.def_map = prev_def_map;
self.expander.module = prev_local_module; self.expander.module = prev_local_module;

View file

@ -292,18 +292,6 @@ impl<'a> Printer<'a> {
self.print_expr(*expr); self.print_expr(*expr);
w!(self, "?"); w!(self, "?");
} }
Expr::TryBlock { body } => {
w!(self, "try ");
self.print_expr(*body);
}
Expr::Async { body } => {
w!(self, "async ");
self.print_expr(*body);
}
Expr::Const { body } => {
w!(self, "const ");
self.print_expr(*body);
}
Expr::Cast { expr, type_ref } => { Expr::Cast { expr, type_ref } => {
self.print_expr(*expr); self.print_expr(*expr);
w!(self, " as "); w!(self, " as ");
@ -402,10 +390,6 @@ impl<'a> Printer<'a> {
} }
w!(self, ")"); w!(self, ")");
} }
Expr::Unsafe { body } => {
w!(self, "unsafe ");
self.print_expr(*body);
}
Expr::Array(arr) => { Expr::Array(arr) => {
w!(self, "["); w!(self, "[");
if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) { if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) {
@ -428,27 +412,49 @@ impl<'a> Printer<'a> {
} }
Expr::Literal(lit) => self.print_literal(lit), Expr::Literal(lit) => self.print_literal(lit),
Expr::Block { id: _, statements, tail, label } => { Expr::Block { id: _, statements, tail, label } => {
self.whitespace(); let label = label.map(|lbl| format!("{}: ", self.body[lbl].name));
if let Some(lbl) = label { self.print_block(label.as_deref(), statements, tail);
w!(self, "{}: ", self.body[*lbl].name); }
} Expr::Unsafe { id: _, statements, tail } => {
w!(self, "{{"); self.print_block(Some("unsafe "), statements, tail);
if !statements.is_empty() || tail.is_some() { }
self.indented(|p| { Expr::TryBlock { id: _, statements, tail } => {
for stmt in &**statements { self.print_block(Some("try "), statements, tail);
p.print_stmt(stmt); }
} Expr::Async { id: _, statements, tail } => {
if let Some(tail) = tail { self.print_block(Some("async "), statements, tail);
p.print_expr(*tail); }
} Expr::Const { id: _, statements, tail } => {
p.newline(); self.print_block(Some("const "), statements, tail);
});
}
w!(self, "}}");
} }
} }
} }
fn print_block(
&mut self,
label: Option<&str>,
statements: &Box<[Statement]>,
tail: &Option<la_arena::Idx<Expr>>,
) {
self.whitespace();
if let Some(lbl) = label {
w!(self, "{}", lbl);
}
w!(self, "{{");
if !statements.is_empty() || tail.is_some() {
self.indented(|p| {
for stmt in &**statements {
p.print_stmt(stmt);
}
if let Some(tail) = tail {
p.print_expr(*tail);
}
p.newline();
});
}
w!(self, "}}");
}
fn print_pat(&mut self, pat: PatId) { fn print_pat(&mut self, pat: PatId) {
let pat = &self.body[pat]; let pat = &self.body[pat];

View file

@ -109,6 +109,26 @@ pub enum Expr {
tail: Option<ExprId>, tail: Option<ExprId>,
label: Option<LabelId>, label: Option<LabelId>,
}, },
TryBlock {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Async {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Const {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Unsafe {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Loop { Loop {
body: ExprId, body: ExprId,
label: Option<LabelId>, label: Option<LabelId>,
@ -172,15 +192,6 @@ pub enum Expr {
Try { Try {
expr: ExprId, expr: ExprId,
}, },
TryBlock {
body: ExprId,
},
Async {
body: ExprId,
},
Const {
body: ExprId,
},
Cast { Cast {
expr: ExprId, expr: ExprId,
type_ref: Interned<TypeRef>, type_ref: Interned<TypeRef>,
@ -222,9 +233,6 @@ pub enum Expr {
exprs: Box<[ExprId]>, exprs: Box<[ExprId]>,
is_assignee_expr: bool, is_assignee_expr: bool,
}, },
Unsafe {
body: ExprId,
},
Array(Array), Array(Array),
Literal(Literal), Literal(Literal),
Underscore, Underscore,
@ -290,13 +298,20 @@ impl Expr {
Expr::Let { expr, .. } => { Expr::Let { expr, .. } => {
f(*expr); f(*expr);
} }
Expr::Block { statements, tail, .. } => { Expr::Block { statements, tail, .. }
| Expr::TryBlock { statements, tail, .. }
| Expr::Unsafe { statements, tail, .. }
| Expr::Async { statements, tail, .. }
| Expr::Const { statements, tail, .. } => {
for stmt in statements.iter() { for stmt in statements.iter() {
match stmt { match stmt {
Statement::Let { initializer, .. } => { Statement::Let { initializer, else_branch, .. } => {
if let &Some(expr) = initializer { if let &Some(expr) = initializer {
f(expr); f(expr);
} }
if let &Some(expr) = else_branch {
f(expr);
}
} }
Statement::Expr { expr: expression, .. } => f(*expression), Statement::Expr { expr: expression, .. } => f(*expression),
} }
@ -305,10 +320,6 @@ impl Expr {
f(expr); f(expr);
} }
} }
Expr::TryBlock { body }
| Expr::Unsafe { body }
| Expr::Async { body }
| Expr::Const { body } => f(*body),
Expr::Loop { body, .. } => f(*body), Expr::Loop { body, .. } => f(*body),
Expr::While { condition, body, .. } => { Expr::While { condition, body, .. } => {
f(*condition); f(*condition);

View file

@ -94,8 +94,10 @@ fn walk_unsafe(
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
} }
} }
Expr::Unsafe { body: child } => { Expr::Unsafe { .. } => {
return walk_unsafe(db, infer, def, body, *child, true, unsafe_expr_cb); expr.walk_child_exprs(|child| {
walk_unsafe(db, infer, def, body, child, true, unsafe_expr_cb);
});
} }
_ => {} _ => {}
} }

View file

@ -124,41 +124,18 @@ impl<'a> InferenceContext<'a> {
self.result.standard_types.bool_.clone() self.result.standard_types.bool_.clone()
} }
Expr::Block { statements, tail, label, id: _ } => { Expr::Block { statements, tail, label, id: _ } => {
let old_resolver = mem::replace( self.infer_block(tgt_expr, statements, *tail, *label, expected)
&mut self.resolver,
resolver_for_expr(self.db.upcast(), self.owner, tgt_expr),
);
let ty = match label {
Some(_) => {
let break_ty = expected.coercion_target_type(&mut self.table);
let (breaks, ty) = self.with_breakable_ctx(
BreakableKind::Block,
Some(break_ty.clone()),
*label,
|this| {
this.infer_block(
tgt_expr,
statements,
*tail,
&Expectation::has_type(break_ty),
)
},
);
breaks.unwrap_or(ty)
}
None => self.infer_block(tgt_expr, statements, *tail, expected),
};
self.resolver = old_resolver;
ty
} }
Expr::Unsafe { body } => self.infer_expr(*body, expected), Expr::Unsafe { id: _, statements, tail } => {
Expr::Const { body } => { self.infer_block(tgt_expr, statements, *tail, None, expected)
}
Expr::Const { id: _, statements, tail } => {
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
this.infer_expr(*body, expected) this.infer_block(tgt_expr, statements, *tail, None, expected)
}) })
.1 .1
} }
Expr::TryBlock { body } => { Expr::TryBlock { id: _, statements, tail } => {
// The type that is returned from the try block // The type that is returned from the try block
let try_ty = self.table.new_type_var(); let try_ty = self.table.new_type_var();
if let Some(ty) = expected.only_has_type(&mut self.table) { if let Some(ty) = expected.only_has_type(&mut self.table) {
@ -169,13 +146,16 @@ impl<'a> InferenceContext<'a> {
let ok_ty = let ok_ty =
self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_output()); self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_output());
self.with_breakable_ctx(BreakableKind::Block, Some(ok_ty.clone()), None, |this| { self.infer_block(
this.infer_expr(*body, &Expectation::has_type(ok_ty)); tgt_expr,
}); statements,
*tail,
None,
&Expectation::has_type(ok_ty.clone()),
);
try_ty try_ty
} }
Expr::Async { body } => { Expr::Async { id: _, statements, tail } => {
let ret_ty = self.table.new_type_var(); let ret_ty = self.table.new_type_var();
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
@ -184,7 +164,13 @@ impl<'a> InferenceContext<'a> {
let (_, inner_ty) = let (_, inner_ty) =
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)) this.infer_block(
tgt_expr,
statements,
*tail,
None,
&Expectation::has_type(ret_ty),
)
}); });
self.diverges = prev_diverges; self.diverges = prev_diverges;
@ -193,7 +179,8 @@ impl<'a> InferenceContext<'a> {
// Use the first type parameter as the output type of future. // Use the first type parameter as the output type of future.
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); let impl_trait_id =
crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr);
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty)) TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty))
.intern(Interner) .intern(Interner)
@ -1153,80 +1140,102 @@ impl<'a> InferenceContext<'a> {
expr: ExprId, expr: ExprId,
statements: &[Statement], statements: &[Statement],
tail: Option<ExprId>, tail: Option<ExprId>,
label: Option<LabelId>,
expected: &Expectation, expected: &Expectation,
) -> Ty { ) -> Ty {
for stmt in statements { let coerce_ty = expected.coercion_target_type(&mut self.table);
match stmt { let old_resolver =
Statement::Let { pat, type_ref, initializer, else_branch } => { mem::replace(&mut self.resolver, resolver_for_expr(self.db.upcast(), self.owner, expr));
let decl_ty = type_ref
.as_ref()
.map(|tr| self.make_ty(tr))
.unwrap_or_else(|| self.table.new_type_var());
let ty = if let Some(expr) = initializer { let (break_ty, ty) =
let ty = if contains_explicit_ref_binding(&self.body, *pat) { self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| {
self.infer_expr(*expr, &Expectation::has_type(decl_ty.clone())) for stmt in statements {
} else { match stmt {
self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())) Statement::Let { pat, type_ref, initializer, else_branch } => {
}; let decl_ty = type_ref
if type_ref.is_some() { .as_ref()
decl_ty .map(|tr| this.make_ty(tr))
} else { .unwrap_or_else(|| this.table.new_type_var());
ty
let ty = if let Some(expr) = initializer {
let ty = if contains_explicit_ref_binding(&this.body, *pat) {
this.infer_expr(*expr, &Expectation::has_type(decl_ty.clone()))
} else {
this.infer_expr_coerce(
*expr,
&Expectation::has_type(decl_ty.clone()),
)
};
if type_ref.is_some() {
decl_ty
} else {
ty
}
} else {
decl_ty
};
this.infer_top_pat(*pat, &ty);
if let Some(expr) = else_branch {
let previous_diverges =
mem::replace(&mut this.diverges, Diverges::Maybe);
this.infer_expr_coerce(
*expr,
&Expectation::HasType(this.result.standard_types.never.clone()),
);
this.diverges = previous_diverges;
}
}
&Statement::Expr { expr, has_semi } => {
this.infer_expr(
expr,
&if has_semi {
Expectation::none()
} else {
Expectation::HasType(this.result.standard_types.unit.clone())
},
);
} }
} else {
decl_ty
};
self.infer_top_pat(*pat, &ty);
if let Some(expr) = else_branch {
let previous_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
self.infer_expr_coerce(
*expr,
&Expectation::HasType(self.result.standard_types.never.clone()),
);
self.diverges = previous_diverges;
} }
} }
&Statement::Expr { expr, has_semi } => {
self.infer_expr(
expr,
&if has_semi {
Expectation::none()
} else {
Expectation::HasType(self.result.standard_types.unit.clone())
},
);
}
}
}
if let Some(expr) = tail { // FIXME: This should make use of the breakable CoerceMany
self.infer_expr_coerce(expr, expected) if let Some(expr) = tail {
} else { this.infer_expr_coerce(expr, expected)
// Citing rustc: if there is no explicit tail expression, } else {
// that is typically equivalent to a tail expression // Citing rustc: if there is no explicit tail expression,
// of `()` -- except if the block diverges. In that // that is typically equivalent to a tail expression
// case, there is no value supplied from the tail // of `()` -- except if the block diverges. In that
// expression (assuming there are no other breaks, // case, there is no value supplied from the tail
// this implies that the type of the block will be // expression (assuming there are no other breaks,
// `!`). // this implies that the type of the block will be
if self.diverges.is_always() { // `!`).
// we don't even make an attempt at coercion if this.diverges.is_always() {
self.table.new_maybe_never_var() // we don't even make an attempt at coercion
} else if let Some(t) = expected.only_has_type(&mut self.table) { this.table.new_maybe_never_var()
if self.coerce(Some(expr), &TyBuilder::unit(), &t).is_err() { } else if let Some(t) = expected.only_has_type(&mut this.table) {
self.result.type_mismatches.insert( if this
expr.into(), .coerce(Some(expr), &this.result.standard_types.unit.clone(), &t)
TypeMismatch { expected: t.clone(), actual: TyBuilder::unit() }, .is_err()
); {
this.result.type_mismatches.insert(
expr.into(),
TypeMismatch {
expected: t.clone(),
actual: this.result.standard_types.unit.clone(),
},
);
}
t
} else {
this.result.standard_types.unit.clone()
}
} }
t });
} else { self.resolver = old_resolver;
TyBuilder::unit()
} break_ty.unwrap_or(ty)
}
} }
fn lookup_field( fn lookup_field(

View file

@ -331,56 +331,11 @@ impl MirLowerCtx<'_> {
} }
Ok(result) Ok(result)
} }
Expr::Unsafe { id: _, statements, tail } => {
self.lower_block_to_place(None, statements, current, *tail, place)
}
Expr::Block { id: _, statements, tail, label } => { Expr::Block { id: _, statements, tail, label } => {
if label.is_some() { self.lower_block_to_place(*label, statements, current, *tail, place)
not_supported!("block with label");
}
for statement in statements.iter() {
match statement {
hir_def::expr::Statement::Let {
pat,
initializer,
else_branch,
type_ref: _,
} => match initializer {
Some(expr_id) => {
let else_block;
let init_place;
(init_place, current) =
self.lower_expr_to_some_place(*expr_id, current)?;
(current, else_block) = self.pattern_match(
current,
None,
init_place,
self.expr_ty(*expr_id),
*pat,
BindingAnnotation::Unannotated,
)?;
match (else_block, else_branch) {
(None, _) => (),
(Some(else_block), None) => {
self.set_terminator(else_block, Terminator::Unreachable);
}
(Some(else_block), Some(else_branch)) => {
let (_, b) = self
.lower_expr_to_some_place(*else_branch, else_block)?;
self.set_terminator(b, Terminator::Unreachable);
}
}
}
None => continue,
},
hir_def::expr::Statement::Expr { expr, has_semi: _ } => {
let ty = self.expr_ty(*expr);
let temp = self.temp(ty)?;
current = self.lower_expr_to_place(*expr, temp.into(), current)?;
}
}
}
match tail {
Some(tail) => self.lower_expr_to_place(*tail, place, current),
None => Ok(current),
}
} }
Expr::Loop { body, label } => self.lower_loop(current, *label, |this, begin, _| { Expr::Loop { body, label } => self.lower_loop(current, *label, |this, begin, _| {
let (_, block) = this.lower_expr_to_some_place(*body, begin)?; let (_, block) = this.lower_expr_to_some_place(*body, begin)?;
@ -686,7 +641,6 @@ impl MirLowerCtx<'_> {
self.push_assignment(current, place, r); self.push_assignment(current, place, r);
Ok(current) Ok(current)
} }
Expr::Unsafe { body } => self.lower_expr_to_place(*body, place, current),
Expr::Array(l) => match l { Expr::Array(l) => match l {
Array::ElementList { elements, .. } => { Array::ElementList { elements, .. } => {
let elem_ty = match &self.expr_ty(expr_id).data(Interner).kind { let elem_ty = match &self.expr_ty(expr_id).data(Interner).kind {
@ -723,6 +677,62 @@ impl MirLowerCtx<'_> {
} }
} }
fn lower_block_to_place(
&mut self,
label: Option<LabelId>,
statements: &[hir_def::expr::Statement],
mut current: BasicBlockId,
tail: Option<ExprId>,
place: Place,
) -> Result<BasicBlockId> {
if label.is_some() {
not_supported!("block with label");
}
for statement in statements.iter() {
match statement {
hir_def::expr::Statement::Let { pat, initializer, else_branch, type_ref: _ } => {
match initializer {
Some(expr_id) => {
let else_block;
let init_place;
(init_place, current) =
self.lower_expr_to_some_place(*expr_id, current)?;
(current, else_block) = self.pattern_match(
current,
None,
init_place,
self.expr_ty(*expr_id),
*pat,
BindingAnnotation::Unannotated,
)?;
match (else_block, else_branch) {
(None, _) => (),
(Some(else_block), None) => {
self.set_terminator(else_block, Terminator::Unreachable);
}
(Some(else_block), Some(else_branch)) => {
let (_, b) =
self.lower_expr_to_some_place(*else_branch, else_block)?;
self.set_terminator(b, Terminator::Unreachable);
}
}
}
None => continue,
}
}
hir_def::expr::Statement::Expr { expr, has_semi: _ } => {
let ty = self.expr_ty(*expr);
let temp = self.temp(ty)?;
current = self.lower_expr_to_place(*expr, temp.into(), current)?;
}
}
}
match tail {
Some(tail) => self.lower_expr_to_place(tail, place, current),
None => Ok(current),
}
}
fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> { fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
let size = layout_of_ty(self.db, &ty, self.owner.module(self.db.upcast()).krate())? let size = layout_of_ty(self.db, &ty, self.owner.module(self.db.upcast()).krate())?
.size .size

View file

@ -61,22 +61,27 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
Some(tracing::subscriber::set_default(subscriber)) Some(tracing::subscriber::set_default(subscriber))
} }
#[track_caller]
fn check_types(ra_fixture: &str) { fn check_types(ra_fixture: &str) {
check_impl(ra_fixture, false, true, false) check_impl(ra_fixture, false, true, false)
} }
#[track_caller]
fn check_types_source_code(ra_fixture: &str) { fn check_types_source_code(ra_fixture: &str) {
check_impl(ra_fixture, false, true, true) check_impl(ra_fixture, false, true, true)
} }
#[track_caller]
fn check_no_mismatches(ra_fixture: &str) { fn check_no_mismatches(ra_fixture: &str) {
check_impl(ra_fixture, true, false, false) check_impl(ra_fixture, true, false, false)
} }
#[track_caller]
fn check(ra_fixture: &str) { fn check(ra_fixture: &str) {
check_impl(ra_fixture, false, false, false) check_impl(ra_fixture, false, false, false)
} }
#[track_caller]
fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) { fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) {
let _tracing = setup_tracing(); let _tracing = setup_tracing();
let (db, files) = TestDB::with_many_files(ra_fixture); let (db, files) = TestDB::with_many_files(ra_fixture);

View file

@ -1167,7 +1167,6 @@ fn test() {
123..167 '{ ...o(); }': () 123..167 '{ ...o(); }': ()
133..134 's': &S 133..134 's': &S
137..151 'unsafe { f() }': &S 137..151 'unsafe { f() }': &S
137..151 'unsafe { f() }': &S
146..147 'f': fn f() -> &S 146..147 'f': fn f() -> &S
146..149 'f()': &S 146..149 'f()': &S
157..158 's': &S 157..158 's': &S

View file

@ -352,7 +352,6 @@ unsafe fn baz(u: MyUnion) {
71..89 'MyUnio...o: 0 }': MyUnion 71..89 'MyUnio...o: 0 }': MyUnion
86..87 '0': u32 86..87 '0': u32
95..113 'unsafe...(u); }': () 95..113 'unsafe...(u); }': ()
95..113 'unsafe...(u); }': ()
104..107 'baz': fn baz(MyUnion) 104..107 'baz': fn baz(MyUnion)
104..110 'baz(u)': () 104..110 'baz(u)': ()
108..109 'u': MyUnion 108..109 'u': MyUnion
@ -360,7 +359,6 @@ unsafe fn baz(u: MyUnion) {
126..146 'MyUnio... 0.0 }': MyUnion 126..146 'MyUnio... 0.0 }': MyUnion
141..144 '0.0': f32 141..144 '0.0': f32
152..170 'unsafe...(u); }': () 152..170 'unsafe...(u); }': ()
152..170 'unsafe...(u); }': ()
161..164 'baz': fn baz(MyUnion) 161..164 'baz': fn baz(MyUnion)
161..167 'baz(u)': () 161..167 'baz(u)': ()
165..166 'u': MyUnion 165..166 'u': MyUnion
@ -2077,22 +2075,17 @@ async fn main() {
16..193 '{ ...2 }; }': () 16..193 '{ ...2 }; }': ()
26..27 'x': i32 26..27 'x': i32
30..43 'unsafe { 92 }': i32 30..43 'unsafe { 92 }': i32
30..43 'unsafe { 92 }': i32
39..41 '92': i32 39..41 '92': i32
53..54 'y': impl Future<Output = ()> 53..54 'y': impl Future<Output = ()>
57..85 'async ...wait }': ()
57..85 'async ...wait }': impl Future<Output = ()> 57..85 'async ...wait }': impl Future<Output = ()>
65..77 'async { () }': ()
65..77 'async { () }': impl Future<Output = ()> 65..77 'async { () }': impl Future<Output = ()>
65..83 'async ....await': () 65..83 'async ....await': ()
73..75 '()': () 73..75 '()': ()
95..96 'z': ControlFlow<(), ()> 95..96 'z': ControlFlow<(), ()>
130..140 'try { () }': ()
130..140 'try { () }': ControlFlow<(), ()> 130..140 'try { () }': ControlFlow<(), ()>
136..138 '()': () 136..138 '()': ()
150..151 'w': i32 150..151 'w': i32
154..166 'const { 92 }': i32 154..166 'const { 92 }': i32
154..166 'const { 92 }': i32
162..164 '92': i32 162..164 '92': i32
176..177 't': i32 176..177 't': i32
180..190 ''a: { 92 }': i32 180..190 ''a: { 92 }': i32
@ -2122,7 +2115,6 @@ fn main() {
83..84 'f': F 83..84 'f': F
89..91 '{}': () 89..91 '{}': ()
103..231 '{ ... }); }': () 103..231 '{ ... }); }': ()
109..161 'async ... }': Result<(), ()>
109..161 'async ... }': impl Future<Output = Result<(), ()>> 109..161 'async ... }': impl Future<Output = Result<(), ()>>
125..139 'return Err(())': ! 125..139 'return Err(())': !
132..135 'Err': Err<(), ()>(()) -> Result<(), ()> 132..135 'Err': Err<(), ()>(()) -> Result<(), ()>
@ -2134,7 +2126,6 @@ fn main() {
167..171 'test': fn test<(), (), || -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(|| -> impl Future<Output = Result<(), ()>>) 167..171 'test': fn test<(), (), || -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(|| -> impl Future<Output = Result<(), ()>>)
167..228 'test(|... })': () 167..228 'test(|... })': ()
172..227 '|| asy... }': || -> impl Future<Output = Result<(), ()>> 172..227 '|| asy... }': || -> impl Future<Output = Result<(), ()>>
175..227 'async ... }': Result<(), ()>
175..227 'async ... }': impl Future<Output = Result<(), ()>> 175..227 'async ... }': impl Future<Output = Result<(), ()>>
191..205 'return Err(())': ! 191..205 'return Err(())': !
198..201 'Err': Err<(), ()>(()) -> Result<(), ()> 198..201 'Err': Err<(), ()>(()) -> Result<(), ()>