@@ -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,47 @@ 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 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
+
197
227
impl < ' a , ' tcx > CastCheck < ' tcx > {
198
- pub fn new (
228
+ pub ( crate ) fn new (
199
229
fcx : & FnCtxt < ' a , ' tcx > ,
200
230
expr : & ' tcx hir:: Expr < ' tcx > ,
201
231
expr_ty : Ty < ' tcx > ,
202
232
cast_ty : Ty < ' tcx > ,
203
233
cast_span : Span ,
204
234
span : Span ,
205
- constness : hir:: Constness ,
206
235
) -> Result < CastCheck < ' tcx > , ErrorGuaranteed > {
207
236
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 } ;
209
238
210
239
// For better error messages, check for some obviously unsized
211
240
// cases now. We do a more thorough check at the end, once
@@ -644,7 +673,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
644
673
/// Checks a cast, and report an error if one exists. In some cases, this
645
674
/// can return Ok and create type errors in the fcx rather than returning
646
675
/// 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 > {
648
677
use rustc_middle:: ty:: cast:: CastTy :: * ;
649
678
use rustc_middle:: ty:: cast:: IntTy :: * ;
650
679
0 commit comments