stabilize member constraints

This commit is contained in:
Niko Matsakis 2021-04-29 10:31:44 -04:00
parent 1969c2e312
commit 128d385e56
27 changed files with 28 additions and 235 deletions

View File

@ -285,6 +285,8 @@ declare_features! (
(accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
/// Allows unsizing coercions in `const fn`.
(accepted, const_fn_unsize, "1.54.0", Some(64992), None),
/// Allows `impl Trait` with multiple unrelated lifetimes.
(accepted, member_constraints, "1.54.0", Some(61997), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features

View File

@ -472,9 +472,6 @@ declare_features! (
/// Allows explicit discriminants on non-unit enum variants.
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
/// Allows `impl Trait` with multiple unrelated lifetimes.
(active, member_constraints, "1.37.0", Some(61997), None),
/// Allows `async || body` closures.
(active, async_closure, "1.37.0", Some(62290), None),

View File

@ -140,15 +140,6 @@ pub trait InferCtxtExt<'tcx> {
first_own_region_index: usize,
);
/*private*/
fn member_constraint_feature_gate(
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: ty::Region<'tcx>,
conflict2: ty::Region<'tcx>,
) -> bool;
fn infer_opaque_definition_from_instantiation(
&self,
def_id: DefId,
@ -490,9 +481,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// ['a, 'b, 'c]`, where `'a..'c` are the
// regions that appear in the impl trait.
// For now, enforce a feature gate outside of async functions.
self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_region);
return self.generate_member_constraint(
concrete_ty,
opaque_defn,
@ -559,60 +547,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
});
}
/// Member constraints are presently feature-gated except for
/// async-await. We expect to lift this once we've had a bit more
/// time.
fn member_constraint_feature_gate(
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: ty::Region<'tcx>,
conflict2: ty::Region<'tcx>,
) -> bool {
// If we have `#![feature(member_constraints)]`, no problems.
if self.tcx.features().member_constraints {
return false;
}
let span = self.tcx.def_span(opaque_type_def_id);
// Without a feature-gate, we only generate member-constraints for async-await.
let context_name = match opaque_defn.origin {
// No feature-gate required for `async fn`.
hir::OpaqueTyOrigin::AsyncFn => return false,
// Otherwise, generate the label we'll use in the error message.
hir::OpaqueTyOrigin::Binding
| hir::OpaqueTyOrigin::FnReturn
| hir::OpaqueTyOrigin::TyAlias
| hir::OpaqueTyOrigin::Misc => "impl Trait",
};
let msg = format!("ambiguous lifetime bound in `{}`", context_name);
let mut err = self.tcx.sess.struct_span_err(span, &msg);
let conflict1_name = conflict1.to_string();
let conflict2_name = conflict2.to_string();
let label_owned;
let label = match (&*conflict1_name, &*conflict2_name) {
("'_", "'_") => "the elided lifetimes here do not outlive one another",
_ => {
label_owned = format!(
"neither `{}` nor `{}` outlives the other",
conflict1_name, conflict2_name,
);
&label_owned
}
};
err.span_label(span, label);
if self.tcx.sess.is_nightly_build() {
err.help("add #![feature(member_constraints)] to the crate attributes to enable");
}
err.emit();
true
}
/// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type

View File

@ -1,29 +0,0 @@
# `member_constraints`
The tracking issue for this feature is: [#61997]
[#61997]: https://github.com/rust-lang/rust/issues/61997
------------------------
The `member_constraints` feature gate lets you use `impl Trait` syntax with
multiple unrelated lifetime parameters.
A simple example is:
```rust
#![feature(member_constraints)]
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T {}
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
(x, y)
}
fn main() { }
```
Without the `member_constraints` feature gate, the above example is an
error because both `'a` and `'b` appear in the impl Trait bounds, but
neither outlives the other.

View File

@ -1,10 +1,9 @@
// edition:2018
// run-pass
// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.
#![feature(member_constraints)]
// Test member constraints that appear in the `impl Trait`
// return type of an async function.
// (This used to require a feature gate.)
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }

View File

@ -1,20 +0,0 @@
// edition:2018
// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }
async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
//~^ ERROR ambiguous lifetime bound
//~| ERROR ambiguous lifetime bound
//~| ERROR ambiguous lifetime bound
//~| 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
(a, b)
}
fn main() {
let _ = async_ret_impl_trait(&22, &44);
}

View File

@ -1,43 +0,0 @@
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
= help: add #![feature(member_constraints)] to the crate attributes to enable
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
= help: add #![feature(member_constraints)] to the crate attributes to enable
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/ret-impl-trait-no-fg.rs:9:64
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another
|
= help: add #![feature(member_constraints)] to the crate attributes to enable
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: hidden type `(&u8, &u8)` captures lifetime '_#5r
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ret-impl-trait-no-fg.rs:9:1
|
LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: hidden type `(&u8, &u8)` captures lifetime '_#6r
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0700`.

View File

@ -3,8 +3,6 @@
// Test that a feature gate is needed to use `impl Trait` as the
// return type of an async.
#![feature(member_constraints)]
trait Trait<'a> { }
impl<T> Trait<'_> for T { }

View File

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch
--> $DIR/ret-impl-trait-one.rs:12:65
--> $DIR/ret-impl-trait-one.rs:10:65
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
| ------ ^^^^^^^^^^^^^^

View File

@ -1,10 +0,0 @@
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
//~^ ERROR ambiguous lifetime bound
//~| ERROR ambiguous lifetime bound
(x, y)
}
fn main() {}

View File

@ -1,18 +0,0 @@
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/feature-gate-member-constraints.rs:4:43
|
LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
|
= help: add #![feature(member_constraints)] to the crate attributes to enable
error: ambiguous lifetime bound in `impl Trait`
--> $DIR/feature-gate-member-constraints.rs:4:43
|
LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another
|
= help: add #![feature(member_constraints)] to the crate attributes to enable
error: aborting due to 2 previous errors

View File

@ -1,5 +1,5 @@
warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/error-handling.rs:6:32
--> $DIR/error-handling.rs:5:32
|
LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
| ^^^^^^^^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
error: lifetime may not live long enough
--> $DIR/error-handling.rs:26:16
--> $DIR/error-handling.rs:25:16
|
LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
| -- -- lifetime `'b` defined here

View File

@ -1,5 +1,5 @@
error: lifetime may not live long enough
--> $DIR/error-handling.rs:26:16
--> $DIR/error-handling.rs:25:16
|
LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
| -- -- lifetime `'b` defined here

View File

@ -1,6 +1,5 @@
// compile-flags:-Zborrowck=mir
#![feature(member_constraints)]
// revisions: min_tait full_tait
#![feature(min_type_alias_impl_trait)]
#![cfg_attr(full_tait, feature(type_alias_impl_trait))]

View File

@ -3,8 +3,6 @@
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir
#![feature(member_constraints)]
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}

