mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
pattern lowering, yeet TypingEnv::from_param_env
This commit is contained in:
parent
decf37bd16
commit
07a5272476
@ -123,7 +123,7 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
||||||
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
|
pat_from_hir(self.tcx, self.typing_env(), self.typeck_results(), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
|
fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
|
||||||
|
@ -2,11 +2,11 @@ use rustc_abi::{FieldIdx, VariantIdx};
|
|||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::traits::Obligation;
|
use rustc_infer::traits::Obligation;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
|
||||||
use rustc_middle::{mir, span_bug};
|
use rustc_middle::{mir, span_bug};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::ObligationCause;
|
use rustc_trait_selection::traits::ObligationCause;
|
||||||
@ -35,10 +35,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
id: hir::HirId,
|
id: hir::HirId,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Box<Pat<'tcx>> {
|
) -> Box<Pat<'tcx>> {
|
||||||
// FIXME(#132279): We likely want to be able to reveal the hidden types
|
let mut convert = ConstToPat::new(self, id, span);
|
||||||
// of opaques defined in this function here.
|
|
||||||
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
|
|
||||||
let mut convert = ConstToPat::new(self, id, span, infcx);
|
|
||||||
|
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
|
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
|
||||||
@ -49,27 +46,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ConstToPat<'tcx> {
|
struct ConstToPat<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
||||||
// inference context used for checking `T: Structural` bounds.
|
|
||||||
infcx: InferCtxt<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
|
|
||||||
treat_byte_string_as_slice: bool,
|
treat_byte_string_as_slice: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ConstToPat<'tcx> {
|
impl<'tcx> ConstToPat<'tcx> {
|
||||||
fn new(
|
fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self {
|
||||||
pat_ctxt: &PatCtxt<'_, 'tcx>,
|
|
||||||
id: hir::HirId,
|
|
||||||
span: Span,
|
|
||||||
infcx: InferCtxt<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
trace!(?pat_ctxt.typeck_results.hir_owner);
|
trace!(?pat_ctxt.typeck_results.hir_owner);
|
||||||
ConstToPat {
|
ConstToPat {
|
||||||
|
tcx: pat_ctxt.tcx,
|
||||||
|
typing_env: pat_ctxt.typing_env,
|
||||||
span,
|
span,
|
||||||
infcx,
|
|
||||||
param_env: pat_ctxt.param_env,
|
|
||||||
treat_byte_string_as_slice: pat_ctxt
|
treat_byte_string_as_slice: pat_ctxt
|
||||||
.typeck_results
|
.typeck_results
|
||||||
.treat_byte_string_as_slice
|
.treat_byte_string_as_slice
|
||||||
@ -77,16 +67,8 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
||||||
self.infcx.tcx
|
|
||||||
}
|
|
||||||
|
|
||||||
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
|
|
||||||
self.infcx.typing_env(self.param_env)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
||||||
ty.is_structural_eq_shallow(self.infcx.tcx)
|
ty.is_structural_eq_shallow(self.tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unevaluated_to_pat(
|
fn unevaluated_to_pat(
|
||||||
@ -105,22 +87,21 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
// FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
|
// FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
|
||||||
// instead of having this logic here
|
// instead of having this logic here
|
||||||
let typing_env =
|
let typing_env =
|
||||||
self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx());
|
self.tcx.erase_regions(self.typing_env).with_reveal_all_normalized(self.tcx);
|
||||||
let uv = self.tcx().erase_regions(uv);
|
let uv = self.tcx.erase_regions(uv);
|
||||||
|
|
||||||
// try to resolve e.g. associated constants to their definition on an impl, and then
|
// try to resolve e.g. associated constants to their definition on an impl, and then
|
||||||
// evaluate the const.
|
// evaluate the const.
|
||||||
let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span)
|
let valtree = match self.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) {
|
||||||
{
|
|
||||||
Ok(Ok(c)) => c,
|
Ok(Ok(c)) => c,
|
||||||
Err(ErrorHandled::Reported(_, _)) => {
|
Err(ErrorHandled::Reported(_, _)) => {
|
||||||
// Let's tell the use where this failing const occurs.
|
// Let's tell the use where this failing const occurs.
|
||||||
let e = self.tcx().dcx().emit_err(CouldNotEvalConstPattern { span: self.span });
|
let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span });
|
||||||
return pat_from_kind(PatKind::Error(e));
|
return pat_from_kind(PatKind::Error(e));
|
||||||
}
|
}
|
||||||
Err(ErrorHandled::TooGeneric(_)) => {
|
Err(ErrorHandled::TooGeneric(_)) => {
|
||||||
let e = self
|
let e = self
|
||||||
.tcx()
|
.tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.emit_err(ConstPatternDependsOnGenericParameter { span: self.span });
|
.emit_err(ConstPatternDependsOnGenericParameter { span: self.span });
|
||||||
return pat_from_kind(PatKind::Error(e));
|
return pat_from_kind(PatKind::Error(e));
|
||||||
@ -130,13 +111,13 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
let e = match bad_ty.kind() {
|
let e = match bad_ty.kind() {
|
||||||
ty::Adt(def, ..) => {
|
ty::Adt(def, ..) => {
|
||||||
assert!(def.is_union());
|
assert!(def.is_union());
|
||||||
self.tcx().dcx().emit_err(UnionPattern { span: self.span })
|
self.tcx.dcx().emit_err(UnionPattern { span: self.span })
|
||||||
}
|
}
|
||||||
ty::FnPtr(..) | ty::RawPtr(..) => {
|
ty::FnPtr(..) | ty::RawPtr(..) => {
|
||||||
self.tcx().dcx().emit_err(PointerPattern { span: self.span })
|
self.tcx.dcx().emit_err(PointerPattern { span: self.span })
|
||||||
}
|
}
|
||||||
_ => self
|
_ => self
|
||||||
.tcx()
|
.tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }),
|
.emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }),
|
||||||
};
|
};
|
||||||
@ -151,7 +132,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
// Always check for `PartialEq` if we had no other errors yet.
|
// Always check for `PartialEq` if we had no other errors yet.
|
||||||
if !self.type_has_partial_eq_impl(ty) {
|
if !self.type_has_partial_eq_impl(ty) {
|
||||||
let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
|
let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
|
||||||
let e = self.tcx().dcx().emit_err(err);
|
let e = self.tcx.dcx().emit_err(err);
|
||||||
return pat_from_kind(PatKind::Error(e));
|
return pat_from_kind(PatKind::Error(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,18 +142,19 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
||||||
let tcx = self.tcx();
|
let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
|
||||||
// double-check there even *is* a semantic `PartialEq` to dispatch to.
|
// double-check there even *is* a semantic `PartialEq` to dispatch to.
|
||||||
//
|
//
|
||||||
// (If there isn't, then we can safely issue a hard
|
// (If there isn't, then we can safely issue a hard
|
||||||
// error, because that's never worked, due to compiler
|
// error, because that's never worked, due to compiler
|
||||||
// using `PartialEq::eq` in this scenario in the past.)
|
// using `PartialEq::eq` in this scenario in the past.)
|
||||||
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
|
let partial_eq_trait_id =
|
||||||
|
self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
|
||||||
let partial_eq_obligation = Obligation::new(
|
let partial_eq_obligation = Obligation::new(
|
||||||
tcx,
|
self.tcx,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
self.param_env,
|
param_env,
|
||||||
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
|
ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]),
|
||||||
);
|
);
|
||||||
|
|
||||||
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
|
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
|
||||||
@ -181,7 +163,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
|
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
|
||||||
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
|
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
|
||||||
// can ensure that the type really implements `PartialEq`.
|
// can ensure that the type really implements `PartialEq`.
|
||||||
self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
|
infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field_pats(
|
fn field_pats(
|
||||||
@ -192,7 +174,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
.map(|(idx, (val, ty))| {
|
.map(|(idx, (val, ty))| {
|
||||||
let field = FieldIdx::new(idx);
|
let field = FieldIdx::new(idx);
|
||||||
// Patterns can only use monomorphic types.
|
// Patterns can only use monomorphic types.
|
||||||
let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty);
|
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
|
||||||
FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
|
FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@ -202,12 +184,12 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
|
fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx;
|
||||||
let kind = match ty.kind() {
|
let kind = match ty.kind() {
|
||||||
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
|
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
|
||||||
// Extremely important check for all ADTs! Make sure they opted-in to be used in
|
// Extremely important check for all ADTs! Make sure they opted-in to be used in
|
||||||
// patterns.
|
// patterns.
|
||||||
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
|
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
|
||||||
let err = TypeNotStructural { span, non_sm_ty: ty };
|
let err = TypeNotStructural { span, non_sm_ty: ty };
|
||||||
let e = tcx.dcx().emit_err(err);
|
let e = tcx.dcx().emit_err(err);
|
||||||
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||||
@ -225,7 +207,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
adt_def.variants()[variant_index]
|
adt_def.variants()[variant_index]
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| field.ty(self.tcx(), args)),
|
.map(|field| field.ty(self.tcx, args)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -233,14 +215,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
assert!(!def.is_union()); // Valtree construction would never succeed for unions.
|
assert!(!def.is_union()); // Valtree construction would never succeed for unions.
|
||||||
PatKind::Leaf {
|
PatKind::Leaf {
|
||||||
subpatterns: self.field_pats(
|
subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
|
||||||
cv.unwrap_branch().iter().copied().zip(
|
def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)),
|
||||||
def.non_enum_variant()
|
)),
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.map(|field| field.ty(self.tcx(), args)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Tuple(fields) => PatKind::Leaf {
|
ty::Tuple(fields) => PatKind::Leaf {
|
||||||
@ -274,9 +251,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
||||||
// deref pattern.
|
// deref pattern.
|
||||||
_ => {
|
_ => {
|
||||||
if !pointee_ty.is_sized(tcx, self.infcx.typing_env(self.param_env))
|
if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() {
|
||||||
&& !pointee_ty.is_slice()
|
|
||||||
{
|
|
||||||
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
|
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
|
||||||
let e = tcx.dcx().emit_err(err);
|
let e = tcx.dcx().emit_err(err);
|
||||||
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
|
||||||
|
@ -30,7 +30,7 @@ use crate::thir::util::UserAnnotatedTyHelpers;
|
|||||||
|
|
||||||
struct PatCtxt<'a, 'tcx> {
|
struct PatCtxt<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
typeck_results: &'a ty::TypeckResults<'tcx>,
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
|
|
||||||
/// Used by the Rust 2024 migration lint.
|
/// Used by the Rust 2024 migration lint.
|
||||||
@ -39,13 +39,13 @@ struct PatCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
pub(super) fn pat_from_hir<'a, 'tcx>(
|
pub(super) fn pat_from_hir<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
typeck_results: &'a ty::TypeckResults<'tcx>,
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
pat: &'tcx hir::Pat<'tcx>,
|
pat: &'tcx hir::Pat<'tcx>,
|
||||||
) -> Box<Pat<'tcx>> {
|
) -> Box<Pat<'tcx>> {
|
||||||
let mut pcx = PatCtxt {
|
let mut pcx = PatCtxt {
|
||||||
tcx,
|
tcx,
|
||||||
param_env,
|
typing_env,
|
||||||
typeck_results,
|
typeck_results,
|
||||||
rust_2024_migration_suggestion: typeck_results
|
rust_2024_migration_suggestion: typeck_results
|
||||||
.rust_2024_migration_desugared_pats()
|
.rust_2024_migration_desugared_pats()
|
||||||
@ -242,7 +242,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
|
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
|
||||||
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
|
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
|
||||||
|
|
||||||
let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env));
|
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
|
||||||
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
||||||
match (end, cmp) {
|
match (end, cmp) {
|
||||||
// `x..y` where `x < y`.
|
// `x..y` where `x < y`.
|
||||||
|
Loading…
Reference in New Issue
Block a user