@@ -5,17 +5,15 @@ use rustc_hir as hir;
5
5
use rustc_hir:: def_id:: DefId ;
6
6
use rustc_index:: bit_set:: BitSet ;
7
7
use rustc_infer:: infer:: TyCtxtInferExt ;
8
- use rustc_infer:: traits:: { ImplSource , Obligation , ObligationCause } ;
8
+ use rustc_infer:: traits:: ObligationCause ;
9
9
use rustc_middle:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor } ;
10
10
use rustc_middle:: mir:: * ;
11
- use rustc_middle:: traits:: BuiltinImplSource ;
12
- use rustc_middle:: ty:: GenericArgs ;
13
- use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , InstanceDef , Ty , TyCtxt } ;
14
- use rustc_middle:: ty:: { TraitRef , TypeVisitableExt } ;
11
+ use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Ty , TyCtxt } ;
12
+ use rustc_middle:: ty:: { Instance , InstanceDef , TypeVisitableExt } ;
15
13
use rustc_mir_dataflow:: Analysis ;
16
14
use rustc_span:: { sym, Span , Symbol } ;
17
15
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
18
- use rustc_trait_selection:: traits:: { self , ObligationCauseCode , ObligationCtxt , SelectionContext } ;
16
+ use rustc_trait_selection:: traits:: { self , ObligationCauseCode , ObligationCtxt } ;
19
17
use rustc_type_ir:: visit:: { TypeSuperVisitable , TypeVisitor } ;
20
18
21
19
use std:: mem;
@@ -756,143 +754,43 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
756
754
infcx. err_ctxt ( ) . report_fulfillment_errors ( errors) ;
757
755
}
758
756
757
+ let mut is_trait = false ;
759
758
// Attempting to call a trait method?
760
- // FIXME(effects) do we need this?
761
- if let Some ( trait_id) = tcx. trait_of_item ( callee) {
759
+ if tcx. trait_of_item ( callee) . is_some ( ) {
762
760
trace ! ( "attempting to call a trait method" ) ;
763
- if !self . tcx . features ( ) . const_trait_impl {
761
+ // trait method calls are only permitted when `effects` is enabled.
762
+ // we don't error, since that is handled by typeck. We try to resolve
763
+ // the trait into the concrete method, and uses that for const stability
764
+ // checks.
765
+ // FIXME(effects) we might consider moving const stability checks to typeck as well.
766
+ if tcx. features ( ) . effects {
767
+ is_trait = true ;
768
+
769
+ if let Ok ( Some ( instance) ) =
770
+ Instance :: resolve ( tcx, param_env, callee, fn_args)
771
+ && let InstanceDef :: Item ( def) = instance. def
772
+ {
773
+ // Resolve a trait method call to its concrete implementation, which may be in a
774
+ // `const` trait impl. This is only used for the const stability check below, since
775
+ // we want to look at the concrete impl's stability.
776
+ fn_args = instance. args ;
777
+ callee = def;
778
+ }
779
+ } else {
764
780
self . check_op ( ops:: FnCallNonConst {
765
781
caller,
766
782
callee,
767
783
args : fn_args,
768
784
span : * fn_span,
769
785
call_source : * call_source,
770
- feature : Some ( sym:: const_trait_impl) ,
786
+ feature : Some ( if tcx. features ( ) . const_trait_impl {
787
+ sym:: effects
788
+ } else {
789
+ sym:: const_trait_impl
790
+ } ) ,
771
791
} ) ;
772
792
return ;
773
793
}
774
-
775
- let trait_ref = TraitRef :: from_method ( tcx, trait_id, fn_args) ;
776
- let obligation =
777
- Obligation :: new ( tcx, ObligationCause :: dummy ( ) , param_env, trait_ref) ;
778
-
779
- let implsrc = {
780
- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
781
- let mut selcx = SelectionContext :: new ( & infcx) ;
782
- selcx. select ( & obligation)
783
- } ;
784
-
785
- match implsrc {
786
- Ok ( Some ( ImplSource :: Param ( _) ) ) if tcx. features ( ) . effects => {
787
- debug ! (
788
- "const_trait_impl: provided {:?} via where-clause in {:?}" ,
789
- trait_ref, param_env
790
- ) ;
791
- return ;
792
- }
793
- // Closure: Fn{Once|Mut}
794
- Ok ( Some ( ImplSource :: Builtin ( BuiltinImplSource :: Misc , _) ) )
795
- if trait_ref. self_ty ( ) . is_closure ( )
796
- && tcx. fn_trait_kind_from_def_id ( trait_id) . is_some ( ) =>
797
- {
798
- let ty:: Closure ( closure_def_id, fn_args) = * trait_ref. self_ty ( ) . kind ( )
799
- else {
800
- unreachable ! ( )
801
- } ;
802
- if !tcx. is_const_fn_raw ( closure_def_id) {
803
- self . check_op ( ops:: FnCallNonConst {
804
- caller,
805
- callee,
806
- args : fn_args,
807
- span : * fn_span,
808
- call_source : * call_source,
809
- feature : None ,
810
- } ) ;
811
-
812
- return ;
813
- }
814
- }
815
- Ok ( Some ( ImplSource :: UserDefined ( data) ) ) => {
816
- let callee_name = tcx. item_name ( callee) ;
817
-
818
- if let hir:: Constness :: NotConst = tcx. constness ( data. impl_def_id ) {
819
- self . check_op ( ops:: FnCallNonConst {
820
- caller,
821
- callee,
822
- args : fn_args,
823
- span : * fn_span,
824
- call_source : * call_source,
825
- feature : None ,
826
- } ) ;
827
- return ;
828
- }
829
-
830
- if let Some ( & did) = tcx
831
- . associated_item_def_ids ( data. impl_def_id )
832
- . iter ( )
833
- . find ( |did| tcx. item_name ( * * did) == callee_name)
834
- {
835
- // using internal args is ok here, since this is only
836
- // used for the `resolve` call below
837
- fn_args = GenericArgs :: identity_for_item ( tcx, did) ;
838
- callee = did;
839
- }
840
- }
841
- _ if !tcx. is_const_fn_raw ( callee) => {
842
- // At this point, it is only legal when the caller is in a trait
843
- // marked with #[const_trait], and the callee is in the same trait.
844
- let mut nonconst_call_permission = false ;
845
- if let Some ( callee_trait) = tcx. trait_of_item ( callee)
846
- && tcx. has_attr ( callee_trait, sym:: const_trait)
847
- && Some ( callee_trait) == tcx. trait_of_item ( caller. to_def_id ( ) )
848
- // Can only call methods when it's `<Self as TheTrait>::f`.
849
- && tcx. types . self_param == fn_args. type_at ( 0 )
850
- {
851
- nonconst_call_permission = true ;
852
- }
853
-
854
- if !nonconst_call_permission {
855
- let obligation = Obligation :: new (
856
- tcx,
857
- ObligationCause :: dummy_with_span ( * fn_span) ,
858
- param_env,
859
- trait_ref,
860
- ) ;
861
-
862
- // improve diagnostics by showing what failed. Our requirements are stricter this time
863
- // as we are going to error again anyways.
864
- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
865
- if let Err ( e) = implsrc {
866
- infcx. err_ctxt ( ) . report_selection_error (
867
- obligation. clone ( ) ,
868
- & obligation,
869
- & e,
870
- ) ;
871
- }
872
-
873
- self . check_op ( ops:: FnCallNonConst {
874
- caller,
875
- callee,
876
- args : fn_args,
877
- span : * fn_span,
878
- call_source : * call_source,
879
- feature : None ,
880
- } ) ;
881
- return ;
882
- }
883
- }
884
- _ => { }
885
- }
886
-
887
- // Resolve a trait method call to its concrete implementation, which may be in a
888
- // `const` trait impl.
889
- let instance = Instance :: resolve ( tcx, param_env, callee, fn_args) ;
890
- debug ! ( "Resolving ({:?}) -> {:?}" , callee, instance) ;
891
- if let Ok ( Some ( func) ) = instance {
892
- if let InstanceDef :: Item ( def) = func. def {
893
- callee = def;
894
- }
895
- }
896
794
}
897
795
898
796
// At this point, we are calling a function, `callee`, whose `DefId` is known...
@@ -925,21 +823,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
925
823
return ;
926
824
}
927
825
928
- if !tcx. is_const_fn_raw ( callee) {
929
- if !tcx. is_const_default_method ( callee) {
930
- // To get to here we must have already found a const impl for the
931
- // trait, but for it to still be non-const can be that the impl is
932
- // using default method bodies.
933
- self . check_op ( ops:: FnCallNonConst {
934
- caller,
935
- callee,
936
- args : fn_args,
937
- span : * fn_span,
938
- call_source : * call_source,
939
- feature : None ,
940
- } ) ;
941
- return ;
942
- }
826
+ if !tcx. is_const_fn_raw ( callee) && !is_trait {
827
+ self . check_op ( ops:: FnCallNonConst {
828
+ caller,
829
+ callee,
830
+ args : fn_args,
831
+ span : * fn_span,
832
+ call_source : * call_source,
833
+ feature : None ,
834
+ } ) ;
835
+ return ;
943
836
}
944
837
945
838
// If the `const fn` we are trying to call is not const-stable, ensure that we have
0 commit comments