diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-01-25 16:51:42 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-02-02 15:40:11 +0000 |
| commit | 7bce50c01af576ca0132d9eddcd0ac85e82c9092 (patch) | |
| tree | 2835676b5857aa24e8be56598964828dc8c8370a | |
| parent | 9110911353aaee4980c78bcabcb9e5d2aac4c7dd (diff) | |
| download | rust-7bce50c01af576ca0132d9eddcd0ac85e82c9092.tar.gz rust-7bce50c01af576ca0132d9eddcd0ac85e82c9092.zip | |
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.
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 da270be5ef0..3667d6bd640 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 ccf8b44206a..aba1dd2bc54 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 ecb50dd6097..20ccad26e89 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 5f4555a78f3..3a288516664 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 3ba4b942725..dc0ebf23058 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 6b0910b475f..d3a28c6d3aa 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 ffb113c1d33..cdb141c0e3e 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, &'<empty> 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 32b4d18c162..2eb3a07059f 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, &'<empty> 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 c4b56cd6253..47e05bce0f8 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 04a5d73e0d3..0e195558bad 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 ff2832c8986..321cb8c92a1 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 018ba3ea5f7..032e88c6d9c 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 8ddc3f2c34b..570a08cb587 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<&'<empty> 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 |
