mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Filter out self-referential projection predicates
If we end up with a projection predicate that equates a type with itself (e.g. <T as MyType>::Value == <T as MyType>::Value), we can run into issues if we try to add it to our ParamEnv.
This commit is contained in:
parent
1a84d211a2
commit
5045e12bd7
@ -649,6 +649,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
};
|
||||
}
|
||||
|
||||
fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
|
||||
match p.ty().skip_binder().sty {
|
||||
ty::Projection(proj) if proj == p.skip_binder().projection_ty => {
|
||||
true
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate_nested_obligations<
|
||||
'b,
|
||||
'c,
|
||||
@ -713,7 +722,23 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
debug!("evaluate_nested_obligations: adding projection predicate\
|
||||
to computed_preds: {:?}", predicate);
|
||||
|
||||
self.add_user_pred(computed_preds, predicate);
|
||||
// Under unusual circumstances, we can end up with a self-refeential
|
||||
// projection predicate. For example:
|
||||
// <T as MyType>::Value == <T as MyType>::Value
|
||||
// Not only is displaying this to the user pointless,
|
||||
// having it in the ParamEnv will cause an issue if we try to call
|
||||
// poly_project_and_unify_type on the predicate, since this kind of
|
||||
// predicate will normally never end up in a ParamEnv.
|
||||
//
|
||||
// For these reasons, we ignore these weird predicates,
|
||||
// ensuring that we're able to properly synthesize an auto trait impl
|
||||
if self.is_self_referential_projection(p) {
|
||||
debug!("evaluate_nested_obligations: encountered a projection
|
||||
predicate equating a type with itself! Skipping");
|
||||
|
||||
} else {
|
||||
self.add_user_pred(computed_preds, predicate);
|
||||
}
|
||||
}
|
||||
|
||||
// We can only call poly_project_and_unify_type when our predicate's
|
||||
|
40
src/test/rustdoc/synthetic_auto/self-referential.rs
Normal file
40
src/test/rustdoc/synthetic_auto/self-referential.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Some unusual code minimized from
|
||||
// https://github.com/sile/handy_async/tree/7b619b762c06544fc67792c8ff8ebc24a88fdb98
|
||||
|
||||
pub trait Pattern {
|
||||
type Value;
|
||||
}
|
||||
|
||||
pub struct Constrain<A, B = A, C = A>(A, B, C);
|
||||
|
||||
impl<A, B, C> Pattern for Constrain<A, B, C>
|
||||
where A: Pattern,
|
||||
B: Pattern<Value = A::Value>,
|
||||
C: Pattern<Value = A::Value>,
|
||||
{
|
||||
type Value = A::Value;
|
||||
}
|
||||
|
||||
pub struct Wrapper<T>(T);
|
||||
|
||||
impl<T> Pattern for Wrapper<T> {
|
||||
type Value = T;
|
||||
}
|
||||
|
||||
|
||||
// @has self_referential/struct.WriteAndThen.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<P1> Send for \
|
||||
// WriteAndThen<P1> where <P1 as Pattern>::Value: Send"
|
||||
pub struct WriteAndThen<P1>(pub P1::Value, pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
|
||||
where P1: Pattern;
|
||||
|
Loading…
Reference in New Issue
Block a user