1
Fork 0

Rollup merge of #103255 - oli-obk:opaque_wrong_eq_relation, r=compiler-errors

Clean up hidden type registration

work on https://github.com/rust-lang/rust/issues/101186

Actually passing down the relation and using it instead of `eq` for the hidden type comparison has *no* effect whatsoever and allows for no further improvements at the call sites. I decided the increased complexity was not worth it and thus did not include that change in this PR.

r? `@compiler-errors`
This commit is contained in:
Matthias Krüger 2022-10-27 15:03:55 +02:00 committed by GitHub
commit 16e74c78a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 75 deletions

View file

@ -263,13 +263,11 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies. // the bounds that the function supplies.
match infcx.register_hidden_type( let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
OpaqueTypeKey { def_id, substs: id_substs }, match infcx
ObligationCause::misc(instantiated_ty.span, body_id), .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
param_env, .eq(opaque_ty, definition_ty)
definition_ty, {
origin,
) {
Ok(infer_ok) => { Ok(infer_ok) => {
for obligation in infer_ok.obligations { for obligation in infer_ok.obligations {
fulfillment_cx.register_predicate_obligation(&infcx, obligation); fulfillment_cx.register_predicate_obligation(&infcx, obligation);
@ -280,7 +278,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
.err_ctxt() .err_ctxt()
.report_mismatched_types( .report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, body_id), &ObligationCause::misc(instantiated_ty.span, body_id),
self.tcx.mk_opaque(def_id.to_def_id(), id_substs), opaque_ty,
definition_ty, definition_ty,
err, err,
) )

View file

@ -1,6 +1,6 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::relate::TypeRelation;
@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true true
} }
fn register_opaque_type( fn register_opaque_type_obligations(
&mut self, &mut self,
a: Ty<'tcx>, obligations: PredicateObligations<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
) -> Result<(), TypeError<'tcx>> { ) -> Result<(), TypeError<'tcx>> {
let param_env = self.param_env();
let span = self.span();
let def_id = self.type_checker.body.source.def_id().expect_local();
let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
let cause = ObligationCause::misc(span, body_id);
self.type_checker self.type_checker
.fully_perform_op( .fully_perform_op(
self.locations, self.locations,
self.category, self.category,
InstantiateOpaqueType { InstantiateOpaqueType {
obligations: self obligations,
.type_checker
.infcx
.handle_opaque_type(a, b, a_is_expected, &cause, param_env)?
.obligations,
// These fields are filled in during execution of the operation // These fields are filled in during execution of the operation
base_universe: None, base_universe: None,
region_constraints: None, region_constraints: None,

View file

@ -16,8 +16,8 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating
use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution}; use crate::traits::query::{Fallible, NoSolution};
use crate::traits::TraitEngine;
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
@ -509,7 +509,7 @@ impl<'tcx> InferCtxt<'tcx> {
for &(a, b) in &query_response.value.opaque_types { for &(a, b) in &query_response.value.opaque_types {
let a = substitute_value(self.tcx, &result_subst, a); let a = substitute_value(self.tcx, &result_subst, a);
let b = substitute_value(self.tcx, &result_subst, b); let b = substitute_value(self.tcx, &result_subst, b);
obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations); obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations);
} }
Ok(InferOk { value: result_subst, obligations }) Ok(InferOk { value: result_subst, obligations })
@ -741,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
true true
} }
fn register_opaque_type( fn register_opaque_type_obligations(
&mut self, &mut self,
a: Ty<'tcx>, obligations: PredicateObligations<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
) -> Result<(), TypeError<'tcx>> { ) -> Result<(), TypeError<'tcx>> {
self.obligations.extend( self.obligations.extend(obligations);
self.infcx
.handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)?
.obligations,
);
Ok(()) Ok(())
} }
} }

View file

@ -25,7 +25,9 @@ use crate::infer::combine::ConstEquateRelation;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::PredicateObligation;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
@ -91,11 +93,9 @@ pub trait TypeRelatingDelegate<'tcx> {
); );
fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
fn register_opaque_type( fn register_opaque_type_obligations(
&mut self, &mut self,
a: Ty<'tcx>, obligations: Vec<PredicateObligation<'tcx>>,
b: Ty<'tcx>,
a_is_expected: bool,
) -> Result<(), TypeError<'tcx>>; ) -> Result<(), TypeError<'tcx>>;
/// Creates a new universe index. Used when instantiating placeholders. /// Creates a new universe index. Used when instantiating placeholders.
@ -414,7 +414,12 @@ where
(_, &ty::Opaque(..)) => (generalize(a, true)?, b), (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
_ => unreachable!(), _ => unreachable!(),
}; };
self.delegate.register_opaque_type(a, b, true)?; let cause = ObligationCause::dummy_with_span(self.delegate.span());
let obligations = self
.infcx
.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
.obligations;
self.delegate.register_opaque_type_obligations(obligations)?;
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a) Ok(a)
} }

