From 7bce50c01af576ca0132d9eddcd0ac85e82c9092 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Jan 2022 16:51:42 +0000 Subject: [PATCH] Register member constraints on the final merged hidden type Previously we did this per hidden type candiate, which didn't always have all the information available. --- compiler/rustc_borrowck/src/type_check/mod.rs | 11 ++++- .../src/type_check/relate_tys.rs | 47 +++++-------------- .../src/infer/canonical/query_response.rs | 2 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 4 +- .../rustc_infer/src/infer/opaque_types.rs | 7 ++- .../rustc_trait_selection/src/opaque_types.rs | 2 +- .../ret-impl-trait-one.nll.stderr | 19 +++++--- .../ret-impl-trait-one.stderr | 19 +++++--- .../ordinary-bounds-unrelated.rs | 1 - .../ordinary-bounds-unrelated.stderr | 16 +------ .../ordinary-bounds-unsuited.rs | 1 - .../ordinary-bounds-unsuited.stderr | 16 +------ ...types_pin_lifetime_impl_trait-async.stderr | 13 ++--- 13 files changed, 62 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index da270be5ef0a..3667d6bd6400 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -203,9 +203,16 @@ pub(crate) fn type_check<'mir, 'tcx>( ConstraintCategory::OpaqueType, CustomTypeOp::new( |infcx| { - Ok(decl + let res = decl .hidden_type(infcx, &cause, param_env) - .map_err(|e| e.0)?) + .map_err(|e| e.0)?; + infcx.register_member_constraints( + param_env, + opaque_type_key, + res.value.ty, + res.value.span, + ); + Ok(res) }, || "opaque_type_map".to_string(), ), diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index ccf8b44206aa..aba1dd2bc548 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_infer::infer::{InferOk, NllRegionVariableOrigin}; use rustc_infer::traits::ObligationCause; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; @@ -136,7 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> true } - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { let param_env = self.param_env(); let span = self.span(); let def_id = self.type_checker.body.source.def_id().expect_local(); @@ -148,39 +148,18 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> self.category, CustomTypeOp::new( |infcx| { - let (concrete_ty, opaque_type_key) = - match (a.kind(), b.kind(), a_is_expected) { - (ty::Opaque(..), ty::Opaque(..), true) => { - (b, a.expect_opaque_type()) - } - (ty::Opaque(..), ty::Opaque(..), false) => { - (a, b.expect_opaque_type()) - } - (ty::Opaque(..), _, _) => (b, a.expect_opaque_type()), - (_, ty::Opaque(..), _) => (a, b.expect_opaque_type()), - _ => span_bug!( - span, - "no opaque types in constrain_opaque_type {:?}, {:?}", - a, - b - ), - }; - let mut result = self.type_checker.infcx.constrain_opaque_type( - param_env, - opaque_type_key, - concrete_ty, - span, - )?; - result.obligations.push(infcx.opaque_ty_obligation( - a, - b, - a_is_expected, - param_env, - cause, - )); - Ok(result) + Ok(InferOk { + value: (), + obligations: vec![infcx.opaque_ty_obligation( + a, + b, + a_is_expected, + param_env, + cause, + )], + }) }, - || "constrain_opaque_type".to_string(), + || "register_opaque_type".to_string(), ), ) .unwrap(); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index ecb50dd60973..20ccad26e891 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -723,7 +723,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { true } - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) { self.obligations.push(self.infcx.opaque_ty_obligation( a, b, diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 5f4555a78f31..3a288516664e 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -90,7 +90,7 @@ pub trait TypeRelatingDelegate<'tcx> { info: ty::VarianceDiagInfo<'tcx>, ); - fn constrain_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); + fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool); fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); @@ -591,7 +591,7 @@ where (_, &ty::Opaque(..)) => (generalize(a, true)?, b), _ => unreachable!(), }; - self.delegate.constrain_opaque_type(a, b, true); + self.delegate.register_opaque_type(a, b, true); trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 3ba4b9427251..dc0ebf23058f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,5 +1,5 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk, InferResult}; +use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, PredicateObligation, PredicateObligations}; use hir::def_id::{DefId, LocalDefId}; use hir::OpaqueTyOrigin; @@ -379,13 +379,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `free_region_relations` -- something that can be used to relate /// the free regions (`'a`) that appear in the impl trait. #[instrument(level = "debug", skip(self))] - pub fn constrain_opaque_type( + pub fn register_member_constraints( &self, param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, concrete_ty: Ty<'tcx>, span: Span, - ) -> InferResult<'tcx, ()> { + ) { let def_id = opaque_type_key.def_id; let tcx = self.tcx; @@ -445,7 +445,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) }, }); - Ok(InferOk { value: (), obligations: vec![] }) } pub fn opaque_ty_obligation( diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 6b0910b475ff..d3a28c6d3aa3 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// purpose of this function is to do that translation. /// /// (*) C1 and C2 were introduced in the comments on - /// `constrain_opaque_type`. Read that comment for more context. + /// `register_member_constraints`. Read that comment for more context. /// /// # Parameters /// diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index ffb113c1d336..cdb141c0e3ea 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -14,16 +14,21 @@ LL | | } = help: consider adding the following bound: `'a: 'b` error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ret-impl-trait-one.rs:16:65 + --> $DIR/ret-impl-trait-one.rs:16:80 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ____________________________________--__________________________________________^ + | | | + | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ | -note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body - --> $DIR/ret-impl-trait-one.rs:16:65 +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index 32b4d18c162d..2eb3a07059f7 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -11,16 +11,21 @@ LL | | } | |_^ ...but data from `a` is returned here error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ret-impl-trait-one.rs:16:65 + --> $DIR/ret-impl-trait-one.rs:16:80 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ____________________________________--__________________________________________^ + | | | + | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ | -note: hidden type `(&'a u8, &' u8)` captures lifetime smaller than the function body - --> $DIR/ret-impl-trait-one.rs:16:65 +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ^^^^^^^^^^^^^^ +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs index c4b56cd62534..47e05bce0f8d 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -27,7 +27,6 @@ where // ``` if condition() { a } else { b } //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds - //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 04a5d73e0d37..0e195558badb 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -12,20 +12,6 @@ help: to declare that the `impl Trait` captures `'b`, you can add an explicit `' LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unrelated.rs:28:33 - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here -... -LL | if condition() { a } else { b } - | ^ - | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs index ff2832c8986e..321cb8c92a17 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -30,7 +30,6 @@ fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. if condition() { a } else { b } //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds - //~| ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds } fn condition() -> bool { diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 018ba3ea5f76..032e88c6d9c1 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -12,20 +12,6 @@ help: to declare that the `impl Trait` captures `'b`, you can add an explicit `' LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ordinary-bounds-unsuited.rs:31:33 - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here -... -LL | if condition() { a } else { b } - | ^ - | -help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 8ddc3f2c34bd..570a08cb5876 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -1,14 +1,15 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ + | - ^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the lifetime `'_` as defined here | -note: hidden type `Pin<&' Foo>` captures lifetime smaller than the function body - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 +help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^ +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ error: aborting due to previous error