always make define_opaque_types explicit

This commit is contained in:
lcnr 2023-03-15 14:00:15 +01:00
parent e84e5ff04a
commit d2b7604db9
33 changed files with 308 additions and 225 deletions

View file

@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
@ -144,7 +144,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.eq(lhs, rhs)
.eq(DefineOpaqueTypes::No, lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
})

View file

@ -19,7 +19,7 @@ use std::mem;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData,
@ -268,7 +268,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.sub(goal.predicate.a, goal.predicate.b)?;
.sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?;
self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|pred| pred.into()).collect(),
)

View file

@ -7,6 +7,7 @@ use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::visit::TypeVisitableExt;
@ -814,7 +815,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).eq(DefineOpaqueTypes::No,c1, c2)
{
Ok(_) => (),
Err(_) => return false,

View file

@ -17,7 +17,7 @@ use crate::traits::{
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::infer::{DefineOpaqueTypes, DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@ -181,7 +181,7 @@ fn overlap_within_probe<'cx, 'tcx>(
let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id);
let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id);
let obligations = equate_impl_headers(selcx, &impl1_header, &impl2_header)?;
let obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
debug!("overlap: unification check succeeded");
if overlap_mode.use_implicit_negative() {
@ -207,20 +207,25 @@ fn overlap_within_probe<'cx, 'tcx>(
Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
}
fn equate_impl_headers<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
impl1_header: &ty::ImplHeader<'tcx>,
impl2_header: &ty::ImplHeader<'tcx>,
#[instrument(level = "debug", skip(infcx), ret)]
fn equate_impl_headers<'tcx>(
infcx: &InferCtxt<'tcx>,
impl1: &ty::ImplHeader<'tcx>,
impl2: &ty::ImplHeader<'tcx>,
) -> Option<PredicateObligations<'tcx>> {
// Do `a` and `b` unify? If not, no overlap.
debug!("equate_impl_headers(impl1_header={:?}, impl2_header={:?}", impl1_header, impl2_header);
selcx
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.define_opaque_types(true)
.eq_impl_headers(impl1_header, impl2_header)
.map(|infer_ok| infer_ok.obligations)
.ok()
let result = match (impl1.trait_ref, impl2.trait_ref) {
(Some(impl1_ref), Some(impl2_ref)) => infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.eq(DefineOpaqueTypes::Yes, impl1_ref, impl2_ref),
(None, None) => infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
DefineOpaqueTypes::Yes,
impl1.self_ty,
impl2.self_ty,
),
_ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
};
result.map(|infer_ok| infer_ok.obligations).ok()
}
/// Given impl1 and impl2 check if both impls can be satisfied by a common type (including
@ -325,7 +330,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).eq(DefineOpaqueTypes::No,subject1, subject2)
else {
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
return true;

View file

@ -11,7 +11,7 @@ use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
};
use rustc_infer::infer::{InferCtxt, InferOk};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::query::Fallible;
use rustc_infer::traits::{
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
@ -128,8 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
{
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.eq_exp(a_is_expected, a, b)
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, a, b)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@ -142,8 +141,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.eq(expected, actual)
.eq(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@ -157,8 +155,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.sub(expected, actual)
.sub(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@ -172,8 +169,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.sup(expected, actual)
.sup(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}

View file

@ -2,6 +2,7 @@ use crate::infer::{InferCtxt, TyOrConstInferVar};
use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled;
@ -515,7 +516,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
.eq(a.substs, b.substs)
.eq(DefineOpaqueTypes::No, a.substs, b.substs)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
@ -524,8 +525,9 @@ 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)
.eq(DefineOpaqueTypes::No, c1, c2)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
@ -565,12 +567,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match self
.selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(c1, c2)
{
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
c1,
c2,
) {
Ok(inf_ok) => {
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
}
@ -610,12 +611,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
bug!("AliasEq is only used for new solver")
}
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
match self
.selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(ct.ty(), ty)
{
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
ct.ty(),
ty,
) {
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,

View file

@ -28,6 +28,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::at::At;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::ImplSourceBuiltinData;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@ -285,12 +286,12 @@ 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(true)
.eq(normalized, actual)
{
// Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait`
match infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::Yes,
normalized,
actual,
) {
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
ProjectAndUnifyResult::Holds(obligations)
@ -2064,7 +2065,11 @@ 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).eq(
DefineOpaqueTypes::No,
cache_projection,
obligation_projection,
) {
Ok(InferOk { value: _, obligations }) => {
nested_obligations.extend(obligations);
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);

View file

@ -8,8 +8,8 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::ty::{
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
TraitRef, Ty, TyCtxt, TypeVisitableExt,
@ -177,7 +177,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.extend(self.infcx.commit_if_ok(|_| {
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(placeholder_trait_predicate, candidate)
.sup(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| Unimplemented)
})?);
@ -462,7 +462,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
nested.extend(self.infcx.commit_if_ok(|_| {
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(obligation_trait_ref, upcast_trait_ref)
.sup(DefineOpaqueTypes::No, obligation_trait_ref, upcast_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| Unimplemented)
})?);
@ -827,11 +827,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
});
// needed to define opaque types for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
self.infcx
.at(&obligation.cause, obligation.param_env)
// needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
.define_opaque_types(true)
.sup(obligation_trait_ref, expected_trait_ref)
.sup(DefineOpaqueTypes::Yes, obligation_trait_ref, expected_trait_ref)
.map(|InferOk { mut obligations, .. }| {
obligations.extend(nested);
obligations
@ -896,7 +895,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(target, source_trait)
.sup(DefineOpaqueTypes::No, target, source_trait)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
@ -995,7 +994,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(target, source_trait)
.sup(DefineOpaqueTypes::No, target, source_trait)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
@ -1066,7 +1065,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(b, a)
.eq(DefineOpaqueTypes::No, b, a)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
}
@ -1114,7 +1113,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(target, new_struct)
.eq(DefineOpaqueTypes::No, target, new_struct)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);
@ -1144,7 +1143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(target, new_tuple)
.eq(DefineOpaqueTypes::No, target, new_tuple)
.map_err(|_| Unimplemented)?;
nested.extend(obligations);

View file

@ -38,6 +38,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::traits::TraitEngine;
use rustc_infer::traits::TraitEngineExt;
@ -912,7 +913,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
.eq(a.substs, b.substs)
.eq(DefineOpaqueTypes::No, a.substs, b.substs)
{
let mut obligations = new_obligations.obligations;
self.add_depth(
@ -930,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Ok(new_obligations) = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(c1, c2)
.eq(DefineOpaqueTypes::No, c1, c2)
{
let mut obligations = new_obligations.obligations;
self.add_depth(
@ -964,8 +965,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(c1, c2)
{
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
c1,
c2,
) {
Ok(inf_ok) => self.evaluate_predicates_recursively(
previous_stack,
inf_ok.into_obligations(),
@ -993,7 +997,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
ct.ty(),
ty,
) {
Ok(inf_ok) => self.evaluate_predicates_recursively(
previous_stack,
inf_ok.into_obligations(),
@ -1751,7 +1759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.sup(DefineOpaqueTypes::No, ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
// inference variables and placeholders escape.
@ -1813,7 +1821,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let is_match = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(obligation.predicate, infer_projection)
.sup(DefineOpaqueTypes::No, obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
@ -2534,7 +2542,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
})?;
@ -2584,7 +2592,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.at(&obligation.cause, obligation.param_env)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.sup(DefineOpaqueTypes::No, obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())
}

View file

@ -10,6 +10,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
pub mod specialization_graph;
use rustc_infer::infer::DefineOpaqueTypes;
use specialization_graph::GraphExt;
use crate::errors::NegativePositiveConflict;
@ -193,7 +194,7 @@ fn fulfill_implication<'tcx>(
// do the impls unify? If not, no specialization.
let Ok(InferOk { obligations: more_obligations, .. }) =
infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait, target_trait)
infcx.at(&ObligationCause::dummy(), param_env, ).eq(DefineOpaqueTypes::No,source_trait, target_trait)
else {
debug!(
"fulfill_implication: {:?} does not unify with {:?}",

View file

@ -1,15 +1,14 @@
use super::NormalizeExt;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferOk;
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, SubstsRef};
use rustc_span::Span;
use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, SubstsRef};
use super::NormalizeExt;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext};
use rustc_infer::infer::InferOk;
pub use rustc_infer::traits::{self, util::*};
///////////////////////////////////////////////////////////////////////////
@ -201,6 +200,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
let subject = selcx.tcx().bound_impl_subject(impl_def_id);
let subject = subject.subst(selcx.tcx(), impl_substs);
let InferOk { value: subject, obligations: normalization_obligations1 } =
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject);