@@ -40,17 +40,19 @@ use rustc_middle::mir::Mutability;
40
40
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
41
41
use rustc_middle:: ty:: cast:: { CastKind , CastTy } ;
42
42
use rustc_middle:: ty:: error:: TypeError ;
43
+ use rustc_middle:: ty:: TyCtxt ;
43
44
use rustc_middle:: ty:: { self , Ty , TypeAndMut , TypeVisitableExt , VariantDef } ;
44
45
use rustc_session:: lint;
45
46
use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
46
47
use rustc_span:: symbol:: sym;
47
48
use rustc_span:: Span ;
49
+ use rustc_span:: DUMMY_SP ;
48
50
use rustc_trait_selection:: infer:: InferCtxtExt ;
49
51
50
52
/// Reifies a cast check to be checked once we have full type information for
51
53
/// a function context.
52
54
#[ derive( Debug ) ]
53
- pub struct CastCheck < ' tcx > {
55
+ pub ( crate ) struct CastCheck < ' tcx > {
54
56
/// The expression whose value is being casted
55
57
expr : & ' tcx hir:: Expr < ' tcx > ,
56
58
/// The source type for the cast expression
@@ -60,8 +62,6 @@ pub struct CastCheck<'tcx> {
60
62
cast_ty : Ty < ' tcx > ,
61
63
cast_span : Span ,
62
64
span : Span ,
63
- /// whether the cast is made in a const context or not.
64
- pub constness : hir:: Constness ,
65
65
}
66
66
67
67
/// The kind of pointer and associated metadata (thin, length or vtable) - we
@@ -194,18 +194,45 @@ fn make_invalid_casting_error<'a, 'tcx>(
194
194
)
195
195
}
196
196
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
+
197
225
impl < ' a , ' tcx > CastCheck < ' tcx > {
198
- pub fn new (
226
+ pub ( crate ) fn new (
199
227
fcx : & FnCtxt < ' a , ' tcx > ,
200
228
expr : & ' tcx hir:: Expr < ' tcx > ,
201
229
expr_ty : Ty < ' tcx > ,
202
230
cast_ty : Ty < ' tcx > ,
203
231
cast_span : Span ,
204
232
span : Span ,
205
- constness : hir:: Constness ,
206
233
) -> Result < CastCheck < ' tcx > , ErrorGuaranteed > {
207
234
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 } ;
209
236
210
237
// For better error messages, check for some obviously unsized
211
238
// cases now. We do a more thorough check at the end, once
@@ -644,7 +671,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
644
671
/// Checks a cast, and report an error if one exists. In some cases, this
645
672
/// can return Ok and create type errors in the fcx rather than returning
646
673
/// 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 > {
648
675
use rustc_middle:: ty:: cast:: CastTy :: * ;
649
676
use rustc_middle:: ty:: cast:: IntTy :: * ;
650
677
0 commit comments