Simplify more FnCtxt normalization

This commit is contained in:
Michael Goulet 2022-11-25 18:00:27 +00:00
parent 52cd342696
commit 06786227fd
10 changed files with 46 additions and 111 deletions

View file

@ -752,10 +752,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
match *self.expr_ty.kind() { match *self.expr_ty.kind() {
ty::FnDef(..) => { ty::FnDef(..) => {
// Attempt a coercion to a fn pointer type. // Attempt a coercion to a fn pointer type.
let f = fcx.normalize( let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
self.expr_span,
self.expr_ty.fn_sig(fcx.tcx),
);
let res = fcx.try_coerce( let res = fcx.try_coerce(
self.expr, self.expr,
self.expr_ty, self.expr_ty,

View file

@ -1,6 +1,6 @@
use crate::coercion::CoerceMany; use crate::coercion::CoerceMany;
use crate::gather_locals::GatherLocalsVisitor; use crate::gather_locals::GatherLocalsVisitor;
use crate::{FnCtxt, Inherited}; use crate::FnCtxt;
use crate::{GeneratorTypes, UnsafetyState}; use crate::{GeneratorTypes, UnsafetyState};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
@ -20,21 +20,16 @@ use std::cell::RefCell;
/// ///
/// * ... /// * ...
/// * inherited: other fields inherited from the enclosing fn (if any) /// * inherited: other fields inherited from the enclosing fn (if any)
#[instrument(skip(inherited, body), level = "debug")] #[instrument(skip(fcx, body), level = "debug")]
pub(super) fn check_fn<'a, 'tcx>( pub(super) fn check_fn<'a, 'tcx>(
inherited: &'a Inherited<'tcx>, fcx: &mut FnCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
fn_sig: ty::FnSig<'tcx>, fn_sig: ty::FnSig<'tcx>,
decl: &'tcx hir::FnDecl<'tcx>, decl: &'tcx hir::FnDecl<'tcx>,
fn_def_id: LocalDefId, fn_def_id: LocalDefId,
body: &'tcx hir::Body<'tcx>, body: &'tcx hir::Body<'tcx>,
can_be_generator: Option<hir::Movability>, can_be_generator: Option<hir::Movability>,
) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) { ) -> Option<GeneratorTypes<'tcx>> {
let fn_id = inherited.tcx.hir().local_def_id_to_hir_id(fn_def_id); let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
// Create the function context. This is either derived from scratch or,
// in the case of closures, based on the outer context.
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
let tcx = fcx.tcx; let tcx = fcx.tcx;
@ -47,7 +42,7 @@ pub(super) fn check_fn<'a, 'tcx>(
declared_ret_ty, declared_ret_ty,
body.value.hir_id, body.value.hir_id,
decl.output.span(), decl.output.span(),
param_env, fcx.param_env,
)); ));
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
@ -105,7 +100,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.write_ty(param.hir_id, param_ty); fcx.write_ty(param.hir_id, param_ty);
} }
inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() { if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() {
// FIXME: We need to verify that the return type is `Sized` after the return expression has // FIXME: We need to verify that the return type is `Sized` after the return expression has
@ -174,7 +169,7 @@ pub(super) fn check_fn<'a, 'tcx>(
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
} }
(fcx, gen_ty) gen_ty
} }
fn check_panic_info_fn( fn check_panic_info_fn(

View file

@ -79,16 +79,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?bound_sig, ?liberated_sig); debug!(?bound_sig, ?liberated_sig);
let mut fcx = FnCtxt::new(self, self.param_env.without_const(), body.value.hir_id);
let generator_types = check_fn( let generator_types = check_fn(
self, &mut fcx,
self.param_env.without_const(),
liberated_sig, liberated_sig,
closure.fn_decl, closure.fn_decl,
expr_def_id, expr_def_id,
body, body,
closure.movability, closure.movability,
) );
.1;
let parent_substs = InternalSubsts::identity_for_item( let parent_substs = InternalSubsts::identity_for_item(
self.tcx, self.tcx,
@ -797,10 +796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> ClosureSignatures<'tcx> { ) -> ClosureSignatures<'tcx> {
let liberated_sig = let liberated_sig =
self.tcx().liberate_late_bound_regions(expr_def_id.to_def_id(), bound_sig); self.tcx().liberate_late_bound_regions(expr_def_id.to_def_id(), bound_sig);
let liberated_sig = self.normalize( let liberated_sig = self.normalize(body.value.span, liberated_sig);
body.value.span,
liberated_sig,
);
ClosureSignatures { bound_sig, liberated_sig } ClosureSignatures { bound_sig, liberated_sig }
} }
} }

