@@ -307,13 +307,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
307307 } else if lang_items. drop_trait ( ) == Some ( def_id)
308308 && obligation. predicate . skip_binder ( ) . constness == ty:: BoundConstness :: ConstIfConst
309309 {
310- if obligation. param_env . constness ( ) == hir:: Constness :: Const {
311- self . assemble_const_drop_candidates ( obligation, stack, & mut candidates) ?;
312- } else {
313- debug ! ( "passing ~const Drop bound; in non-const context" ) ;
314- // `~const Drop` when we are not in a const context has no effect.
315- candidates. vec . push ( ConstDropCandidate )
316- }
310+ self . assemble_const_drop_candidates ( obligation, & mut candidates) ;
317311 } else {
318312 if lang_items. clone_trait ( ) == Some ( def_id) {
319313 // Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -918,139 +912,77 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
918912 }
919913 }
920914
921- fn assemble_const_drop_candidates < ' a > (
915+ fn assemble_const_drop_candidates (
922916 & mut self ,
923917 obligation : & TraitObligation < ' tcx > ,
924- obligation_stack : & TraitObligationStack < ' a , ' tcx > ,
925918 candidates : & mut SelectionCandidateSet < ' tcx > ,
926- ) -> Result < ( ) , SelectionError < ' tcx > > {
927- let mut stack: Vec < ( Ty < ' tcx > , usize ) > = vec ! [ ( obligation. self_ty( ) . skip_binder( ) , 0 ) ] ;
928-
929- while let Some ( ( ty, depth) ) = stack. pop ( ) {
930- let mut noreturn = false ;
931-
932- self . check_recursion_depth ( depth, obligation) ?;
933- let mut new_candidates = SelectionCandidateSet { vec : Vec :: new ( ) , ambiguous : false } ;
934- let mut copy_obligation =
935- obligation. with ( obligation. predicate . rebind ( ty:: TraitPredicate {
936- trait_ref : ty:: TraitRef {
937- def_id : self . tcx ( ) . require_lang_item ( hir:: LangItem :: Copy , None ) ,
938- substs : self . tcx ( ) . mk_substs_trait ( ty, & [ ] ) ,
939- } ,
940- constness : ty:: BoundConstness :: NotConst ,
941- polarity : ty:: ImplPolarity :: Positive ,
942- } ) ) ;
943- copy_obligation. recursion_depth = depth + 1 ;
944- self . assemble_candidates_from_impls ( & copy_obligation, & mut new_candidates) ;
945- let copy_conditions = self . copy_clone_conditions ( & copy_obligation) ;
946- self . assemble_builtin_bound_candidates ( copy_conditions, & mut new_candidates) ;
947- let copy_stack = self . push_stack ( obligation_stack. list ( ) , & copy_obligation) ;
948- self . assemble_candidates_from_caller_bounds ( & copy_stack, & mut new_candidates) ?;
949-
950- let const_drop_obligation =
951- obligation. with ( obligation. predicate . rebind ( ty:: TraitPredicate {
952- trait_ref : ty:: TraitRef {
953- def_id : self . tcx ( ) . require_lang_item ( hir:: LangItem :: Drop , None ) ,
954- substs : self . tcx ( ) . mk_substs_trait ( ty, & [ ] ) ,
955- } ,
956- constness : ty:: BoundConstness :: ConstIfConst ,
957- polarity : ty:: ImplPolarity :: Positive ,
958- } ) ) ;
959-
960- let const_drop_stack = self . push_stack ( obligation_stack. list ( ) , & const_drop_obligation) ;
961- self . assemble_candidates_from_caller_bounds ( & const_drop_stack, & mut new_candidates) ?;
962-
963- if !new_candidates. vec . is_empty ( ) {
964- noreturn = true ;
965- }
966- debug ! ( ?new_candidates. vec, "assemble_const_drop_candidates" ) ;
967-
968- match ty. kind ( ) {
969- ty:: Int ( _)
970- | ty:: Uint ( _)
971- | ty:: Float ( _)
972- | ty:: Infer ( ty:: IntVar ( _) )
973- | ty:: Infer ( ty:: FloatVar ( _) )
974- | ty:: FnPtr ( _)
975- | ty:: Never
976- | ty:: Ref ( ..)
977- | ty:: FnDef ( ..)
978- | ty:: RawPtr ( _)
979- | ty:: Bool
980- | ty:: Char
981- | ty:: Str
982- | ty:: Foreign ( _) => { } // Do nothing. These types satisfy `const Drop`.
983-
984- ty:: Adt ( def, subst) => {
985- let mut set = SelectionCandidateSet { vec : Vec :: new ( ) , ambiguous : false } ;
986- self . assemble_candidates_from_impls (
987- & obligation. with ( obligation. predicate . map_bound ( |mut pred| {
988- pred. trait_ref . substs = self . tcx ( ) . mk_substs_trait ( ty, & [ ] ) ;
989- pred
990- } ) ) ,
991- & mut set,
992- ) ;
993- stack. extend ( def. all_fields ( ) . map ( |f| ( f. ty ( self . tcx ( ) , subst) , depth + 1 ) ) ) ;
994-
995- debug ! ( ?set. vec, "assemble_const_drop_candidates - ty::Adt" ) ;
996- if set. vec . into_iter ( ) . any ( |candidate| {
997- if let SelectionCandidate :: ImplCandidate ( did) = candidate {
998- matches ! ( self . tcx( ) . impl_constness( did) , hir:: Constness :: NotConst )
999- } else {
1000- false
1001- }
1002- } ) {
1003- if !noreturn {
1004- // has non-const Drop
1005- return Ok ( ( ) ) ;
1006- }
1007- debug ! ( "not returning" ) ;
1008- }
1009- }
1010-
1011- ty:: Array ( ty, _) => stack. push ( ( ty, depth + 1 ) ) ,
1012-
1013- ty:: Tuple ( _) => stack. extend ( ty. tuple_fields ( ) . map ( |t| ( t, depth + 1 ) ) ) ,
919+ ) {
920+ // If the predicate is `~const Drop` in a non-const environment, we don't actually need
921+ // to check anything. We'll short-circuit checking any obligations in confirmation, too.
922+ if obligation. param_env . constness ( ) == hir:: Constness :: NotConst {
923+ candidates. vec . push ( ConstDropCandidate ( None ) ) ;
924+ return ;
925+ }
1014926
1015- ty:: Closure ( _, substs) => {
1016- let substs = substs. as_closure ( ) ;
1017- let ty = self . infcx . shallow_resolve ( substs. tupled_upvars_ty ( ) ) ;
1018- stack. push ( ( ty, depth + 1 ) ) ;
1019- }
927+ let self_ty = self . infcx ( ) . shallow_resolve ( obligation. self_ty ( ) ) ;
928+ match self_ty. skip_binder ( ) . kind ( ) {
929+ ty:: Opaque ( ..)
930+ | ty:: Dynamic ( ..)
931+ | ty:: Error ( _)
932+ | ty:: Bound ( ..)
933+ | ty:: Param ( _)
934+ | ty:: Placeholder ( _)
935+ | ty:: Never
936+ | ty:: Foreign ( _)
937+ | ty:: Projection ( _) => {
938+ // We don't know if these are `~const Drop`, at least
939+ // not structurally... so don't push a candidate.
940+ }
1020941
1021- ty:: Generator ( _, substs, _) => {
1022- let substs = substs. as_generator ( ) ;
1023- let ty = self . infcx . shallow_resolve ( substs. tupled_upvars_ty ( ) ) ;
942+ ty:: Bool
943+ | ty:: Char
944+ | ty:: Int ( _)
945+ | ty:: Uint ( _)
946+ | ty:: Float ( _)
947+ | ty:: Infer ( ty:: IntVar ( _) )
948+ | ty:: Infer ( ty:: FloatVar ( _) )
949+ | ty:: Str
950+ | ty:: RawPtr ( _)
951+ | ty:: Ref ( ..)
952+ | ty:: FnDef ( ..)
953+ | ty:: FnPtr ( _)
954+ | ty:: Array ( ..)
955+ | ty:: Slice ( _)
956+ | ty:: Closure ( ..)
957+ | ty:: Generator ( ..)
958+ | ty:: Tuple ( _)
959+ | ty:: GeneratorWitness ( _) => {
960+ // These are built-in, and cannot have a custom `impl const Drop`.
961+ candidates. vec . push ( ConstDropCandidate ( None ) ) ;
962+ }
1024963
1025- stack. push ( ( ty, depth + 1 ) ) ;
1026- stack. push ( ( substs. witness ( ) , depth + 1 ) ) ;
1027- }
964+ ty:: Adt ( ..) => {
965+ // Find a custom `impl Drop` impl, if it exists
966+ let relevant_impl = self . tcx ( ) . find_map_relevant_impl (
967+ obligation. predicate . def_id ( ) ,
968+ obligation. predicate . skip_binder ( ) . trait_ref . self_ty ( ) ,
969+ Some ,
970+ ) ;
1028971
1029- ty:: GeneratorWitness ( tys) => stack. extend (
1030- self . tcx ( ) . erase_late_bound_regions ( * tys) . iter ( ) . map ( |t| ( t, depth + 1 ) ) ,
1031- ) ,
1032-
1033- ty:: Slice ( ty) => stack. push ( ( ty, depth + 1 ) ) ,
1034-
1035- ty:: Opaque ( ..)
1036- | ty:: Dynamic ( ..)
1037- | ty:: Error ( _)
1038- | ty:: Bound ( ..)
1039- | ty:: Infer ( _)
1040- | ty:: Placeholder ( _)
1041- | ty:: Projection ( ..)
1042- | ty:: Param ( ..) => {
1043- if !noreturn {
1044- return Ok ( ( ) ) ;
972+ if let Some ( impl_def_id) = relevant_impl {
973+ // Check that `impl Drop` is actually const, if there is a custom impl
974+ if self . tcx ( ) . impl_constness ( impl_def_id) == hir:: Constness :: Const {
975+ candidates. vec . push ( ConstDropCandidate ( Some ( impl_def_id) ) ) ;
1045976 }
1046- debug ! ( "not returning" ) ;
977+ } else {
978+ // Otherwise check the ADT like a built-in type (structurally)
979+ candidates. vec . push ( ConstDropCandidate ( None ) ) ;
1047980 }
1048981 }
1049- debug ! ( ?stack, "assemble_const_drop_candidates - in loop" ) ;
1050- }
1051- // all types have passed.
1052- candidates. vec . push ( ConstDropCandidate ) ;
1053982
1054- Ok ( ( ) )
983+ ty:: Infer ( _) => {
984+ candidates. ambiguous = true ;
985+ }
986+ }
1055987 }
1056988}
0 commit comments