Skip to content

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 #108311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
let param_env = self.tcx.param_env(def_id);
// 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 =
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
let ocx = ObligationCtxt::new(&infcx);
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
// Check that E' = S'.
let cause = self.misc(hir_ty.span);
let InferOk { value: (), obligations } =
self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?;
let InferOk { value: (), obligations } = self
.at(&cause, self.param_env)
.define_opaque_types(true)
.eq(*expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
}

Expand All @@ -574,6 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = &self.misc(decl.output.span());
let InferOk { value: (), obligations } = self
.at(cause, self.param_env)
.define_opaque_types(true)
.eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
all_obligations.extend(obligations);

Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ impl<'f, 'tcx> Coerce<'f, '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);
self.commit_if_ok(|_| {
let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true);
if self.use_lub {
self.at(&self.cause, self.fcx.param_env).lub(b, a)
at.lub(b, a)
} else {
self.at(&self.cause, self.fcx.param_env)
.sup(b, a)
at.sup(b, a)
.map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
}
})
Expand All @@ -174,7 +174,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// 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
// 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![]);
}

Expand Down Expand Up @@ -1484,6 +1486,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// Another example is `break` with no argument expression.
assert!(expression_ty.is_unit(), "if let hack without unit type");
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())
.map(|infer_ok| {
fcx.register_infer_ok_obligations(infer_ok);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> 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: () }) => {
self.register_predicates(obligations);
None
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> 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: () }) => {
self.register_predicates(obligations);
None
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
TraitCandidate(trait_ref) => self.probe(|_| {
let _ = self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(candidate.xform_self_ty, self_ty);
match self.select_trait_candidate(trait_ref) {
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
Expand Down Expand Up @@ -1466,7 +1465,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// First check that the self type can be related.
let sub_obligations = match self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(probe.xform_self_ty, self_ty)
{
Ok(InferOk { obligations, value: () }) => obligations,
Expand Down Expand Up @@ -1683,7 +1681,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if let ProbeResult::Match = result
&& self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(return_ty, xform_ret_ty)
.is_err()
{
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub struct InferCtxt<'tcx> {
/// 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.
///
/// 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.
pub defining_use_anchor: DefiningAnchor,

Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,11 @@ impl<'tcx> InferCtxt<'tcx> {
origin,
);
if let Some(prev) = prev {
obligations =
self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
obligations = self
.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());
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/solve/infcx_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env)
.define_opaque_types(false)
.eq(lhs, rhs)
.map(|InferOk { value: (), obligations }| {
obligations.into_iter().map(|o| o.into()).collect()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ fn equate_impl_headers<'cx, 'tcx>(
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()
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +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)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
Expand All @@ -141,6 +142,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.eq(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
Expand All @@ -155,6 +157,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
Expand All @@ -169,6 +172,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
.define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>(
);
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: () }) => {
obligations.extend(inferred_obligations);
ProjectAndUnifyResult::Holds(obligations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

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)
.map(|InferOk { mut obligations, .. }| {
obligations.extend(nested);
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1752,7 +1752,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
Expand Down Expand Up @@ -1815,7 +1814,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let is_match = self
.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
Expand Down Expand Up @@ -2507,7 +2505,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
.define_opaque_types(false)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
Expand Down Expand Up @@ -2558,11 +2555,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.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)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/type-alias-impl-trait/match-unification.rs
Original file line number Diff line number Diff line change
@@ -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() {}