about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/errors/pattern_types.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs14
6 files changed, 104 insertions, 2 deletions
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 067878091a7..4a85e9983f4 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -144,7 +144,12 @@ impl<'tcx> InherentCollect<'tcx> {
         let id = id.owner_id.def_id;
         let item_span = self.tcx.def_span(id);
         let self_ty = self.tcx.type_of(id).instantiate_identity();
-        let self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
+        let mut self_ty = self.tcx.peel_off_weak_alias_tys(self_ty);
+        // We allow impls on pattern types exactly when we allow impls on the base type.
+        // FIXME(pattern_types): Figure out the exact coherence rules we want here.
+        while let ty::Pat(base, _) = *self_ty.kind() {
+            self_ty = base;
+        }
         match *self_ty.kind() {
             ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
             ty::Foreign(did) => self.check_def_id(id, self_ty, did),
@@ -154,6 +159,7 @@ impl<'tcx> InherentCollect<'tcx> {
             ty::Dynamic(..) => {
                 Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
             }
+            ty::Pat(_, _) => unreachable!(),
             ty::Bool
             | ty::Char
             | ty::Int(_)
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 1770f7b4e91..5585d2e069c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -206,6 +206,11 @@ pub(crate) fn orphan_check_impl(
                 (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
             }
 
+            ty::Pat(..) => (
+                LocalImpl::Disallow { problematic_kind: "pattern type" },
+                NonlocalImpl::DisallowOther,
+            ),
+
             ty::Bool
             | ty::Char
             | ty::Int(..)
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 2d4742fa1dc..d129614e0e1 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -7,6 +7,8 @@ use rustc_errors::{
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
 use rustc_span::{symbol::Ident, Span, Symbol};
+mod pattern_types;
+pub use pattern_types::*;
 
 #[derive(Diagnostic)]
 #[diag(hir_analysis_ambiguous_assoc_item)]
@@ -1629,3 +1631,10 @@ pub struct OpaqueCapturesHigherRankedLifetime {
     pub decl_span: Span,
     pub bad_place: &'static str,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_pattern_type_non_const_range)]
+pub struct NonConstRange {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
new file mode 100644
index 00000000000..008d2698989
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
@@ -0,0 +1,9 @@
+use rustc_macros::Diagnostic;
+use rustc_span::Span;
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_pattern_type_wild_pat)]
+pub struct WildPatTy {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index f726f2a7b89..ebfccd27d17 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -21,7 +21,7 @@ mod object_safety;
 
 use crate::bounds::Bounds;
 use crate::collect::HirPlaceholderCollector;
-use crate::errors::AmbiguousLifetimeBound;
+use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
 use crate::hir_ty_lowering::errors::{prohibit_assoc_item_binding, GenericsArgsErrExtend};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -39,6 +39,7 @@ use rustc_hir::{GenericArg, GenericArgs};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
+use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{
     self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
     TypeVisitableExt,
@@ -2195,6 +2196,64 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 // handled specially and will not descend into this routine.
                 self.ty_infer(None, hir_ty.span)
             }
+            hir::TyKind::Pat(ty, pat) => {
+                let ty = self.lower_ty(ty);
+                let pat_ty = match pat.kind {
+                    hir::PatKind::Wild => {
+                        let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
+                        Ty::new_error(tcx, err)
+                    }
+                    hir::PatKind::Range(start, end, include_end) => {
+                        let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
+                            let (expr, neg) = match expr.kind {
+                                hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
+                                    (negated, Some((expr.hir_id, expr.span)))
+                                }
+                                _ => (expr, None),
+                            };
+                            let c = match &expr.kind {
+                                hir::ExprKind::Lit(lit) => {
+                                    let lit_input =
+                                        LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
+                                    match tcx.lit_to_const(lit_input) {
+                                        Ok(c) => c,
+                                        Err(LitToConstError::Reported(err)) => {
+                                            ty::Const::new_error(tcx, err, ty)
+                                        }
+                                        Err(LitToConstError::TypeError) => todo!(),
+                                    }
+                                }
+                                _ => {
+                                    let err = tcx
+                                        .dcx()
+                                        .emit_err(crate::errors::NonConstRange { span: expr.span });
+                                    ty::Const::new_error(tcx, err, ty)
+                                }
+                            };
+                            self.record_ty(expr.hir_id, c.ty(), expr.span);
+                            if let Some((id, span)) = neg {
+                                self.record_ty(id, c.ty(), span);
+                            }
+                            c
+                        };
+
+                        let start = start.map(expr_to_const);
+                        let end = end.map(expr_to_const);
+
+                        let include_end = match include_end {
+                            hir::RangeEnd::Included => true,
+                            hir::RangeEnd::Excluded => false,
+                        };
+
+                        let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
+                        Ty::new_pat(tcx, ty, pat)
+                    }
+                    hir::PatKind::Err(e) => Ty::new_error(tcx, e),
+                    _ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"),
+                };
+                self.record_ty(pat.hir_id, ty, pat.span);
+                pat_ty
+            }
             hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
         };
 
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 28c86d8019e..20e4110e137 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -249,6 +249,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_ty(current, typ, variance);
             }
 
+            ty::Pat(typ, pat) => {
+                match *pat {
+                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                        if let Some(start) = start {
+                            self.add_constraints_from_const(current, start, variance);
+                        }
+                        if let Some(end) = end {
+                            self.add_constraints_from_const(current, end, variance);
+                        }
+                    }
+                }
+                self.add_constraints_from_ty(current, typ, variance);
+            }
+
             ty::Slice(typ) => {
                 self.add_constraints_from_ty(current, typ, variance);
             }