View file

@ -62,7 +62,9 @@ use rustc_span::{self, BytePos, DesugaringKind, Span};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::ops::Deref; use std::ops::Deref;
@ -832,7 +834,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let b = self.shallow_resolve(b); let b = self.shallow_resolve(b);
let InferOk { value: b, mut obligations } = let InferOk { value: b, mut obligations } =
self.normalize_associated_types_in_as_infer_ok(self.cause.span, b); self.at(&self.cause, self.param_env).normalize(b);
debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
match b.kind() { match b.kind() {
@ -854,7 +856,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
} }
let InferOk { value: a_sig, obligations: o1 } = let InferOk { value: a_sig, obligations: o1 } =
self.normalize_associated_types_in_as_infer_ok(self.cause.span, a_sig); self.at(&self.cause, self.param_env).normalize(a_sig);
obligations.extend(o1); obligations.extend(o1);
let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig); let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);

View file

@ -1748,9 +1748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Adt(adt, substs) if adt.is_struct() => variant ty::Adt(adt, substs) if adt.is_struct() => variant
.fields .fields
.iter() .iter()
.map(|f| { .map(|f| self.normalize(expr_span, f.ty(self.tcx, substs)))
self.normalize(expr_span, f.ty(self.tcx, substs))
})
.collect(), .collect(),
_ => { _ => {
self.tcx self.tcx

View file

@ -16,7 +16,7 @@ use rustc_hir_analysis::astconv::{
}; };
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::{InferOk, InferResult}; use rustc_infer::infer::InferResult;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
@ -31,9 +31,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::slice; use std::slice;
@ -377,42 +375,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) )
} }
pub(in super::super) fn normalize_associated_types_in_as_infer_ok<T>(
&self,
span: Span,
value: T,
) -> InferOk<'tcx, T>
where
T: TypeFoldable<'tcx>,
{
self.at(&ObligationCause::misc(span, self.body_id), self.param_env).normalize(value)
}
pub(in super::super) fn normalize_op_associated_types_in_as_infer_ok<T>(
&self,
span: Span,
value: T,
opt_input_expr: Option<&hir::Expr<'_>>,
) -> InferOk<'tcx, T>
where
T: TypeFoldable<'tcx>,
{
self.at(
&ObligationCause::new(
span,
self.body_id,
traits::BinOp {
rhs_span: opt_input_expr.map(|expr| expr.span),
is_lit: opt_input_expr
.map_or(false, |expr| matches!(expr.kind, ExprKind::Lit(_))),
output_ty: None,
},
),
self.param_env,
)
.normalize(value)
}
pub fn require_type_meets( pub fn require_type_meets(
&self, &self,
ty: Ty<'tcx>, ty: Ty<'tcx>,

View file

@ -20,6 +20,7 @@ use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::NormalizeExt;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn body_fn_sig(&self) -> Option<ty::FnSig<'tcx>> { pub(crate) fn body_fn_sig(&self) -> Option<ty::FnSig<'tcx>> {
@ -245,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// implied by wf, but also because that would possibly result in // implied by wf, but also because that would possibly result in
// erroneous errors later on. // erroneous errors later on.
let infer::InferOk { value: output, obligations: _ } = let infer::InferOk { value: output, obligations: _ } =
self.normalize_associated_types_in_as_infer_ok(expr.span, output); self.at(&self.misc(expr.span), self.param_env).normalize(output);
if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) } if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
} }

View file

