Skip to content

Commit

Permalink
Require all .at calls to provide a defining use anchor
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Mar 1, 2023
1 parent e920c5d commit 17f29f4
Show file tree
Hide file tree
Showing 28 changed files with 132 additions and 88 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {

let normalized_ty = self
.infcx
.at(&cause, self.param_env)
.at(&cause, self.param_env, DefiningAnchor::Error)
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx, self.defining_use_anchor);
let normalized_ty =
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionResolutionError};
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
Expand Down Expand Up @@ -227,7 +227,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
use rustc_type_ir::sty::TyKind::*;
match (source.kind(), target.kind()) {
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {}
if infcx.at(&cause, param_env, DefiningAnchor::Error).eq(r_a, *r_b).is_ok()
&& mutbl_a == *mutbl_b => {}
(&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
(&Adt(def_a, substs_a), &Adt(def_b, substs_b))
if def_a.is_struct() && def_b.is_struct() =>
Expand Down Expand Up @@ -270,7 +271,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}

if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
if let Ok(ok) =
infcx.at(&cause, param_env, DefiningAnchor::Error).eq(ty_a, ty_b)
{
if ok.obligations.is_empty() {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
Expand Down Expand Up @@ -497,7 +500,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// we may have to evaluate constraint
// expressions in the course of execution.)
// See e.g., #41936.
if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
if let Ok(ok) = infcx.at(&cause, param_env, DefiningAnchor::Error).eq(a, b) {
if ok.obligations.is_empty() {
return None;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn require_same_types<'tcx>(
) -> bool {
let infcx = &tcx.infer_ctxt().build();
let param_env = ty::ParamEnv::empty();
let errors = match infcx.at(cause, param_env).eq(expected, actual) {
let errors = match infcx.at(cause, param_env, DefiningAnchor::Error).eq(expected, actual) {
Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(
infcx,
obligations,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}

pub fn at(&self) -> At<'_, 'tcx> {
self.infcx.at(&self.cause, self.param_env)
self.fcx.at(&self.cause)
}

fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

pub fn at(&'a self, cause: &'a ObligationCause<'tcx>) -> At<'a, 'tcx> {
self.infcx.at(cause, self.param_env)
self.infcx.at(cause, self.param_env, self.defining_use_anchor())
}

pub fn sess(&self) -> &Session {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ impl<'tcx> InferCtxt<'tcx> {
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
define_opaque_types: impl Into<DefiningAnchor>,
) -> At<'a, 'tcx> {
At { infcx: self, cause, param_env, define_opaque_types: DefiningAnchor::Error }
At { infcx: self, cause, param_env, define_opaque_types: define_opaque_types.into() }
}

/// Forks the inference context, creating a new inference context with the same inference
Expand Down
24 changes: 13 additions & 11 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,12 +515,8 @@ impl<'tcx> InferCtxt<'tcx> {
let a = substitute_value(self.tcx, &result_subst, a);
let b = substitute_value(self.tcx, &result_subst, b);
debug!(?a, ?b, "constrain opaque type");
obligations.extend(
self.at(cause, param_env)
.define_opaque_types(defining_use_anchor)
.eq(a, b)?
.obligations,
);
obligations
.extend(self.at(cause, param_env, defining_use_anchor).eq(a, b)?.obligations);
}

Ok(InferOk { value: result_subst, obligations })
Expand Down Expand Up @@ -613,20 +609,26 @@ impl<'tcx> InferCtxt<'tcx> {

match (value1.unpack(), value2.unpack()) {
(GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
obligations
.extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations());
obligations.extend(
self.at(cause, param_env, DefiningAnchor::Error)
.eq(v1, v2)?
.into_obligations(),
);
}
(GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2))
if re1.is_erased() && re2.is_erased() =>
{
// no action needed
}
(GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => {
obligations
.extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations());
obligations.extend(
self.at(cause, param_env, DefiningAnchor::Error)
.eq(v1, v2)?
.into_obligations(),
);
}
(GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
let ok = self.at(cause, param_env).eq(v1, v2)?;
let ok = self.at(cause, param_env, DefiningAnchor::Error).eq(v1, v2)?;
obligations.extend(ok.into_obligations());
}
_ => {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,15 +837,15 @@ impl<'tcx> InferCtxt<'tcx> {
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok())
self.probe(|_| self.at(origin, param_env, DefiningAnchor::Error).sub(a, b).is_ok())
}

pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok())
self.probe(|_| self.at(origin, param_env, DefiningAnchor::Error).eq(a, b).is_ok())
}

#[instrument(skip(self), level = "debug")]
Expand Down Expand Up @@ -940,7 +940,8 @@ impl<'tcx> InferCtxt<'tcx> {
let ty::SubtypePredicate { a_is_expected, a, b } =
self.instantiate_binder_with_placeholders(predicate);

let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
let ok =
self.at(cause, param_env, DefiningAnchor::Error).sub_exp(a_is_expected, a, b)?;

Ok(ok.unit())
}))
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,7 @@ impl<'tcx> InferCtxt<'tcx> {
);
if let Some(prev) = prev {
obligations = self
.at(&cause, param_env)
.define_opaque_types(defining_use_anchor)
.at(&cause, param_env, defining_use_anchor)
.eq_exp(a_is_expected, prev, hidden_ty)?
.obligations;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error)
.eq(lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
} else {
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.at(&ObligationCause::dummy(), goal.param_env, DefiningAnchor::Error)
.sub(goal.predicate.a, goal.predicate.b)?;
self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|pred| pred.into()).collect(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {

match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2)
match selcx.infcx.at(&obligation.cause, obligation.param_env, DefiningAnchor::Error).eq(c1, c2)
{
Ok(_) => (),
Err(_) => return false,
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
};

let InferOk { value: mut header, obligations } =
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
let InferOk { value: mut header, obligations } = selcx
.infcx
.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error)
.normalize(header);

header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
header
Expand Down Expand Up @@ -214,7 +216,7 @@ fn equate_impl_headers<'cx, 'tcx>(
debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header);
selcx
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.at(&ObligationCause::dummy(), ty::ParamEnv::empty(), DefiningAnchor::Error)
.define_opaque_types(DefiningAnchor::Bubble)
.eq_impl_headers(impl1_header, impl2_header)
.map(|infer_ok| infer_ok.obligations)
Expand Down Expand Up @@ -323,7 +325,7 @@ fn equate<'tcx>(
) -> bool {
// do the impls unify? If not, not disjoint.
let Ok(InferOk { obligations: more_obligations, .. }) =
infcx.at(&ObligationCause::dummy(), impl_env).eq(subject1, subject2)
infcx.at(&ObligationCause::dummy(), impl_env, DefiningAnchor::Error).eq(subject1, subject2)
else {
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
return true;
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
value: T,
) -> T {
let infer_ok = self.infcx.at(&cause, param_env).normalize(value);
let infer_ok = self.infcx.at(&cause, param_env, DefiningAnchor::Error).normalize(value);
self.register_infer_ok_obligations(infer_ok)
}

Expand All @@ -149,7 +149,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
T: ToTrace<'tcx>,
{
self.infcx
.at(cause, param_env)
.at(cause, param_env, DefiningAnchor::Error)
.define_opaque_types(self.defining_use_anchor())
.eq_exp(a_is_expected, a, b)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
Expand All @@ -163,7 +163,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
actual: T,
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.at(cause, param_env, DefiningAnchor::Error)
.define_opaque_types(self.defining_use_anchor())
.eq(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
Expand All @@ -178,7 +178,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
actual: T,
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.at(cause, param_env, DefiningAnchor::Error)
.define_opaque_types(self.defining_use_anchor())
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
Expand All @@ -193,7 +193,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
actual: T,
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.at(cause, param_env, DefiningAnchor::Error)
.define_opaque_types(self.defining_use_anchor())
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2142,7 +2142,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.map(|ImplCandidate { trait_ref, similarity }| {
// FIXME(compiler-errors): This should be using `NormalizeExt::normalize`
let normalized = self
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.at(&ObligationCause::dummy(), ty::ParamEnv::empty(), DefiningAnchor::Error)
.query_normalize(trait_ref)
.map_or(trait_ref, |normalized| normalized.value);
(similarity, normalized)
Expand Down Expand Up @@ -2706,8 +2706,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let cleaned_pred =
pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });

let InferOk { value: cleaned_pred, .. } =
self.infcx.at(&ObligationCause::dummy(), param_env).normalize(cleaned_pred);
let InferOk { value: cleaned_pred, .. } = self
.infcx
.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error)
.normalize(cleaned_pred);

let obligation =
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// implied by wf, but also because that would possibly result in
// erroneous errors later on.
let InferOk { value: output, obligations: _ } =
self.at(&ObligationCause::dummy(), param_env).normalize(output);
self.at(&ObligationCause::dummy(), param_env, DefiningAnchor::Error).normalize(output);

if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
}
Expand Down Expand Up @@ -3388,8 +3388,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
[trait_pred.self_ty()],
)
});
let InferOk { value: projection_ty, .. } =
self.at(&obligation.cause, obligation.param_env).normalize(projection_ty);
let InferOk { value: projection_ty, .. } = self
.at(&obligation.cause, obligation.param_env, DefiningAnchor::Error)
.normalize(projection_ty);

debug!(
normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
&& tcx.def_kind(a.def.did) == DefKind::AssocConst =>
{
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
.at(
&obligation.cause,
obligation.param_env,
DefiningAnchor::Error,
)
.trace(c1, c2)
.eq(a.substs, b.substs)
{
Expand All @@ -532,8 +536,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
(_, Unevaluated(_)) | (Unevaluated(_), _) => (),
(_, _) => {
if let Ok(new_obligations) =
infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2)
if let Ok(new_obligations) = infcx
.at(
&obligation.cause,
obligation.param_env,
DefiningAnchor::Error,
)
.eq(c1, c2)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
Expand Down Expand Up @@ -576,7 +585,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
match self
.selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.at(&obligation.cause, obligation.param_env, DefiningAnchor::Error)
.eq(c1, c2)
{
Ok(inf_ok) => {
Expand Down Expand Up @@ -621,7 +630,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
match self
.selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.at(&obligation.cause, obligation.param_env, DefiningAnchor::Error)
.eq(ct.ty(), ty)
{
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,8 @@ fn project_and_unify_type<'cx, 'tcx>(
obligations.extend(new);

match infcx
.at(&obligation.cause, obligation.param_env)
// This is needed to support nested opaque types like `impl Fn() -> impl Trait`
.define_opaque_types(selcx.defining_use_anchor())
// This anchor is needed to support nested opaque types like `impl Fn() -> impl Trait`
.at(&obligation.cause, obligation.param_env, selcx.defining_use_anchor())
.eq(normalized, actual)
{
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
Expand Down Expand Up @@ -2067,7 +2066,10 @@ fn confirm_param_env_candidate<'cx, 'tcx>(

debug!(?cache_projection, ?obligation_projection);

match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
match infcx
.at(cause, param_env, DefiningAnchor::Error)
.eq(cache_projection, obligation_projection)
{
Ok(InferOk { value: _, obligations }) => {
nested_obligations.extend(obligations);
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
Expand Down
Loading

0 comments on commit 17f29f4

Please sign in to comment.