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
|
@ -391,6 +391,24 @@ rustc_queries! {
|
|||
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.
|
||||
query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
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,
|
||||
explicit_predicates_of,
|
||||
super_predicates_of,
|
||||
trait_explicit_predicates_and_bounds,
|
||||
type_param_predicates,
|
||||
trait_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`.
|
||||
/// 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::*;
|
||||
|
||||
debug!("explicit_predicates_of(def_id={:?})", def_id);
|
||||
|
@ -2116,6 +2117,71 @@ fn const_evaluatable_predicates_of<'tcx>(
|
|||
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(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
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_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 =
|
||||
trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// revisions: rpass cfail
|
||||
|
||||
trait Tr where Self::Arr: Sized {
|
||||
trait Tr
|
||||
where
|
||||
(Self::Arr,): Sized,
|
||||
{
|
||||
type Arr;
|
||||
|
||||
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 () {
|
||||
// Doesn't error because we abort compilation after the errors below.
|
||||
// See point-at-type-on-obligation-failure-3.rs
|
||||
type Assoc = bool;
|
||||
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
||||
}
|
||||
|
||||
trait Baz where Self::Assoc: Bar {
|
||||
trait Baz
|
||||
where
|
||||
Self::Assoc: Bar,
|
||||
{
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
|
@ -18,7 +19,10 @@ impl Baz for () {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,36 @@
|
|||
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 {
|
||||
| --- required by this bound in `Baz`
|
||||
LL | type Assoc: Bar;
|
||||
| --- required by this bound in `Foo::Assoc`
|
||||
...
|
||||
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
|
||||
--> $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 {
|
||||
| --- required by this bound in `Bat`
|
||||
LL | Self::Assoc: Bar,
|
||||
| --- required by this bound in `Baz::Assoc`
|
||||
LL | {
|
||||
LL | type Assoc;
|
||||
| ----- required by a bound in this
|
||||
...
|
||||
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`.
|
||||
|
|
|
@ -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`
|
||||
--> $DIR/issue-67765-async-diagnostic.rs:13:11
|
||||
--> $DIR/issue-67765-async-diagnostic.rs:13:5
|
||||
|
|
||||
LL | let b = &s[..];
|
||||
| - `s` is borrowed here
|
||||
LL |
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue