@@ -4,16 +4,18 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported};
4
4
use rustc_hir:: def_id:: DefId ;
5
5
use rustc_hir:: { self as hir, HirId , LangItem } ;
6
6
use rustc_infer:: infer:: TyCtxtInferExt ;
7
+ use rustc_infer:: traits:: { ImplSource , Obligation , ObligationCause } ;
7
8
use rustc_middle:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor } ;
8
9
use rustc_middle:: mir:: * ;
9
10
use rustc_middle:: ty:: cast:: CastTy ;
10
11
use rustc_middle:: ty:: subst:: GenericArgKind ;
11
12
use rustc_middle:: ty:: {
12
13
self , adjustment:: PointerCast , Instance , InstanceDef , Ty , TyCtxt , TypeAndMut ,
13
14
} ;
15
+ use rustc_middle:: ty:: { Binder , TraitPredicate , TraitRef } ;
14
16
use rustc_span:: { sym, Span , Symbol } ;
15
17
use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt ;
16
- use rustc_trait_selection:: traits:: { self , TraitEngine } ;
18
+ use rustc_trait_selection:: traits:: { self , SelectionContext , TraitEngine } ;
17
19
18
20
use std:: mem;
19
21
use std:: ops:: Deref ;
@@ -765,9 +767,39 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
765
767
}
766
768
} ;
767
769
768
- // Resolve a trait method call to its concrete implementation, which may be in a
769
- // `const` trait impl.
770
- if self . tcx . features ( ) . const_trait_impl {
770
+ // Attempting to call a trait method?
771
+ if let Some ( trait_id) = tcx. trait_of_item ( callee) {
772
+ if !self . tcx . features ( ) . const_trait_impl {
773
+ self . check_op ( ops:: FnCallNonConst ( callee) ) ;
774
+ return ;
775
+ }
776
+
777
+ let trait_ref = TraitRef :: from_method ( tcx, trait_id, substs) ;
778
+ let obligation = Obligation :: new (
779
+ ObligationCause :: dummy ( ) ,
780
+ param_env,
781
+ Binder :: bind ( TraitPredicate {
782
+ trait_ref : TraitRef :: from_method ( tcx, trait_id, substs) ,
783
+ } ) ,
784
+ ) ;
785
+
786
+ let implsrc = tcx. infer_ctxt ( ) . enter ( |infcx| {
787
+ let mut selcx = SelectionContext :: new ( & infcx) ;
788
+ selcx. select ( & obligation) . unwrap ( )
789
+ } ) ;
790
+
791
+ // If the method is provided via a where-clause that does not use the `?const`
792
+ // opt-out, the call is allowed.
793
+ if let Some ( ImplSource :: Param ( _, hir:: Constness :: Const ) ) = implsrc {
794
+ debug ! (
795
+ "const_trait_impl: provided {:?} via where-clause in {:?}" ,
796
+ trait_ref, param_env
797
+ ) ;
798
+ return ;
799
+ }
800
+
801
+ // Resolve a trait method call to its concrete implementation, which may be in a
802
+ // `const` trait impl.
771
803
let instance = Instance :: resolve ( tcx, param_env, callee, substs) ;
772
804
debug ! ( "Resolving ({:?}) -> {:?}" , callee, instance) ;
773
805
if let Ok ( Some ( func) ) = instance {
0 commit comments