Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Judgment borrow_check_expr

judgment_fn! {
    /// Prove that any loans issued in this value expression are respected, and return its type.
    pub fn borrow_check_expr(
        env: TypeckEnv,
        assumptions: Predicates,
        state: FlowState,
        expr: Expr,
        places_live_on_exit: LivePlaces,
    ) => (Ty, FlowState) {
        /* rules omitted */
    }
}

Source: crates/formality-rust/src/check/borrow_check/nll.rs:371

The number on each rule’s conclusion is positive coverage; the number on each premise is negative coverage. Click a number to browse the tests.

parenthesized
LineCoverageSource
383✗(borrow_check_expr(env, assumptions, state, expr, places_live_on_exit) => (ty, state))
──────── ("parenthesized")
3855(borrow_check_expr(env, assumptions, state, Expr::Parens(expr), places_live_on_exit) => (ty, state))
multiplication
LineCoverageSource
389N/A(let expr = Expr::BinOp { lhs: lhs.clone(), op: BinOpKind::Mul, rhs: rhs.clone() })
3902(borrow_check_expr(env, assumptions, state, expr, places_live_on_exit) => (ty, state))
──────── ("multiplication")
3927(borrow_check_expr(env, assumptions, state, Expr::Mul { lhs, rhs }, places_live_on_exit) => (ty, state))
assign
LineCoverageSource
3971(borrow_check_expr(
env,
assumptions,
state,
expr,
Assignment(place).live_before(env, &state, places_live_on_exit),
) => (value_ty, state))
4062(borrow_check_place_expr(
env,
assumptions,
state,
place,
) => (place, state))
4141(prove_assignable(env, assumptions, state, value_ty, &place.ty) => state)
41611(access_permitted(
env,
assumptions,
state,
Access::new(AccessKind::Write, place),
places_live_on_exit,
) => state)
424N/A(let state = kill_loans(place, state))
425N/A(let state = state.with_initialized(&place.to_place_expression()))
──────── ("assign")
42727(borrow_check_expr(env, assumptions, state, Expr::Assign { place, expr }, places_live_on_exit) => (Ty::unit(), state))
assign-op
LineCoverageSource
4321(borrow_check_expr(
env,
assumptions,
state,
rhs,
Seq(place, Assignment(place)).live_before(env, &state, places_live_on_exit),
) => (rhs_ty, state))
439N/A(let places_live_before_write = Assignment(place).live_before(env, &state, places_live_on_exit))
441✗(borrow_check_place_expr(env, assumptions, state, place) => (place, state))
442✗(prove_ty_is_rigid(env, assumptions, state, &place.ty) => (RigidTy { name: RigidName::ScalarId(scalar), parameters: _ }, state))
4431(if scalar.is_int())
4441(prove_assignable(env, assumptions, state, rhs_ty, &place.ty) => state)
4462(access_permitted(env, assumptions, state, Access::new(AccessKind::Read, place), places_live_before_write) => state)
4471(access_permitted(env, assumptions, state, Access::new(AccessKind::Write, place), places_live_on_exit) => state)
448N/A(let state = kill_loans(place, state))
──────── ("assign-op")
4507(borrow_check_expr(env, assumptions, state, Expr::AssignOp { place, op: _, rhs }, places_live_on_exit) => (Ty::unit(), state))
call
LineCoverageSource
4556(borrow_check_expr(
env,
assumptions,
state,
callee,
args.live_before(env, &state, places_live),
) => (callee_ty, state))
464✗(prove_ty_is_rigid(env, assumptions, state, callee_ty) => (RigidTy { name: RigidName::FnDef(fn_id), parameters }, state))
467✗(let Fn { id: _, safety, binder } = env.crates().fn_named(fn_id)?)
469✗(ProvenSet::singleton((safety, ProofTree::leaf("safety"))) => Safety::Safe)
470✗(let FnBoundData { input_args, output_ty, where_clauses, body: _ } =
binder.instantiate_with(parameters)?)
474N/A(let input_tys: Vec<Ty> = input_args.iter().map(|a| a.ty.clone()).collect())
4751(if input_tys.len() == args.len())
477✗(for_all(i in 0..args.len()) with(state)
(borrow_check_expr_has_ty(env, assumptions, state, &args[i], &input_tys[i], places_live) => state))
480✗(prove_where_clauses(env, assumptions, state, where_clauses) => state)
──────── ("call")
48241(borrow_check_expr(env, assumptions, state, Expr::Call { callee, args }, places_live) => (output_ty, state))
binop
LineCoverageSource
4851(borrow_check_expr(env, assumptions, state, lhs, rhs.live_before(env, &state, places_live_on_exit)) => (lhs_ty, state))
486✗(prove_ty_is_rigid(env, assumptions, state, &lhs_ty) => (RigidTy {name: RigidName::ScalarId(scalar), parameters: _}, state))
4871(if scalar.is_int())
4883(borrow_check_expr_has_ty(env, assumptions, state, rhs, &lhs_ty, places_live_on_exit) => state)
──────── ("binop")
49023(borrow_check_expr(env, assumptions, state, Expr::BinOp{lhs, op: _, rhs}, places_live_on_exit) => (lhs_ty, state))
literal
LineCoverageSource
──────── ("literal")
495114(borrow_check_expr(_env, _assumptions, state, Literal { value: _, ty }, _places_live_on_exit) => (ty, state))
true
LineCoverageSource
──────── ("true")
50028(borrow_check_expr(_env, _assumptions, state, Expr::True, _places_live_on_exit) => (ScalarId::Bool, state))
false
LineCoverageSource
──────── ("false")
5057(borrow_check_expr(_env, _assumptions, state, Expr::False, _places_live_on_exit) => (ScalarId::Bool, state))
ref
LineCoverageSource
509✗(borrow_check_place_expr(
env,
assumptions,
state,
place,
) => (place, state))
517N/A(let access_kind = match kind {
RefKind::Shared => AccessKind::Read,
RefKind::Mut => AccessKind::Write,
})
5218(access_permitted(
env,
assumptions,
state,
Access::new(access_kind, place),
places_live_on_exit,
) => state)
530N/A(let state = state.with_loan(Loan::new(lt, place, kind)))
531N/A(let state = state.with_outlives(&reborrow_constraints(place, lt)))
5381(verify_universal_outlives(env, assumptions, &state.current.outlives) => ())
539N/A(let ty = place.ty.ref_ty_of_kind(kind, lt))
──────── ("ref")
54141(borrow_check_expr(env, assumptions, state, Expr::Ref { kind, lt, place }, places_live_on_exit) => (ty, state))
place
LineCoverageSource
5452(borrow_check_place_expr(env, assumptions, state, place) => (place, state))
546✗(access_kind_for_place_use(env, assumptions, state, place) => (access_kind, state))
54717(access_permitted(env, assumptions, state, Access::new(access_kind, place), places_live_on_exit) => state)
548N/A(let state = if matches!(access_kind, AccessKind::Move) { state.with_uninit(&place.to_place_expression()) } else { state.clone() })
5493(prove_place_is_movable(env, assumptions, state, place) => state)
──────── ("place")
551100(borrow_check_expr(env, assumptions, state, Expr::Place(place), places_live_on_exit) => (&place.ty, state))
fn-name
LineCoverageSource
557✗(if let PlaceExpr::Var(id) = place)
558✗(if !state.has_local(id))
5592(borrow_check_fn_ref(env, assumptions, state, id, Vec::<Parameter>::new()) => (ty, state))
──────── ("fn-name")
56114(borrow_check_expr(env, assumptions, state, Expr::Place(place), _places_live_on_exit) => (ty, state))
turbofish
LineCoverageSource
5666(borrow_check_fn_ref(env, assumptions, state, id, args) => (ty, state))
──────── ("turbofish")
56830(borrow_check_expr(env, assumptions, state, Expr::Turbofish { id, args }, _places_live_on_exit) => (ty, state))
struct
LineCoverageSource
5881(let Struct { id: _, binder } = env.crates().struct_named(&adt_id)?)
589✗(if turbofish.parameters.len() == binder.len())
590✗(let StructBoundData { where_clauses, fields } = binder.instantiate_with(&turbofish.parameters)?)
593N/A(let expected_names: Set<FieldName> = for_all field in fields => field.name)
594N/A(let provided_names: Set<FieldName> = for_all field in field_exprs => field.name)
595✗(if expected_names == provided_names)
5991(if field_exprs.len() == provided_names.len())
602✗(for_all(i in 0..field_exprs.len()) with(state)
(field in fields)
(if field.name == field_exprs[i].name)
(borrow_check_expr_has_ty(env, assumptions, state, &field_exprs[i].value, &field.ty, places_live_on_exit) => state))
607✗(prove_where_clauses(env, assumptions, state, where_clauses) => state)
609N/A(let ty = RigidTy::new(adt_id, &turbofish.parameters))
──────── ("struct")
61119(borrow_check_expr(env, assumptions, state, Expr::Struct { adt_id, turbofish, field_exprs }, places_live_on_exit) => (ty, state))

How to read this page