@@ -15,7 +15,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
1515use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
1616use rustc_hir:: RangeEnd ;
1717use 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 } ;
1919use rustc_middle:: mir:: interpret:: { LitToConstError , LitToConstInput } ;
2020use rustc_middle:: mir:: UserTypeProjection ;
2121use rustc_middle:: mir:: { BorrowKind , Field , Mutability } ;
@@ -762,69 +762,80 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
762762 fn lower_path ( & mut self , qpath : & hir:: QPath < ' _ > , id : hir:: HirId , span : Span ) -> Pat < ' tcx > {
763763 let ty = self . tables . node_type ( id) ;
764764 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 ! [ ] ) ) ,
768773 } ;
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- }
788774
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 ) ;
823794 }
824- _ => self . lower_variant_or_leaf ( res, id, span, ty, vec ! [ ] ) ,
825795 } ;
826796
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+ }
828839 }
829840
830841 /// Converts literals, paths and negation of literals to patterns.
@@ -849,7 +860,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
849860
850861 let lit_input = LitToConstInput { lit : & lit. node , ty : self . tables . expr_ty ( expr) , neg } ;
851862 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 ,
853864 Err ( LitToConstError :: UnparseableFloat ) => {
854865 self . errors . push ( PatternError :: FloatBug ) ;
855866 PatKind :: Wild
0 commit comments