View File

@ -3,10 +3,8 @@
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir
#![feature(member_constraints)]
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}
// Test case where we have elision in the impl trait and we have to
// pick the right region.
@ -26,4 +24,4 @@ fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> {
(a, a)
}
fn main() { }
fn main() {}

View File

@ -3,10 +3,9 @@
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir
#![feature(member_constraints)]
#![feature(min_type_alias_impl_trait)]
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}
// Here we wind up selecting `'a` and `'b` in the hidden type because
// those are the types that appear in the original values.
@ -28,4 +27,4 @@ fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
(a, b)
}
fn main() { }
fn main() {}

View File

@ -3,10 +3,8 @@
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir
#![feature(member_constraints)]
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}
// Here we wind up selecting `'a` and `'b` in the hidden type because
// those are the types that appear in the original values.
@ -26,4 +24,4 @@ fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
(a, b)
}
fn main() { }
fn main() {}

View File

@ -3,8 +3,6 @@
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir
#![feature(member_constraints)]
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}

View File

@ -1,7 +1,5 @@
// edition:2018
#![feature(member_constraints)]
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}

View File

@ -1,11 +1,11 @@
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unrelated.rs:18:74
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^
|
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
--> $DIR/ordinary-bounds-unrelated.rs:18:74
--> $DIR/ordinary-bounds-unrelated.rs:16:74
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^

View File

@ -1,7 +1,5 @@
// edition:2018
#![feature(member_constraints)]
trait Trait<'a, 'b> {}
impl<T> Trait<'_, '_> for T {}
@ -18,7 +16,7 @@ struct Ordinary<'a>(&'a u8);
// consider the loans for both `'a` and `'b` alive.
fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, '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
{
// We return a value:
//

View File

@ -1,11 +1,11 @@
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unsuited.rs:20:62
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^
|
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
--> $DIR/ordinary-bounds-unsuited.rs:20:62
--> $DIR/ordinary-bounds-unsuited.rs:18:62
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^

View File

@ -1,7 +1,5 @@
// check-pass
#![feature(member_constraints)]
trait MultiRegionTrait<'a, 'b> {}
impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}

View File

@ -1,5 +1,5 @@
warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-74761.rs:4:32
--> $DIR/issue-74761.rs:3:32
|
LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
| ^^^^^^^^^^^^^^^^^^^^^
@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:11:6
--> $DIR/issue-74761.rs:10:6
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter
error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:11:10
--> $DIR/issue-74761.rs:10:10
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter

View File

@ -1,11 +1,11 @@
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:11:6
--> $DIR/issue-74761.rs:10:6
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter
error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74761.rs:11:10
--> $DIR/issue-74761.rs:10:10
|
LL | impl<'a, 'b> A for () {
| ^^ unconstrained lifetime parameter

View File

@ -1,4 +1,3 @@
#![feature(member_constraints)]
// revisions: min_tait full_tait
#![feature(min_type_alias_impl_trait)]
#![cfg_attr(full_tait, feature(type_alias_impl_trait))]