mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Make hidden type registration opt-in, so that each site can be reviewed on its own and we have the right defaults for trait solvers
This commit is contained in:
parent
bda32a4023
commit
88a7b6803b
@ -273,7 +273,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||||||
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
|
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
|
||||||
let param_env = self.tcx.param_env(def_id);
|
let param_env = self.tcx.param_env(def_id);
|
||||||
// HACK This bubble is required for this tests to pass:
|
// HACK This bubble is required for this tests to pass:
|
||||||
// type-alias-impl-trait/issue-67844-nested-opaque.rs
|
// nested-return-type2-tait2.rs
|
||||||
|
// nested-return-type2-tait3.rs
|
||||||
let infcx =
|
let infcx =
|
||||||
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
|
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
@ -561,8 +561,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
) {
|
) {
|
||||||
// Check that E' = S'.
|
// Check that E' = S'.
|
||||||
let cause = self.misc(hir_ty.span);
|
let cause = self.misc(hir_ty.span);
|
||||||
let InferOk { value: (), obligations } =
|
let InferOk { value: (), obligations } = self
|
||||||
self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?;
|
.at(&cause, self.param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
|
.eq(*expected_ty, supplied_ty)?;
|
||||||
all_obligations.extend(obligations);
|
all_obligations.extend(obligations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,6 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let cause = &self.misc(decl.output.span());
|
let cause = &self.misc(decl.output.span());
|
||||||
let InferOk { value: (), obligations } = self
|
let InferOk { value: (), obligations } = self
|
||||||
.at(cause, self.param_env)
|
.at(cause, self.param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
.eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
|
.eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
|
||||||
all_obligations.extend(obligations);
|
all_obligations.extend(obligations);
|
||||||
|
|
||||||
|
@ -143,11 +143,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
|
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
|
||||||
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
|
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
|
let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true);
|
||||||
if self.use_lub {
|
if self.use_lub {
|
||||||
self.at(&self.cause, self.fcx.param_env).lub(b, a)
|
at.lub(b, a)
|
||||||
} else {
|
} else {
|
||||||
self.at(&self.cause, self.fcx.param_env)
|
at.sup(b, a)
|
||||||
.sup(b, a)
|
|
||||||
.map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
|
.map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -174,7 +174,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
// Best-effort try to unify these types -- we're already on the error path,
|
// Best-effort try to unify these types -- we're already on the error path,
|
||||||
// so this will have the side-effect of making sure we have no ambiguities
|
// so this will have the side-effect of making sure we have no ambiguities
|
||||||
// due to `[type error]` and `_` not coercing together.
|
// due to `[type error]` and `_` not coercing together.
|
||||||
let _ = self.commit_if_ok(|_| self.at(&self.cause, self.param_env).eq(a, b));
|
let _ = self.commit_if_ok(|_| {
|
||||||
|
self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b)
|
||||||
|
});
|
||||||
return success(vec![], self.fcx.tcx.ty_error(), vec![]);
|
return success(vec![], self.fcx.tcx.ty_error(), vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1484,6 +1486,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
// Another example is `break` with no argument expression.
|
// Another example is `break` with no argument expression.
|
||||||
assert!(expression_ty.is_unit(), "if let hack without unit type");
|
assert!(expression_ty.is_unit(), "if let hack without unit type");
|
||||||
fcx.at(cause, fcx.param_env)
|
fcx.at(cause, fcx.param_env)
|
||||||
|
// needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
|
||||||
|
.define_opaque_types(true)
|
||||||
.eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
|
.eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
|
||||||
.map(|infer_ok| {
|
.map(|infer_ok| {
|
||||||
fcx.register_infer_ok_obligations(infer_ok);
|
fcx.register_infer_ok_obligations(infer_ok);
|
||||||
|
@ -113,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
actual: Ty<'tcx>,
|
actual: Ty<'tcx>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||||
match self.at(cause, self.param_env).sup(expected, actual) {
|
match self.at(cause, self.param_env).define_opaque_types(true).sup(expected, actual) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
None
|
None
|
||||||
@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
actual: Ty<'tcx>,
|
actual: Ty<'tcx>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
|
||||||
match self.at(cause, self.param_env).eq(expected, actual) {
|
match self.at(cause, self.param_env).define_opaque_types(true).eq(expected, actual) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
None
|
None
|
||||||
|
@ -1436,7 +1436,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
TraitCandidate(trait_ref) => self.probe(|_| {
|
TraitCandidate(trait_ref) => self.probe(|_| {
|
||||||
let _ = self
|
let _ = self
|
||||||
.at(&ObligationCause::dummy(), self.param_env)
|
.at(&ObligationCause::dummy(), self.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(candidate.xform_self_ty, self_ty);
|
.sup(candidate.xform_self_ty, self_ty);
|
||||||
match self.select_trait_candidate(trait_ref) {
|
match self.select_trait_candidate(trait_ref) {
|
||||||
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
|
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
|
||||||
@ -1466,7 +1465,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
// First check that the self type can be related.
|
// First check that the self type can be related.
|
||||||
let sub_obligations = match self
|
let sub_obligations = match self
|
||||||
.at(&ObligationCause::dummy(), self.param_env)
|
.at(&ObligationCause::dummy(), self.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(probe.xform_self_ty, self_ty)
|
.sup(probe.xform_self_ty, self_ty)
|
||||||
{
|
{
|
||||||
Ok(InferOk { obligations, value: () }) => obligations,
|
Ok(InferOk { obligations, value: () }) => obligations,
|
||||||
@ -1683,7 +1681,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
if let ProbeResult::Match = result
|
if let ProbeResult::Match = result
|
||||||
&& self
|
&& self
|
||||||
.at(&ObligationCause::dummy(), self.param_env)
|
.at(&ObligationCause::dummy(), self.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(return_ty, xform_ret_ty)
|
.sup(return_ty, xform_ret_ty)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
cause: &'a ObligationCause<'tcx>,
|
cause: &'a ObligationCause<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> At<'a, 'tcx> {
|
) -> At<'a, 'tcx> {
|
||||||
At { infcx: self, cause, param_env, define_opaque_types: true }
|
At { infcx: self, cause, param_env, define_opaque_types: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forks the inference context, creating a new inference context with the same inference
|
/// Forks the inference context, creating a new inference context with the same inference
|
||||||
|
@ -264,7 +264,7 @@ pub struct InferCtxt<'tcx> {
|
|||||||
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
|
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
|
||||||
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
|
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
|
||||||
///
|
///
|
||||||
/// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
|
/// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
|
||||||
/// might come up during inference or typeck.
|
/// might come up during inference or typeck.
|
||||||
pub defining_use_anchor: DefiningAnchor,
|
pub defining_use_anchor: DefiningAnchor,
|
||||||
|
|
||||||
|
@ -545,8 +545,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
origin,
|
origin,
|
||||||
);
|
);
|
||||||
if let Some(prev) = prev {
|
if let Some(prev) = prev {
|
||||||
obligations =
|
obligations = self
|
||||||
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
|
.at(&cause, param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
|
.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());
|
||||||
|
@ -54,7 +54,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
||||||
self.at(&ObligationCause::dummy(), param_env)
|
self.at(&ObligationCause::dummy(), param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.eq(lhs, rhs)
|
.eq(lhs, rhs)
|
||||||
.map(|InferOk { value: (), obligations }| {
|
.map(|InferOk { value: (), obligations }| {
|
||||||
obligations.into_iter().map(|o| o.into()).collect()
|
obligations.into_iter().map(|o| o.into()).collect()
|
||||||
|
@ -217,6 +217,7 @@ fn equate_impl_headers<'cx, 'tcx>(
|
|||||||
selcx
|
selcx
|
||||||
.infcx
|
.infcx
|
||||||
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
|
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
|
||||||
|
.define_opaque_types(true)
|
||||||
.eq_impl_headers(impl1_header, impl2_header)
|
.eq_impl_headers(impl1_header, impl2_header)
|
||||||
.map(|infer_ok| infer_ok.obligations)
|
.map(|infer_ok| infer_ok.obligations)
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -128,6 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
{
|
{
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(cause, param_env)
|
.at(cause, param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
.eq_exp(a_is_expected, a, b)
|
.eq_exp(a_is_expected, a, b)
|
||||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||||
}
|
}
|
||||||
@ -141,6 +142,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
) -> Result<(), TypeError<'tcx>> {
|
) -> Result<(), TypeError<'tcx>> {
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(cause, param_env)
|
.at(cause, param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
.eq(expected, actual)
|
.eq(expected, actual)
|
||||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||||
}
|
}
|
||||||
@ -155,6 +157,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
) -> Result<(), TypeError<'tcx>> {
|
) -> Result<(), TypeError<'tcx>> {
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(cause, param_env)
|
.at(cause, param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
.sup(expected, actual)
|
.sup(expected, actual)
|
||||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||||
}
|
}
|
||||||
@ -169,6 +172,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
) -> Result<(), TypeError<'tcx>> {
|
) -> Result<(), TypeError<'tcx>> {
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(cause, param_env)
|
.at(cause, param_env)
|
||||||
|
.define_opaque_types(true)
|
||||||
.sup(expected, actual)
|
.sup(expected, actual)
|
||||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>(
|
|||||||
);
|
);
|
||||||
obligations.extend(new);
|
obligations.extend(new);
|
||||||
|
|
||||||
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
|
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)
|
||||||
|
{
|
||||||
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
||||||
obligations.extend(inferred_obligations);
|
obligations.extend(inferred_obligations);
|
||||||
ProjectAndUnifyResult::Holds(obligations)
|
ProjectAndUnifyResult::Holds(obligations)
|
||||||
|
@ -821,6 +821,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.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(obligation_trait_ref, expected_trait_ref)
|
||||||
.map(|InferOk { mut obligations, .. }| {
|
.map(|InferOk { mut obligations, .. }| {
|
||||||
obligations.extend(nested);
|
obligations.extend(nested);
|
||||||
|
@ -1752,7 +1752,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
});
|
});
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
|
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
|
||||||
.map(|InferOk { obligations: _, value: () }| {
|
.map(|InferOk { obligations: _, value: () }| {
|
||||||
// This method is called within a probe, so we can't have
|
// This method is called within a probe, so we can't have
|
||||||
@ -1815,7 +1814,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
let is_match = self
|
let is_match = self
|
||||||
.infcx
|
.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(obligation.predicate, infer_projection)
|
.sup(obligation.predicate, infer_projection)
|
||||||
.map_or(false, |InferOk { obligations, value: () }| {
|
.map_or(false, |InferOk { obligations, value: () }| {
|
||||||
self.evaluate_predicates_recursively(
|
self.evaluate_predicates_recursively(
|
||||||
@ -2507,7 +2505,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
let InferOk { obligations, .. } = self
|
let InferOk { obligations, .. } = self
|
||||||
.infcx
|
.infcx
|
||||||
.at(&cause, obligation.param_env)
|
.at(&cause, obligation.param_env)
|
||||||
.define_opaque_types(false)
|
|
||||||
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
|
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
|
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
|
||||||
@ -2558,11 +2555,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
|
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
|
||||||
self.infcx
|
self.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
// We don't want predicates for opaque types to just match all other types,
|
|
||||||
// if there is an obligation on the opaque type, then that obligation must be met
|
|
||||||
// opaquely. Otherwise we'd match any obligation to the opaque type and then error
|
|
||||||
// out later.
|
|
||||||
.define_opaque_types(false)
|
|
||||||
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
|
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
|
||||||
.map(|InferOk { obligations, .. }| obligations)
|
.map(|InferOk { obligations, .. }| obligations)
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
|
14
tests/ui/type-alias-impl-trait/match-unification.rs
Normal file
14
tests/ui/type-alias-impl-trait/match-unification.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
fn bar() -> impl Debug {}
|
||||||
|
|
||||||
|
fn baz(b: bool) -> Option<impl Debug> {
|
||||||
|
match b {
|
||||||
|
true => baz(false),
|
||||||
|
false => Some(bar()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user