use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::traits::select;
-use rustc_middle::ty::abstract_const::AbstractConst;
+use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
/// might come up during inference or typeck.
pub defining_use_anchor: DefiningAnchor,
+ /// Whether this inference context should care about region obligations in
+ /// the root universe. Most notably, this is used during hir typeck as region
+ /// solving is left to borrowck instead.
+ pub considering_regions: bool,
+
/// During type-checking/inference of a body, `in_progress_typeck_results`
/// contains a reference to the typeck results being built up, which are
/// used for reading closure kinds/signatures as they are inferred,
/// Comparing the signature and requirements of an impl method against
/// the containing trait.
- CompareImplMethodObligation {
- span: Span,
- impl_item_def_id: LocalDefId,
- trait_item_def_id: DefId,
- },
-
- /// Comparing the signature and requirements of an impl associated type
- /// against the containing trait
- CompareImplTypeObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
+ CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
/// Checking that the bounds of a trait's associated type hold for a given impl
CheckAssociatedTypeBounds {
/// without using `Rc` or something similar.
pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
- fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
defining_use_anchor: DefiningAnchor,
+ considering_regions: bool,
+ fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
}
pub trait TyCtxtInferExt<'tcx> {
InferCtxtBuilder {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
+ considering_regions: true,
fresh_typeck_results: None,
}
}
self
}
+ pub fn ignoring_regions(mut self) -> Self {
+ self.considering_regions = false;
+ self
+ }
+
/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
}
pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
- let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
+ let InferCtxtBuilder {
+ tcx,
+ defining_use_anchor,
+ considering_regions,
+ ref fresh_typeck_results,
+ } = *self;
let in_progress_typeck_results = fresh_typeck_results.as_ref();
f(InferCtxt {
tcx,
defining_use_anchor,
+ considering_regions,
in_progress_typeck_results,
inner: RefCell::new(InferCtxtInner::new()),
lexical_region_resolutions: RefCell::new(None),
&self,
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
- ) -> UnitResult<'tcx> {
- self.commit_if_ok(|_snapshot| {
- let ty::OutlivesPredicate(r_a, r_b) =
- self.replace_bound_vars_with_placeholders(predicate);
- let origin = SubregionOrigin::from_obligation_cause(cause, || {
- RelateRegionParamBound(cause.span)
- });
- self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
- Ok(())
- })
+ ) {
+ let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate);
+ let origin =
+ SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
+ self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
}
/// Number of type variables created so far.
#[instrument(skip(self), level = "debug")]
pub fn const_eval_resolve(
&self,
- param_env: ty::ParamEnv<'tcx>,
+ mut param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// variables
if substs.has_infer_types_or_consts() {
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
- if let Ok(None) = ac {
- substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
- } else {
- return Err(ErrorHandled::TooGeneric);
+ match ac {
+ Ok(None) => {
+ substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
+ param_env = self.tcx.param_env(unevaluated.def.did);
+ }
+ Ok(Some(ct)) => {
+ if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete {
+ substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs);
+ } else {
+ return Err(ErrorHandled::TooGeneric);
+ }
+ }
+ Err(guar) => return Err(ErrorHandled::Reported(guar)),
}
}
ReborrowUpvar(a, _) => a,
DataBorrowed(_, a) => a,
ReferenceOutlivesReferent(_, a) => a,
- CompareImplMethodObligation { span, .. } => span,
- CompareImplTypeObligation { span, .. } => span,
+ CompareImplItemObligation { span, .. } => span,
CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
}
}
SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
}
- traits::ObligationCauseCode::CompareImplMethodObligation {
+ traits::ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id,
trait_item_def_id,
- } => SubregionOrigin::CompareImplMethodObligation {
- span: cause.span,
- impl_item_def_id,
- trait_item_def_id,
- },
-
- traits::ObligationCauseCode::CompareImplTypeObligation {
- impl_item_def_id,
- trait_item_def_id,
- } => SubregionOrigin::CompareImplTypeObligation {
+ kind: _,
+ } => SubregionOrigin::CompareImplItemObligation {
span: cause.span,
impl_item_def_id,
trait_item_def_id,
)
}
}
+
+/// Replaces substs that reference param or infer variables with suitable
+/// placeholders. This function is meant to remove these param and infer
+/// substs when they're not actually needed to evaluate a constant.
+fn replace_param_and_infer_substs_with_placeholder<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ substs: SubstsRef<'tcx>,
+) -> SubstsRef<'tcx> {
+ tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
+ match arg.unpack() {
+ GenericArgKind::Type(_)
+ if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
+ {
+ tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundVar::from_usize(idx),
+ }))
+ .into()
+ }
+ GenericArgKind::Const(ct)
+ if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
+ {
+ let ty = ct.ty();
+ // If the type references param or infer, replace that too...
+ if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
+ bug!("const `{ct}`'s type should not reference params or types");
+ }
+ tcx.mk_const(ty::ConstS {
+ ty,
+ kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundConst { ty, var: ty::BoundVar::from_usize(idx) },
+ }),
+ })
+ .into()
+ }
+ _ => arg,
+ }
+ }))
+}