@ -48,8 +48,6 @@ pub use diverges::Diverges;
pub use expectation::Expectation; pub use expectation::Expectation;
pub use fn_ctxt::*; pub use fn_ctxt::*;
pub use inherited::{Inherited, InheritedBuilder}; pub use inherited::{Inherited, InheritedBuilder};
use rustc_infer::traits::ObligationCause;
use rustc_trait_selection::traits::NormalizeExt;
use crate::check::check_fn; use crate::check::check_fn;
use crate::coercion::DynamicCoerceMany; use crate::coercion::DynamicCoerceMany;
@ -235,9 +233,10 @@ fn typeck_with_fallback<'tcx>(
let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let mut fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() { let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
<dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None) <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
} else { } else {
tcx.fn_sig(def_id) tcx.fn_sig(def_id)
@ -247,16 +246,10 @@ fn typeck_with_fallback<'tcx>(
// Compute the function signature from point of view of inside the fn. // Compute the function signature from point of view of inside the fn.
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
// FIXME(compiler-errors): Remove let fn_sig = fcx.normalize(body.value.span, fn_sig);
let fn_sig = inh
.register_infer_ok_obligations( check_fn(&mut fcx, fn_sig, decl, def_id, body, None);
inh.at(&ObligationCause::misc(body.value.span, body_id.hir_id),
param_env,
)
.normalize(fn_sig));
check_fn(&inh, param_env, fn_sig, decl, def_id, body, None).0
} else { } else {
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
let expected_type = body_ty let expected_type = body_ty
.and_then(|ty| match ty.kind { .and_then(|ty| match ty.kind {
hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)), hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
@ -316,8 +309,6 @@ fn typeck_with_fallback<'tcx>(
fcx.check_expr_coercable_to_type(&body.value, expected_type, None); fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
fcx.write_ty(id, expected_type); fcx.write_ty(id, expected_type);
fcx
}; };
fcx.type_inference_fallback(); fcx.type_inference_fallback();

View file

@ -23,8 +23,8 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable}; use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable};
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{self, NormalizeExt};
use self::probe::{IsSuggestion, ProbeScope}; use self::probe::{IsSuggestion, ProbeScope};
@ -465,11 +465,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let fn_sig = fn_sig.subst(self.tcx, substs); let fn_sig = fn_sig.subst(self.tcx, substs);
let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig); let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig);
let InferOk { value, obligations: o } = if is_op { let cause = if is_op {
self.normalize_op_associated_types_in_as_infer_ok(span, fn_sig, opt_input_expr) ObligationCause::new(
span,
self.body_id,
traits::BinOp {
rhs_span: opt_input_expr.map(|expr| expr.span),
is_lit: opt_input_expr
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: None,
},
)
} else { } else {
self.normalize_associated_types_in_as_infer_ok(span, fn_sig) traits::ObligationCause::misc(span, self.body_id)
}; };
let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(fn_sig);
let fn_sig = { let fn_sig = {
obligations.extend(o); obligations.extend(o);
value value
@ -485,11 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// any late-bound regions appearing in its bounds. // any late-bound regions appearing in its bounds.
let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs);
let InferOk { value, obligations: o } = if is_op { let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(bounds);
self.normalize_op_associated_types_in_as_infer_ok(span, bounds, opt_input_expr)
} else {
self.normalize_associated_types_in_as_infer_ok(span, bounds)
};
let bounds = { let bounds = {
obligations.extend(o); obligations.extend(o);
value value
@ -497,20 +504,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
assert!(!bounds.has_escaping_bound_vars()); assert!(!bounds.has_escaping_bound_vars());
let cause = if is_op {
ObligationCause::new(
span,
self.body_id,
traits::BinOp {
rhs_span: opt_input_expr.map(|expr| expr.span),
is_lit: opt_input_expr
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: None,
},
)
} else {
traits::ObligationCause::misc(span, self.body_id)
};
let predicates_cause = cause.clone(); let predicates_cause = cause.clone();
obligations.extend(traits::predicates_for_generics( obligations.extend(traits::predicates_for_generics(
move |_, _| predicates_cause.clone(), move |_, _| predicates_cause.clone(),