Skip to content

Commit a9edbfd

Browse files
committed
Stop exporting TypeckRootCtxt and FnCtxt.
While they have many convenient APIs, it is better to expose dedicated functions for them
1 parent 7a495cc commit a9edbfd

File tree

9 files changed

+57
-63
lines changed

9 files changed

+57
-63
lines changed

compiler/rustc_hir_typeck/src/cast.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,19 @@ use rustc_middle::mir::Mutability;
4040
use rustc_middle::ty::adjustment::AllowTwoPhase;
4141
use rustc_middle::ty::cast::{CastKind, CastTy};
4242
use rustc_middle::ty::error::TypeError;
43+
use rustc_middle::ty::TyCtxt;
4344
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
4445
use rustc_session::lint;
4546
use rustc_span::def_id::{DefId, LOCAL_CRATE};
4647
use rustc_span::symbol::sym;
4748
use rustc_span::Span;
49+
use rustc_span::DUMMY_SP;
4850
use rustc_trait_selection::infer::InferCtxtExt;
4951

5052
/// Reifies a cast check to be checked once we have full type information for
5153
/// a function context.
5254
#[derive(Debug)]
53-
pub struct CastCheck<'tcx> {
55+
pub(crate) struct CastCheck<'tcx> {
5456
/// The expression whose value is being casted
5557
expr: &'tcx hir::Expr<'tcx>,
5658
/// The source type for the cast expression
@@ -60,8 +62,6 @@ pub struct CastCheck<'tcx> {
6062
cast_ty: Ty<'tcx>,
6163
cast_span: Span,
6264
span: Span,
63-
/// whether the cast is made in a const context or not.
64-
pub constness: hir::Constness,
6565
}
6666

6767
/// The kind of pointer and associated metadata (thin, length or vtable) - we
@@ -194,18 +194,45 @@ fn make_invalid_casting_error<'a, 'tcx>(
194194
)
195195
}
196196

197+
/// If a cast from `from_ty` to `to_ty` is valid, returns a `Some` containing the kind
198+
/// of the cast.
199+
///
200+
/// This is a helper used from clippy.
201+
pub fn check_cast<'tcx>(
202+
tcx: TyCtxt<'tcx>,
203+
param_env: ty::ParamEnv<'tcx>,
204+
e: &'tcx hir::Expr<'tcx>,
205+
from_ty: Ty<'tcx>,
206+
to_ty: Ty<'tcx>,
207+
) -> Option<CastKind> {
208+
let hir_id = e.hir_id;
209+
let local_def_id = hir_id.owner.def_id;
210+
211+
let root_ctxt = crate::TypeckRootCtxt::new(tcx, local_def_id);
212+
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, local_def_id);
213+
214+
if let Ok(check) = CastCheck::new(
215+
&fn_ctxt, e, from_ty, to_ty,
216+
// We won't show any errors to the user, so the span is irrelevant here.
217+
DUMMY_SP, DUMMY_SP,
218+
) {
219+
check.do_check(&fn_ctxt).ok()
220+
} else {
221+
None
222+
}
223+
}
224+
197225
impl<'a, 'tcx> CastCheck<'tcx> {
198-
pub fn new(
226+
pub(crate) fn new(
199227
fcx: &FnCtxt<'a, 'tcx>,
200228
expr: &'tcx hir::Expr<'tcx>,
201229
expr_ty: Ty<'tcx>,
202230
cast_ty: Ty<'tcx>,
203231
cast_span: Span,
204232
span: Span,
205-
constness: hir::Constness,
206233
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
207234
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
208-
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness };
235+
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
209236

210237
// For better error messages, check for some obviously unsized
211238
// cases now. We do a more thorough check at the end, once
@@ -644,7 +671,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
644671
/// Checks a cast, and report an error if one exists. In some cases, this
645672
/// can return Ok and create type errors in the fcx rather than returning
646673
/// directly. coercion-cast is handled in check instead of here.
647-
pub fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
674+
fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
648675
use rustc_middle::ty::cast::CastTy::*;
649676
use rustc_middle::ty::cast::IntTy::*;
650677

compiler/rustc_hir_typeck/src/coercion.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13181318
}
13191319
}
13201320

1321+
/// Check whether `ty` can be coerced to `output_ty`.
1322+
/// Used from clippy.
1323+
pub fn can_coerce<'tcx>(
1324+
tcx: TyCtxt<'tcx>,
1325+
param_env: ty::ParamEnv<'tcx>,
1326+
body_id: LocalDefId,
1327+
ty: Ty<'tcx>,
1328+
output_ty: Ty<'tcx>,
1329+
) -> bool {
1330+
let root_ctxt = crate::typeck_root_ctxt::TypeckRootCtxt::new(tcx, body_id);
1331+
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, body_id);
1332+
fn_ctxt.can_coerce(ty, output_ty)
1333+
}
1334+
13211335
/// CoerceMany encapsulates the pattern you should use when you have
13221336
/// many expressions that are all getting coerced to a common
13231337
/// type. This arises, for example, when you have a match (the result

compiler/rustc_hir_typeck/src/expr.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -1390,15 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13901390
} else {
13911391
// Defer other checks until we're done type checking.
13921392
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
1393-
match cast::CastCheck::new(
1394-
self,
1395-
e,
1396-
t_expr,
1397-
t_cast,
1398-
t.span,
1399-
expr.span,
1400-
hir::Constness::NotConst,
1401-
) {
1393+
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
14021394
Ok(cast_check) => {
14031395
debug!(
14041396
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use std::ops::Deref;
3838
///
3939
/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
4040
/// [`InferCtxt`]: infer::InferCtxt
41-
pub struct FnCtxt<'a, 'tcx> {
41+
pub(crate) struct FnCtxt<'a, 'tcx> {
4242
pub(super) body_id: LocalDefId,
4343

4444
/// The parameter environment used for proving trait obligations

compiler/rustc_hir_typeck/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ mod typeck_root_ctxt;
4242
mod upvar;
4343
mod writeback;
4444

45-
pub use fn_ctxt::FnCtxt;
46-
pub use typeck_root_ctxt::TypeckRootCtxt;
45+
pub use coercion::can_coerce;
46+
use fn_ctxt::FnCtxt;
47+
use typeck_root_ctxt::TypeckRootCtxt;
4748

4849
use crate::check::check_fn;
4950
use crate::coercion::DynamicCoerceMany;

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::ops::Deref;
2727
/// `bar()` will each have their own `FnCtxt`, but they will
2828
/// share the inference context, will process obligations together,
2929
/// can access each other's local types (scoping permitted), etc.
30-
pub struct TypeckRootCtxt<'tcx> {
30+
pub(crate) struct TypeckRootCtxt<'tcx> {
3131
pub(super) infcx: InferCtxt<'tcx>,
3232

3333
pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,

src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_errors::Applicability;
1212
use rustc_hir::def::{DefKind, Res};
1313
use rustc_hir::def_id::DefId;
1414
use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
15-
use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt};
1615
use rustc_infer::infer::TyCtxtInferExt;
1716
use rustc_lint::LateContext;
1817
use rustc_middle::mir::Mutability;
@@ -437,9 +436,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
437436
Node::Item(item) => {
438437
if let ItemKind::Fn(_, _, body_id) = &item.kind
439438
&& let output_ty = return_ty(cx, item.owner_id)
440-
&& let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id)
441-
&& let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id)
442-
&& fn_ctxt.can_coerce(ty, output_ty)
439+
&& rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty)
443440
{
444441
if has_lifetime(output_ty) && has_lifetime(ty) {
445442
return false;

src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::utils::check_cast;
1+
use rustc_hir_typeck::cast::check_cast;
22
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
33
use clippy_utils::diagnostics::span_lint_and_sugg;
44
use clippy_utils::sugg::Sugg;
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
2222
) -> bool {
2323
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
2424
let mut app = Applicability::MachineApplicable;
25-
let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
25+
let mut sugg = match check_cast(cx.tcx, cx.param_env, e, from_ty, to_ty) {
2626
Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false,
2727
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
2828
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
use rustc_hir as hir;
2-
use rustc_hir::Expr;
3-
use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt};
41
use rustc_lint::LateContext;
5-
use rustc_middle::ty::cast::CastKind;
62
use rustc_middle::ty::Ty;
7-
use rustc_span::DUMMY_SP;
83

94
// check if the component types of the transmuted collection and the result have different ABI,
105
// size or alignment
@@ -20,35 +15,3 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
2015
false
2116
}
2217
}
23-
24-
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
25-
/// the cast. In certain cases, including some invalid casts from array references
26-
/// to pointers, this may cause additional errors to be emitted and/or ICE error
27-
/// messages. This function will panic if that occurs.
28-
pub(super) fn check_cast<'tcx>(
29-
cx: &LateContext<'tcx>,
30-
e: &'tcx Expr<'_>,
31-
from_ty: Ty<'tcx>,
32-
to_ty: Ty<'tcx>,
33-
) -> Option<CastKind> {
34-
let hir_id = e.hir_id;
35-
let local_def_id = hir_id.owner.def_id;
36-
37-
let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id);
38-
let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id);
39-
40-
if let Ok(check) = cast::CastCheck::new(
41-
&fn_ctxt,
42-
e,
43-
from_ty,
44-
to_ty,
45-
// We won't show any error to the user, so we don't care what the span is here.
46-
DUMMY_SP,
47-
DUMMY_SP,
48-
hir::Constness::NotConst,
49-
) {
50-
check.do_check(&fn_ctxt).ok()
51-
} else {
52-
None
53-
}
54-
}

0 commit comments

Comments
 (0)