diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
5 files changed, 92 insertions, 10 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 adb5cd24929..d129614e0e1 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1631,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/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 8ff5a22c484..ebfccd27d17 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -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,15 +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) => match pat.kind { - hir::PatKind::Wild => { - let err = tcx.dcx().emit_err(WildPatTy { span: pat.span }); - Ty::new_error(tcx, err) - } - hir::PatKind::Range(_, _, _) => Ty::new_misc_error(tcx), - hir::PatKind::Err(e) => Ty::new_error(tcx, e), - _ => span_bug!(pat.span, "unsupported pattern for pattern type: {pat:#?}"), - }, + 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); } |
