@@ -307,13 +307,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
307
307
} else if lang_items. drop_trait ( ) == Some ( def_id)
308
308
&& obligation. predicate . skip_binder ( ) . constness == ty:: BoundConstness :: ConstIfConst
309
309
{
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) ;
317
311
} else {
318
312
if lang_items. clone_trait ( ) == Some ( def_id) {
319
313
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -918,139 +912,77 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
918
912
}
919
913
}
920
914
921
- fn assemble_const_drop_candidates < ' a > (
915
+ fn assemble_const_drop_candidates (
922
916
& mut self ,
923
917
obligation : & TraitObligation < ' tcx > ,
924
- obligation_stack : & TraitObligationStack < ' a , ' tcx > ,
925
918
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
+ }
1014
926
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
+ }
1020
941
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
+ }
1024
963
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
+ ) ;
1028
971
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) ) ) ;
1045
976
}
1046
- debug ! ( "not returning" ) ;
977
+ } else {
978
+ // Otherwise check the ADT like a built-in type (structurally)
979
+ candidates. vec . push ( ConstDropCandidate ( None ) ) ;
1047
980
}
1048
981
}
1049
- debug ! ( ?stack, "assemble_const_drop_candidates - in loop" ) ;
1050
- }
1051
- // all types have passed.
1052
- candidates. vec . push ( ConstDropCandidate ) ;
1053
982
1054
- Ok ( ( ) )
983
+ ty:: Infer ( _) => {
984
+ candidates. ambiguous = true ;
985
+ }
986
+ }
1055
987
}
1056
988
}
0 commit comments