@@ -40,17 +40,19 @@ use rustc_middle::mir::Mutability;
4040use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
4141use rustc_middle:: ty:: cast:: { CastKind , CastTy } ;
4242use rustc_middle:: ty:: error:: TypeError ;
43+ use rustc_middle:: ty:: TyCtxt ;
4344use rustc_middle:: ty:: { self , Ty , TypeAndMut , TypeVisitableExt , VariantDef } ;
4445use rustc_session:: lint;
4546use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
4647use rustc_span:: symbol:: sym;
4748use rustc_span:: Span ;
49+ use rustc_span:: DUMMY_SP ;
4850use 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+
197227impl < ' 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
0 commit comments