View file

@ -103,7 +103,7 @@ impl<'tcx> InferCtxt<'tcx> {
return Ok(InferOk { value: (), obligations: vec![] }); return Ok(InferOk { value: (), obligations: vec![] });
} }
let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
ty::Opaque(def_id, substs) if def_id.is_local() => { ty::Opaque(def_id, substs) if def_id.is_local() => {
let def_id = def_id.expect_local(); let def_id = def_id.expect_local();
let origin = match self.defining_use_anchor { let origin = match self.defining_use_anchor {
@ -169,13 +169,14 @@ impl<'tcx> InferCtxt<'tcx> {
param_env, param_env,
b, b,
origin, origin,
a_is_expected,
)) ))
} }
_ => None, _ => None,
}; };
if let Some(res) = process(a, b) { if let Some(res) = process(a, b, true) {
res res
} else if let Some(res) = process(b, a) { } else if let Some(res) = process(b, a, false) {
res res
} else { } else {
let (a, b) = self.resolve_vars_if_possible((a, b)); let (a, b) = self.resolve_vars_if_possible((a, b));
@ -514,13 +515,14 @@ impl UseKind {
impl<'tcx> InferCtxt<'tcx> { impl<'tcx> InferCtxt<'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub fn register_hidden_type( fn register_hidden_type(
&self, &self,
opaque_type_key: OpaqueTypeKey<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>,
cause: ObligationCause<'tcx>, cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>, hidden_ty: Ty<'tcx>,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin,
a_is_expected: bool,
) -> InferResult<'tcx, ()> { ) -> InferResult<'tcx, ()> {
let tcx = self.tcx; let tcx = self.tcx;
let OpaqueTypeKey { def_id, substs } = opaque_type_key; let OpaqueTypeKey { def_id, substs } = opaque_type_key;
@ -539,7 +541,8 @@ impl<'tcx> InferCtxt<'tcx> {
origin, origin,
); );
if let Some(prev) = prev { if let Some(prev) = prev {
obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations; obligations =
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
} }
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());

View file

@ -2,9 +2,7 @@ use super::combine::{CombineFields, RelationDir};
use super::SubregionOrigin; use super::SubregionOrigin;
use crate::infer::combine::ConstEquateRelation; use crate::infer::combine::ConstEquateRelation;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::Obligation; use crate::traits::Obligation;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::TyVar; use rustc_middle::ty::TyVar;
@ -130,39 +128,18 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
if self.fields.define_opaque_types && did.is_local() => if self.fields.define_opaque_types && did.is_local() =>
{ {
let mut generalize = |ty, ty_is_expected| {
let var = infcx.next_ty_var_id_in_universe(
TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: self.fields.trace.cause.span,
},
ty::UniverseIndex::ROOT,
);
self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
Ok(infcx.tcx.mk_ty_var(var))
};
let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
let (ga, gb) = match (a.kind(), b.kind()) {
(&ty::Opaque(..), _) => (a, generalize(b, true)?),
(_, &ty::Opaque(..)) => (generalize(a, false)?, b),
_ => unreachable!(),
};
self.fields.obligations.extend( self.fields.obligations.extend(
infcx infcx
.handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env()) .handle_opaque_type(
// Don't leak any generalized type variables out of this a,
// subtyping relation in the case of a type error. b,
.map_err(|err| { self.a_is_expected,
let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb)); &self.fields.trace.cause,
if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb { self.param_env(),
TypeError::Sorts(ExpectedFound { expected: a, found: b }) )?
} else {
err
}
})?
.obligations, .obligations,
); );
Ok(ga) Ok(a)
} }
// Optimization of GeneratorWitness relation since we know that all // Optimization of GeneratorWitness relation since we know that all
// free regions are replaced with bound regions during construction. // free regions are replaced with bound regions during construction.