1
Fork 0

FnCtxt normalization stuff

This commit is contained in:
Michael Goulet 2022-11-25 17:28:50 +00:00
parent fc710832ea
commit 52cd342696
15 changed files with 41 additions and 67 deletions

View file

@ -109,6 +109,9 @@ pub trait AstConv<'tcx> {
) -> Ty<'tcx>; ) -> Ty<'tcx>;
/// Normalize an associated type coming from the user. /// Normalize an associated type coming from the user.
///
/// This should only be used by astconv. Use `FnCtxt::normalize`
/// or `ObligationCtxt::normalize` in downstream crates.
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
/// Invoked when we encounter an error from some prior pass /// Invoked when we encounter an error from some prior pass

View file

@ -53,6 +53,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.ocx.infcx.tcx self.ocx.infcx.tcx
} }
// Convenience function to normalize during wfcheck. This performs
// `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.
fn normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T fn normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,

View file

@ -448,7 +448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// previously appeared within a `Binder<>` and hence would not // previously appeared within a `Binder<>` and hence would not
// have been normalized before. // have been normalized before.
let fn_sig = self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig); let fn_sig = self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
let fn_sig = self.normalize_associated_types_in(call_expr.span, fn_sig); let fn_sig = self.normalize(call_expr.span, fn_sig);
// Call the generic checker. // Call the generic checker.
let expected_arg_tys = self.expected_inputs_for_expected_output( let expected_arg_tys = self.expected_inputs_for_expected_output(

View file

@ -752,7 +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_associated_types_in( let f = fcx.normalize(
self.expr_span, self.expr_span,
self.expr_ty.fn_sig(fcx.tcx), self.expr_ty.fn_sig(fcx.tcx),
); );

View file

@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if expected_sig.is_none() if expected_sig.is_none()
&& let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder() && let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
{ {
expected_sig = self.normalize_associated_types_in( expected_sig = self.normalize(
obligation.cause.span, obligation.cause.span,
self.deduce_sig_from_projection( self.deduce_sig_from_projection(
Some(obligation.cause.span), Some(obligation.cause.span),
@ -623,7 +623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
// Astconv can't normalize inputs or outputs with escaping bound vars, // Astconv can't normalize inputs or outputs with escaping bound vars,
// so normalize them here, after we've wrapped them in a binder. // so normalize them here, after we've wrapped them in a binder.
let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result); let result = self.normalize(self.tcx.hir().span(hir_id), result);
let c_result = self.inh.infcx.canonicalize_response(result); let c_result = self.inh.infcx.canonicalize_response(result);
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
@ -797,10 +797,8 @@ 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.inh.normalize_associated_types_in( let liberated_sig = self.normalize(
body.value.span, body.value.span,
self.tcx.hir().local_def_id_to_hir_id(expr_def_id),
self.param_env,
liberated_sig, liberated_sig,
); );
ClosureSignatures { bound_sig, liberated_sig } ClosureSignatures { bound_sig, liberated_sig }

View file

@ -1141,8 +1141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Err(TypeError::IntrinsicCast); return Err(TypeError::IntrinsicCast);
} }
// The signature must match. // The signature must match.
let a_sig = self.normalize_associated_types_in(new.span, a_sig); let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig));
let b_sig = self.normalize_associated_types_in(new.span, b_sig);
let sig = self let sig = self
.at(cause, self.param_env) .at(cause, self.param_env)
.trace(prev_ty, new_ty) .trace(prev_ty, new_ty)

View file

@ -1664,7 +1664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.fields .fields
.iter() .iter()
.map(|f| { .map(|f| {
let fru_ty = self.normalize_associated_types_in( let fru_ty = self.normalize(
expr_span, expr_span,
self.field_ty(base_expr.span, f, fresh_substs), self.field_ty(base_expr.span, f, fresh_substs),
); );
@ -1749,7 +1749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.fields .fields
.iter() .iter()
.map(|f| { .map(|f| {
self.normalize_associated_types_in(expr_span, f.ty(self.tcx, substs)) self.normalize(expr_span, f.ty(self.tcx, substs))
}) })
.collect(), .collect(),
_ => { _ => {

View file

@ -344,7 +344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{ {
debug!("instantiate_type_scheme(value={:?}, substs={:?})", value, substs); debug!("instantiate_type_scheme(value={:?}, substs={:?})", value, substs);
let value = EarlyBinder(value).subst(self.tcx, substs); let value = EarlyBinder(value).subst(self.tcx, substs);
let result = self.normalize_associated_types_in(span, value); let result = self.normalize(span, value);
debug!("instantiate_type_scheme = {:?}", result); debug!("instantiate_type_scheme = {:?}", result);
result result
} }
@ -360,7 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let bounds = self.tcx.predicates_of(def_id); let bounds = self.tcx.predicates_of(def_id);
let spans: Vec<Span> = bounds.predicates.iter().map(|(_, span)| *span).collect(); let spans: Vec<Span> = bounds.predicates.iter().map(|(_, span)| *span).collect();
let result = bounds.instantiate(self.tcx, substs); let result = bounds.instantiate(self.tcx, substs);
let result = self.normalize_associated_types_in(span, result); let result = self.normalize(span, result);
debug!( debug!(
"instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}", "instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}",
bounds, substs, result, spans, bounds, substs, result, spans,
@ -368,11 +368,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(result, spans) (result, spans)
} }
pub(in super::super) fn normalize_associated_types_in<T>(&self, span: Span, value: T) -> T pub(in super::super) fn normalize<T>(&self, span: Span, value: T) -> T
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
self.inh.normalize_associated_types_in(span, self.body_id, self.param_env, value) self.register_infer_ok_obligations(
self.at(&self.misc(span), self.param_env).normalize(value),
)
} }
pub(in super::super) fn normalize_associated_types_in_as_infer_ok<T>( pub(in super::super) fn normalize_associated_types_in_as_infer_ok<T>(
@ -487,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let span = self.tcx.def_span(anon_const.def_id); let span = self.tcx.def_span(anon_const.def_id);
let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id); let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None)); self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
self.normalize_associated_types_in(span, c) self.normalize(span, c)
} }
} }
} }
@ -580,7 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: &'tcx ty::FieldDef, field: &'tcx ty::FieldDef,
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
self.normalize_associated_types_in(span, field.ty(self.tcx, substs)) self.normalize(span, field.ty(self.tcx, substs))
} }
pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) { pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
@ -1107,7 +1109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Res::Local(hid) = res { if let Res::Local(hid) = res {
let ty = self.local_ty(span, hid).decl_ty; let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, ty); let ty = self.normalize(span, ty);
self.write_ty(hir_id, ty); self.write_ty(hir_id, ty);
return (ty, res); return (ty, res);
} }

View file

@ -288,7 +288,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
if ty.has_escaping_bound_vars() { if ty.has_escaping_bound_vars() {
ty // FIXME: normalization and escaping regions ty // FIXME: normalization and escaping regions
} else { } else {
self.normalize_associated_types_in(span, ty) self.normalize(span, ty)
} }
} }

View file

@ -759,7 +759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("suggest_missing_return_type: expected type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty);
let bound_vars = self.tcx.late_bound_vars(fn_id); let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = Binder::bind_with_vars(ty, bound_vars); let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize_associated_types_in(span, ty); let ty = self.normalize(span, ty);
let ty = self.tcx.erase_late_bound_regions(ty); let ty = self.tcx.erase_late_bound_regions(ty);
if self.can_coerce(expected, ty) { if self.can_coerce(expected, ty) {
err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected }); err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
@ -920,7 +920,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty); let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
let bound_vars = self.tcx.late_bound_vars(fn_id); let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = self.normalize_associated_types_in(expr.span, ty); let ty = self.normalize(expr.span, ty);
let ty = match self.tcx.asyncness(fn_id.owner) { let ty = match self.tcx.asyncness(fn_id.owner) {
hir::IsAsync::Async => { hir::IsAsync::Async => {
let infcx = self.tcx.infer_ctxt().build(); let infcx = self.tcx.infer_ctxt().build();

View file

@ -235,7 +235,7 @@ pub fn resolve_interior<'a, 'tcx>(
counter += 1; counter += 1;
ty::BoundRegion { var, kind } ty::BoundRegion { var, kind }
}; };
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty); let ty = fcx.normalize(cause.span, cause.ty);
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| { let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
let br = match region.kind() { let br = match region.kind() {
ty::ReVar(vid) => { ty::ReVar(vid) => {

View file

@ -7,13 +7,12 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap; use rustc_hir::HirIdMap;
use rustc_infer::infer; use rustc_infer::infer;
use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap; use rustc_span::def_id::LocalDefIdMap;
use rustc_span::{self, Span}; use rustc_span::{self, Span};
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCause, ObligationCtxt, TraitEngine, TraitEngineExt as _, self, ObligationCause, ObligationCtxt, TraitEngine, TraitEngineExt as _,
}; };
use std::cell::RefCell; use std::cell::RefCell;
@ -178,35 +177,4 @@ impl<'tcx> Inherited<'tcx> {
self.register_predicates(infer_ok.obligations); self.register_predicates(infer_ok.obligations);
infer_ok.value infer_ok.value
} }
pub(super) fn normalize_associated_types_in<T>(
&self,
span: Span,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value: T,
) -> T
where
T: TypeFoldable<'tcx>,
{
self.normalize_associated_types_in_with_cause(
ObligationCause::misc(span, body_id),
param_env,
value,
)
}
pub(super) fn normalize_associated_types_in_with_cause<T>(
&self,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: T,
) -> T
where
T: TypeFoldable<'tcx>,
{
let ok = self.at(&cause, param_env).normalize(value);
debug!(?ok);
self.register_infer_ok_obligations(ok)
}
} }

View file

@ -48,6 +48,8 @@ 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;
@ -245,12 +247,13 @@ 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);
let fn_sig = inh.normalize_associated_types_in( // FIXME(compiler-errors): Remove
body.value.span, let fn_sig = inh
body_id.hir_id, .register_infer_ok_obligations(
inh.at(&ObligationCause::misc(body.value.span, body_id.hir_id),
param_env, param_env,
fn_sig, )
); .normalize(fn_sig));
check_fn(&inh, param_env, fn_sig, decl, def_id, body, None).0 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 fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
@ -304,7 +307,7 @@ fn typeck_with_fallback<'tcx>(
_ => fallback(), _ => fallback(),
}); });
let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type); let expected_type = fcx.normalize(body.value.span, expected_type);
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
// Gather locals in statics (because of block expressions). // Gather locals in statics (because of block expressions).

