@@ -15,7 +15,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
15
15
use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
16
16
use rustc_hir:: RangeEnd ;
17
17
use rustc_index:: vec:: Idx ;
18
- use rustc_middle:: mir:: interpret:: { get_slice_bytes, sign_extend, ConstValue , ErrorHandled } ;
18
+ use rustc_middle:: mir:: interpret:: { get_slice_bytes, sign_extend, ConstValue } ;
19
19
use rustc_middle:: mir:: interpret:: { LitToConstError , LitToConstInput } ;
20
20
use rustc_middle:: mir:: UserTypeProjection ;
21
21
use rustc_middle:: mir:: { BorrowKind , Field , Mutability } ;
@@ -762,69 +762,80 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
762
762
fn lower_path ( & mut self , qpath : & hir:: QPath < ' _ > , id : hir:: HirId , span : Span ) -> Pat < ' tcx > {
763
763
let ty = self . tables . node_type ( id) ;
764
764
let res = self . tables . qpath_res ( qpath, id) ;
765
- let is_associated_const = match res {
766
- Res :: Def ( DefKind :: AssocConst , _) => true ,
767
- _ => false ,
765
+
766
+ let pat_from_kind = |kind| Pat { span, ty, kind : Box :: new ( kind) } ;
767
+
768
+ let ( def_id, is_associated_const) = match res {
769
+ Res :: Def ( DefKind :: Const , def_id) => ( def_id, false ) ,
770
+ Res :: Def ( DefKind :: AssocConst , def_id) => ( def_id, true ) ,
771
+
772
+ _ => return pat_from_kind ( self . lower_variant_or_leaf ( res, id, span, ty, vec ! [ ] ) ) ,
768
773
} ;
769
- let kind = match res {
770
- Res :: Def ( DefKind :: Const | DefKind :: AssocConst , def_id) => {
771
- let substs = self . tables . node_substs ( id) ;
772
- // Use `Reveal::All` here because patterns are always monomorphic even if their function isn't.
773
- match self . tcx . const_eval_resolve (
774
- self . param_env . with_reveal_all ( ) ,
775
- def_id,
776
- substs,
777
- None ,
778
- Some ( span) ,
779
- ) {
780
- Ok ( value) => {
781
- let const_ =
782
- ty:: Const :: from_value ( self . tcx , value, self . tables . node_type ( id) ) ;
783
-
784
- let pattern = self . const_to_pat ( & const_, id, span) ;
785
- if !is_associated_const {
786
- return pattern;
787
- }
788
774
789
- let user_provided_types = self . tables ( ) . user_provided_types ( ) ;
790
- return if let Some ( u_ty) = user_provided_types. get ( id) {
791
- let user_ty = PatTyProj :: from_user_type ( * u_ty) ;
792
- Pat {
793
- span,
794
- kind : Box :: new ( PatKind :: AscribeUserType {
795
- subpattern : pattern,
796
- ascription : Ascription {
797
- /// Note that use `Contravariant` here. See the
798
- /// `variance` field documentation for details.
799
- variance : ty:: Variance :: Contravariant ,
800
- user_ty,
801
- user_ty_span : span,
802
- } ,
803
- } ) ,
804
- ty : const_. ty ,
805
- }
806
- } else {
807
- pattern
808
- } ;
809
- }
810
- Err ( ErrorHandled :: TooGeneric ) => {
811
- self . errors . push ( if is_associated_const {
812
- PatternError :: AssocConstInPattern ( span)
813
- } else {
814
- PatternError :: StaticInPattern ( span)
815
- } ) ;
816
- PatKind :: Wild
817
- }
818
- Err ( _) => {
819
- self . tcx . sess . span_err ( span, "could not evaluate constant pattern" ) ;
820
- PatKind :: Wild
821
- }
822
- }
775
+ // Use `Reveal::All` here because patterns are always monomorphic even if their function
776
+ // isn't.
777
+ let param_env_reveal_all = self . param_env . with_reveal_all ( ) ;
778
+ let substs = self . tables . node_substs ( id) ;
779
+ let instance = match ty:: Instance :: resolve ( self . tcx , param_env_reveal_all, def_id, substs) {
780
+ Ok ( Some ( i) ) => i,
781
+ Ok ( None ) => {
782
+ self . errors . push ( if is_associated_const {
783
+ PatternError :: AssocConstInPattern ( span)
784
+ } else {
785
+ PatternError :: StaticInPattern ( span)
786
+ } ) ;
787
+
788
+ return pat_from_kind ( PatKind :: Wild ) ;
789
+ }
790
+
791
+ Err ( _) => {
792
+ self . tcx . sess . span_err ( span, "could not evaluate constant pattern" ) ;
793
+ return pat_from_kind ( PatKind :: Wild ) ;
823
794
}
824
- _ => self . lower_variant_or_leaf ( res, id, span, ty, vec ! [ ] ) ,
825
795
} ;
826
796
827
- Pat { span, ty, kind : Box :: new ( kind) }
797
+ // `mir_const_qualif` must be called with the `DefId` of the item where the const is
798
+ // defined, not where it is declared. The difference is significant for associated
799
+ // constants.
800
+ let mir_structural_match_violation = self . tcx . mir_const_qualif ( instance. def_id ( ) ) . custom_eq ;
801
+ debug ! ( "mir_structural_match_violation({:?}) -> {}" , qpath, mir_structural_match_violation) ;
802
+
803
+ match self . tcx . const_eval_instance ( param_env_reveal_all, instance, Some ( span) ) {
804
+ Ok ( value) => {
805
+ let const_ = ty:: Const :: from_value ( self . tcx , value, self . tables . node_type ( id) ) ;
806
+
807
+ let pattern = self . const_to_pat ( & const_, id, span, mir_structural_match_violation) ;
808
+
809
+ if !is_associated_const {
810
+ return pattern;
811
+ }
812
+
813
+ let user_provided_types = self . tables ( ) . user_provided_types ( ) ;
814
+ if let Some ( u_ty) = user_provided_types. get ( id) {
815
+ let user_ty = PatTyProj :: from_user_type ( * u_ty) ;
816
+ Pat {
817
+ span,
818
+ kind : Box :: new ( PatKind :: AscribeUserType {
819
+ subpattern : pattern,
820
+ ascription : Ascription {
821
+ /// Note that use `Contravariant` here. See the
822
+ /// `variance` field documentation for details.
823
+ variance : ty:: Variance :: Contravariant ,
824
+ user_ty,
825
+ user_ty_span : span,
826
+ } ,
827
+ } ) ,
828
+ ty : const_. ty ,
829
+ }
830
+ } else {
831
+ pattern
832
+ }
833
+ }
834
+ Err ( _) => {
835
+ self . tcx . sess . span_err ( span, "could not evaluate constant pattern" ) ;
836
+ pat_from_kind ( PatKind :: Wild )
837
+ }
838
+ }
828
839
}
829
840
830
841
/// Converts literals, paths and negation of literals to patterns.
@@ -849,7 +860,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
849
860
850
861
let lit_input = LitToConstInput { lit : & lit. node , ty : self . tables . expr_ty ( expr) , neg } ;
851
862
match self . tcx . at ( expr. span ) . lit_to_const ( lit_input) {
852
- Ok ( val) => * self . const_to_pat ( val, expr. hir_id , lit. span ) . kind ,
863
+ Ok ( val) => * self . const_to_pat ( val, expr. hir_id , lit. span , false ) . kind ,
853
864
Err ( LitToConstError :: UnparseableFloat ) => {
854
865
self . errors . push ( PatternError :: FloatBug ) ;
855
866
PatKind :: Wild
0 commit comments