Skip to content

Commit 6f3db69

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 6f3db69

File tree

9 files changed

+59
-63
lines changed

9 files changed

+59
-63
lines changed

compiler/rustc_hir_typeck/src/cast.rs

+36-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,47 @@ fn make_invalid_casting_error<'a, 'tcx>(
194194
)
195195
}
196196

197+
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
198+
/// the cast. In certain cases, including some invalid casts from array references
199+
/// to pointers, this may cause additional errors to be emitted and/or ICE error
200+
/// messages. This function will panic if that occurs.
201+
///
202+
/// This is a helper used from clippy.
203+
pub fn check_cast<'tcx>(
204+
tcx: TyCtxt<'tcx>,
205+
param_env: ty::ParamEnv<'tcx>,
206+
e: &'tcx hir::Expr<'tcx>,
207+
from_ty: Ty<'tcx>,
208+
to_ty: Ty<'tcx>,
209+
) -> Option<CastKind> {
210+
let hir_id = e.hir_id;
211+
let local_def_id = hir_id.owner.def_id;
212+
213+
let root_ctxt = crate::TypeckRootCtxt::new(tcx, local_def_id);
214+
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, local_def_id);
215+
216+
if let Ok(check) = CastCheck::new(
217+
&fn_ctxt, e, from_ty, to_ty,
218+
// We won't show any error to the user, so we don't care what the span is here.
219+
DUMMY_SP, DUMMY_SP,
220+
) {
221+
check.do_check(&fn_ctxt).ok()
222+
} else {
223+
None
224+
}
225+
}
226+
197227
impl<'a, 'tcx> CastCheck<'tcx> {
198-
pub fn new(
228+
pub(crate) fn new(
199229
fcx: &FnCtxt<'a, 'tcx>,
200230
expr: &'tcx hir::Expr<'tcx>,
201231
expr_ty: Ty<'tcx>,
202232
cast_ty: Ty<'tcx>,
203233
cast_span: Span,
204234
span: Span,
205-
constness: hir::Constness,
206235
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
207236
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 };
237+
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
209238

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

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)