Remove predicates on associated types from traits
These need to only be bounds to avoid cycle errors in trait checking.
This commit is contained in:
parent
8787090964
commit
582ccec1c5
10 changed files with 141 additions and 42 deletions
|
@ -391,6 +391,24 @@ rustc_queries! {
|
||||||
desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns everything that looks like a predicate written explicitly
|
||||||
|
/// by the user on a trait item.
|
||||||
|
///
|
||||||
|
/// Traits are unusual, because predicates on associated types are
|
||||||
|
/// converted into bounds on that type for backwards compatibility:
|
||||||
|
///
|
||||||
|
/// trait X where Self::U: Copy { type U; }
|
||||||
|
///
|
||||||
|
/// becomes
|
||||||
|
///
|
||||||
|
/// trait X { type U: Copy; }
|
||||||
|
///
|
||||||
|
/// `explicit_predicates_of` and `explicit_item_bounds` will then take
|
||||||
|
/// the appropriate subsets of the predicates here.
|
||||||
|
query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> {
|
||||||
|
desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the predicates written explicitly by the user.
|
/// Returns the predicates written explicitly by the user.
|
||||||
query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
|
query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
|
||||||
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
|
||||||
|
|
|
@ -77,6 +77,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
projection_ty_from_predicates,
|
projection_ty_from_predicates,
|
||||||
explicit_predicates_of,
|
explicit_predicates_of,
|
||||||
super_predicates_of,
|
super_predicates_of,
|
||||||
|
trait_explicit_predicates_and_bounds,
|
||||||
type_param_predicates,
|
type_param_predicates,
|
||||||
trait_def,
|
trait_def,
|
||||||
adt_def,
|
adt_def,
|
||||||
|
@ -1731,7 +1732,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
||||||
|
|
||||||
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
|
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
|
||||||
/// N.B., this does not include any implied/inferred constraints.
|
/// N.B., this does not include any implied/inferred constraints.
|
||||||
fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
|
||||||
debug!("explicit_predicates_of(def_id={:?})", def_id);
|
debug!("explicit_predicates_of(def_id={:?})", def_id);
|
||||||
|
@ -2116,6 +2117,71 @@ fn const_evaluatable_predicates_of<'tcx>(
|
||||||
collector.preds
|
collector.preds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn trait_explicit_predicates_and_bounds(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> ty::GenericPredicates<'_> {
|
||||||
|
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
|
||||||
|
gather_explicit_predicates_of(tcx, def_id.to_def_id())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
|
||||||
|
if let DefKind::Trait = tcx.def_kind(def_id) {
|
||||||
|
// Remove bounds on associated types from the predicates, they will be
|
||||||
|
// returned by `explicit_item_bounds`.
|
||||||
|
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
|
||||||
|
let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
|
|
||||||
|
let is_assoc_item_ty = |ty: Ty<'_>| {
|
||||||
|
// For a predicate from a where clause to become a bound on an
|
||||||
|
// associated type:
|
||||||
|
// * It must use the identity substs of the item.
|
||||||
|
// * Since any generic parameters on the item are not in scope,
|
||||||
|
// this means that the item is not a GAT, and its identity substs
|
||||||
|
// are the same as the trait's.
|
||||||
|
// * It must be an associated type for this trait (*not* a
|
||||||
|
// supertrait).
|
||||||
|
if let ty::Projection(projection) = ty.kind {
|
||||||
|
if projection.substs == trait_identity_substs
|
||||||
|
&& tcx.associated_item(projection.item_def_id).container.id() == def_id
|
||||||
|
{
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let predicates: Vec<_> = predicates_and_bounds
|
||||||
|
.predicates
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(|(pred, _)| match pred.kind() {
|
||||||
|
ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.skip_binder().self_ty()),
|
||||||
|
ty::PredicateKind::Projection(proj) => {
|
||||||
|
!is_assoc_item_ty(proj.skip_binder().projection_ty.self_ty())
|
||||||
|
}
|
||||||
|
ty::PredicateKind::TypeOutlives(outlives) => {
|
||||||
|
!is_assoc_item_ty(outlives.skip_binder().0)
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if predicates.len() == predicates_and_bounds.predicates.len() {
|
||||||
|
predicates_and_bounds
|
||||||
|
} else {
|
||||||
|
ty::GenericPredicates {
|
||||||
|
parent: predicates_and_bounds.parent,
|
||||||
|
predicates: tcx.arena.alloc_slice(&predicates),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gather_explicit_predicates_of(tcx, def_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn projection_ty_from_predicates(
|
fn projection_ty_from_predicates(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: (
|
key: (
|
||||||
|
|
|
@ -34,7 +34,7 @@ fn associated_type_bounds<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
|
let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
|
||||||
let trait_predicates = tcx.predicates_of(trait_def_id);
|
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
|
||||||
|
|
||||||
let bounds_from_parent =
|
let bounds_from_parent =
|
||||||
trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() {
|
trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// revisions: rpass cfail
|
// revisions: rpass cfail
|
||||||
|
|
||||||
trait Tr where Self::Arr: Sized {
|
trait Tr
|
||||||
|
where
|
||||||
|
(Self::Arr,): Sized,
|
||||||
|
{
|
||||||
type Arr;
|
type Arr;
|
||||||
|
|
||||||
const C: usize = 0;
|
const C: usize = 0;
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`.
|
||||||
|
|
||||||
|
//check-pass
|
||||||
|
|
||||||
|
trait Op
|
||||||
|
where
|
||||||
|
Self::Output: Copy,
|
||||||
|
{
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn duplicate<T: Op>(x: T::Output) -> (T::Output, T::Output) {
|
||||||
|
(x, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -5,12 +5,13 @@ trait Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
// Doesn't error because we abort compilation after the errors below.
|
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
||||||
// See point-at-type-on-obligation-failure-3.rs
|
|
||||||
type Assoc = bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Baz where Self::Assoc: Bar {
|
trait Baz
|
||||||
|
where
|
||||||
|
Self::Assoc: Bar,
|
||||||
|
{
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +19,10 @@ impl Baz for () {
|
||||||
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bat where <Self as Bat>::Assoc: Bar {
|
trait Bat
|
||||||
|
where
|
||||||
|
<Self as Bat>::Assoc: Bar,
|
||||||
|
{
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,36 @@
|
||||||
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||||
--> $DIR/point-at-type-on-obligation-failure-2.rs:18:18
|
--> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
|
||||||
|
|
|
|
||||||
LL | trait Baz where Self::Assoc: Bar {
|
LL | type Assoc: Bar;
|
||||||
| --- required by this bound in `Baz`
|
| --- required by this bound in `Foo::Assoc`
|
||||||
...
|
...
|
||||||
LL | type Assoc = bool;
|
LL | type Assoc = bool;
|
||||||
| ^^^^ the trait `Bar` is not implemented for `bool`
|
| ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||||
|
|
||||||
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||||
--> $DIR/point-at-type-on-obligation-failure-2.rs:26:18
|
--> $DIR/point-at-type-on-obligation-failure-2.rs:19:5
|
||||||
|
|
|
|
||||||
LL | trait Bat where <Self as Bat>::Assoc: Bar {
|
LL | Self::Assoc: Bar,
|
||||||
| --- required by this bound in `Bat`
|
| --- required by this bound in `Baz::Assoc`
|
||||||
|
LL | {
|
||||||
|
LL | type Assoc;
|
||||||
|
| ----- required by a bound in this
|
||||||
...
|
...
|
||||||
LL | type Assoc = bool;
|
LL | type Assoc = bool;
|
||||||
| ^^^^ the trait `Bar` is not implemented for `bool`
|
| ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||||
|
--> $DIR/point-at-type-on-obligation-failure-2.rs:30:5
|
||||||
|
|
|
||||||
|
LL | <Self as Bat>::Assoc: Bar,
|
||||||
|
| --- required by this bound in `Bat::Assoc`
|
||||||
|
LL | {
|
||||||
|
LL | type Assoc;
|
||||||
|
| ----- required by a bound in this
|
||||||
|
...
|
||||||
|
LL | type Assoc = bool;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
trait Bar {}
|
|
||||||
|
|
||||||
trait Foo {
|
|
||||||
type Assoc: Bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Foo for () {
|
|
||||||
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,12 +0,0 @@
|
||||||
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
|
||||||
--> $DIR/point-at-type-on-obligation-failure-3.rs:8:5
|
|
||||||
|
|
|
||||||
LL | type Assoc: Bar;
|
|
||||||
| --- required by this bound in `Foo::Assoc`
|
|
||||||
...
|
|
||||||
LL | type Assoc = bool;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0515]: cannot return value referencing local variable `s`
|
error[E0515]: cannot return value referencing local variable `s`
|
||||||
--> $DIR/issue-67765-async-diagnostic.rs:13:11
|
--> $DIR/issue-67765-async-diagnostic.rs:13:5
|
||||||
|
|
|
|
||||||
LL | let b = &s[..];
|
LL | let b = &s[..];
|
||||||
| - `s` is borrowed here
|
| - `s` is borrowed here
|
||||||
LL |
|
LL |
|
||||||
LL | Err(b)?;
|
LL | Err(b)?;
|
||||||
| ^ returns a value referencing data owned by the current function
|
| ^^^^^^^ returns a value referencing data owned by the current function
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue