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