1818// definitely contains interior mutability.
1919
2020use clippy_config:: Conf ;
21- use clippy_utils:: consts:: { ConstEvalCtxt , Constant } ;
21+ use clippy_utils:: consts:: { ConstEvalCtxt , Constant , const_item_rhs_to_expr } ;
2222use clippy_utils:: diagnostics:: { span_lint, span_lint_and_then} ;
2323use clippy_utils:: is_in_const_context;
2424use clippy_utils:: macros:: macro_backtrace;
@@ -28,7 +28,8 @@ use rustc_data_structures::fx::FxHashMap;
2828use rustc_hir:: def:: { DefKind , Res } ;
2929use rustc_hir:: def_id:: { DefId , DefIdSet } ;
3030use rustc_hir:: {
31- Expr , ExprKind , ImplItem , ImplItemKind , Item , ItemKind , Node , StructTailExpr , TraitItem , TraitItemKind , UnOp ,
31+ ConstArgKind , ConstItemRhs , Expr , ExprKind , ImplItem , ImplItemKind , Item , ItemKind , Node , StructTailExpr ,
32+ TraitItem , TraitItemKind , UnOp ,
3233} ;
3334use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
3435use rustc_middle:: mir:: { ConstValue , UnevaluatedConst } ;
@@ -272,6 +273,7 @@ impl<'tcx> NonCopyConst<'tcx> {
272273
273274 /// Checks if a value of the given type is `Freeze`, or may be depending on the value.
274275 fn is_ty_freeze ( & mut self , tcx : TyCtxt < ' tcx > , typing_env : TypingEnv < ' tcx > , ty : Ty < ' tcx > ) -> IsFreeze {
276+ // FIXME: this should probably be using the trait solver
275277 let ty = tcx. try_normalize_erasing_regions ( typing_env, ty) . unwrap_or ( ty) ;
276278 match self . freeze_tys . entry ( ty) {
277279 Entry :: Occupied ( e) => * e. get ( ) ,
@@ -695,21 +697,22 @@ impl<'tcx> NonCopyConst<'tcx> {
695697
696698impl < ' tcx > LateLintPass < ' tcx > for NonCopyConst < ' tcx > {
697699 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) {
698- if let ItemKind :: Const ( ident, .., body_id ) = item. kind
700+ if let ItemKind :: Const ( ident, .., ct_rhs ) = item. kind
699701 && !ident. is_special ( )
700702 && let ty = cx. tcx . type_of ( item. owner_id ) . instantiate_identity ( )
701703 && match self . is_ty_freeze ( cx. tcx , cx. typing_env ( ) , ty) {
702704 IsFreeze :: No => true ,
703705 IsFreeze :: Yes => false ,
704706 IsFreeze :: Maybe => match cx. tcx . const_eval_poly ( item. owner_id . to_def_id ( ) ) {
705707 Ok ( val) if let Ok ( is_freeze) = self . is_value_freeze ( cx. tcx , cx. typing_env ( ) , ty, val) => !is_freeze,
706- _ => !self . is_init_expr_freeze (
708+ // FIXME: we just assume mgca rhs's are freeze
709+ _ => const_item_rhs_to_expr ( cx. tcx , ct_rhs) . map_or ( false , |e| !self . is_init_expr_freeze (
707710 cx. tcx ,
708711 cx. typing_env ( ) ,
709712 cx. tcx . typeck ( item. owner_id ) ,
710713 GenericArgs :: identity_for_item ( cx. tcx , item. owner_id ) ,
711- cx . tcx . hir_body ( body_id ) . value ,
712- ) ,
714+ e
715+ ) ) ,
713716 } ,
714717 }
715718 && !item. span . in_external_macro ( cx. sess ( ) . source_map ( ) )
@@ -736,22 +739,25 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
736739 }
737740
738741 fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < ' _ > ) {
739- if let TraitItemKind :: Const ( _, body_id_opt ) = item. kind
742+ if let TraitItemKind :: Const ( _, ct_rhs_opt ) = item. kind
740743 && let ty = cx. tcx . type_of ( item. owner_id ) . instantiate_identity ( )
741744 && match self . is_ty_freeze ( cx. tcx , cx. typing_env ( ) , ty) {
742745 IsFreeze :: No => true ,
743- IsFreeze :: Maybe if let Some ( body_id ) = body_id_opt => {
746+ IsFreeze :: Maybe if let Some ( ct_rhs ) = ct_rhs_opt => {
744747 match cx. tcx . const_eval_poly ( item. owner_id . to_def_id ( ) ) {
745748 Ok ( val) if let Ok ( is_freeze) = self . is_value_freeze ( cx. tcx , cx. typing_env ( ) , ty, val) => {
746749 !is_freeze
747750 } ,
748- _ => !self . is_init_expr_freeze (
749- cx. tcx ,
750- cx. typing_env ( ) ,
751- cx. tcx . typeck ( item. owner_id ) ,
752- GenericArgs :: identity_for_item ( cx. tcx , item. owner_id ) ,
753- cx. tcx . hir_body ( body_id) . value ,
754- ) ,
751+ // FIXME: we just assume mgca rhs's are freeze
752+ _ => const_item_rhs_to_expr ( cx. tcx , ct_rhs) . map_or ( false , |e| {
753+ !self . is_init_expr_freeze (
754+ cx. tcx ,
755+ cx. typing_env ( ) ,
756+ cx. tcx . typeck ( item. owner_id ) ,
757+ GenericArgs :: identity_for_item ( cx. tcx , item. owner_id ) ,
758+ e,
759+ )
760+ } ) ,
755761 }
756762 } ,
757763 IsFreeze :: Yes | IsFreeze :: Maybe => false ,
@@ -768,7 +774,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
768774 }
769775
770776 fn check_impl_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx ImplItem < ' _ > ) {
771- if let ImplItemKind :: Const ( _, body_id ) = item. kind
777+ if let ImplItemKind :: Const ( _, ct_rhs ) = item. kind
772778 && let ty = cx. tcx . type_of ( item. owner_id ) . instantiate_identity ( )
773779 && match self . is_ty_freeze ( cx. tcx , cx. typing_env ( ) , ty) {
774780 IsFreeze :: Yes => false ,
@@ -799,13 +805,16 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
799805 // interior mutability.
800806 IsFreeze :: Maybe => match cx. tcx . const_eval_poly ( item. owner_id . to_def_id ( ) ) {
801807 Ok ( val) if let Ok ( is_freeze) = self . is_value_freeze ( cx. tcx , cx. typing_env ( ) , ty, val) => !is_freeze,
802- _ => !self . is_init_expr_freeze (
803- cx. tcx ,
804- cx. typing_env ( ) ,
805- cx. tcx . typeck ( item. owner_id ) ,
806- GenericArgs :: identity_for_item ( cx. tcx , item. owner_id ) ,
807- cx. tcx . hir_body ( body_id) . value ,
808- ) ,
808+ // FIXME: we just assume mgca rhs's are freeze
809+ _ => const_item_rhs_to_expr ( cx. tcx , ct_rhs) . map_or ( false , |e| {
810+ !self . is_init_expr_freeze (
811+ cx. tcx ,
812+ cx. typing_env ( ) ,
813+ cx. tcx . typeck ( item. owner_id ) ,
814+ GenericArgs :: identity_for_item ( cx. tcx , item. owner_id ) ,
815+ e,
816+ )
817+ } ) ,
809818 } ,
810819 }
811820 && !item. span . in_external_macro ( cx. sess ( ) . source_map ( ) )
@@ -913,20 +922,26 @@ fn get_const_hir_value<'tcx>(
913922 args : GenericArgsRef < ' tcx > ,
914923) -> Option < ( & ' tcx TypeckResults < ' tcx > , & ' tcx Expr < ' tcx > ) > {
915924 let did = did. as_local ( ) ?;
916- let ( did, body_id ) = match tcx. hir_node ( tcx. local_def_id_to_hir_id ( did) ) {
917- Node :: Item ( item) if let ItemKind :: Const ( .., body_id ) = item. kind => ( did, body_id ) ,
918- Node :: ImplItem ( item) if let ImplItemKind :: Const ( .., body_id ) = item. kind => ( did, body_id ) ,
925+ let ( did, ct_rhs ) = match tcx. hir_node ( tcx. local_def_id_to_hir_id ( did) ) {
926+ Node :: Item ( item) if let ItemKind :: Const ( .., ct_rhs ) = item. kind => ( did, ct_rhs ) ,
927+ Node :: ImplItem ( item) if let ImplItemKind :: Const ( .., ct_rhs ) = item. kind => ( did, ct_rhs ) ,
919928 Node :: TraitItem ( _)
920929 if let Ok ( Some ( inst) ) = Instance :: try_resolve ( tcx, typing_env, did. into ( ) , args)
921930 && let Some ( did) = inst. def_id ( ) . as_local ( ) =>
922931 {
923932 match tcx. hir_node ( tcx. local_def_id_to_hir_id ( did) ) {
924- Node :: ImplItem ( item) if let ImplItemKind :: Const ( .., body_id ) = item. kind => ( did, body_id ) ,
925- Node :: TraitItem ( item) if let TraitItemKind :: Const ( .., Some ( body_id ) ) = item. kind => ( did, body_id ) ,
933+ Node :: ImplItem ( item) if let ImplItemKind :: Const ( .., ct_rhs ) = item. kind => ( did, ct_rhs ) ,
934+ Node :: TraitItem ( item) if let TraitItemKind :: Const ( .., Some ( ct_rhs ) ) = item. kind => ( did, ct_rhs ) ,
926935 _ => return None ,
927936 }
928937 } ,
929938 _ => return None ,
930939 } ;
931- Some ( ( tcx. typeck ( did) , tcx. hir_body ( body_id) . value ) )
940+ match ct_rhs {
941+ ConstItemRhs :: Body ( body_id) => Some ( ( tcx. typeck ( did) , tcx. hir_body ( body_id) . value ) ) ,
942+ ConstItemRhs :: TypeConst ( ct_arg) => match ct_arg. kind {
943+ ConstArgKind :: Anon ( anon_const) => Some ( ( tcx. typeck ( did) , tcx. hir_body ( anon_const. body ) . value ) ) ,
944+ _ => None ,
945+ } ,
946+ }
932947}
0 commit comments