@@ -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,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+
197225impl < ' 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
0 commit comments