View file

@ -106,7 +106,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// traits, no trait system method can be called before this point because they // traits, no trait system method can be called before this point because they
// could alter our Self-type, except for normalizing the receiver from the // could alter our Self-type, except for normalizing the receiver from the
// signature (which is also done during probing). // signature (which is also done during probing).
let method_sig_rcvr = self.normalize_associated_types_in(self.span, method_sig.inputs()[0]); let method_sig_rcvr = self.normalize(self.span, method_sig.inputs()[0]);
debug!( debug!(
"confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
self_ty, method_sig_rcvr, method_sig, method_predicates self_ty, method_sig_rcvr, method_sig, method_predicates
@ -114,7 +114,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);
let (method_sig, method_predicates) = let (method_sig, method_predicates) =
self.normalize_associated_types_in(self.span, (method_sig, method_predicates)); self.normalize(self.span, (method_sig, method_predicates));
let method_sig = ty::Binder::dummy(method_sig); let method_sig = ty::Binder::dummy(method_sig);
// Make sure nobody calls `drop()` explicitly. // Make sure nobody calls `drop()` explicitly.

View file

@ -22,8 +22,7 @@ use rustc_span::symbol::Ident;
use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::{Size, VariantIdx}; use rustc_target::abi::{Size, VariantIdx};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::NormalizeExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::normalize::AtExt;
use std::iter; use std::iter;
use crate::{match_def_path, path_res, paths}; use crate::{match_def_path, path_res, paths};
@ -284,7 +283,7 @@ fn is_normalizable_helper<'tcx>(
cache.insert(ty, false); cache.insert(ty, false);
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
let cause = rustc_middle::traits::ObligationCause::dummy(); let cause = rustc_middle::traits::ObligationCause::dummy();
let result = if infcx.at(&cause, param_env).normalize(ty).is_ok() { let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
match ty.kind() { match ty.kind() {
ty::Adt(def, substs) => def.variants().iter().all(|variant| { ty::Adt(def, substs) => def.variants().iter().all(|variant| {
variant variant