Make rustdoc tests use always applicable negative auto impls
This commit is contained in:
parent
3d62b279dd
commit
05a80608b3
8 changed files with 102 additions and 62 deletions
|
@ -140,7 +140,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let drop_impl_span = tcx.def_span(impl_def_id);
|
let impl_span = tcx.def_span(impl_def_id);
|
||||||
let item_span = tcx.def_span(adt_def_id);
|
let item_span = tcx.def_span(adt_def_id);
|
||||||
let self_descr = tcx.def_descr(adt_def_id);
|
let self_descr = tcx.def_descr(adt_def_id);
|
||||||
let polarity = match tcx.impl_polarity(impl_def_id) {
|
let polarity = match tcx.impl_polarity(impl_def_id) {
|
||||||
|
@ -151,7 +151,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
|
||||||
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
|
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
|
||||||
let mut err = struct_span_code_err!(
|
let mut err = struct_span_code_err!(
|
||||||
tcx.dcx(),
|
tcx.dcx(),
|
||||||
drop_impl_span,
|
impl_span,
|
||||||
E0366,
|
E0366,
|
||||||
"`{polarity}{trait_name}` impls cannot be specialized",
|
"`{polarity}{trait_name}` impls cannot be specialized",
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
extern crate rustdoc_impl_parts_crosscrate;
|
extern crate rustdoc_impl_parts_crosscrate;
|
||||||
|
|
||||||
pub struct Bar<T> { t: T }
|
pub struct Bar<T: Copy + Send> { t: T }
|
||||||
|
|
||||||
// The output file is html embedded in javascript, so the html tags
|
// The output file is html embedded in javascript, so the html tags
|
||||||
// aren't stripped by the processing script and we can't check for the
|
// aren't stripped by the processing script and we can't check for the
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
pub auto trait AnAutoTrait {}
|
pub auto trait AnAutoTrait {}
|
||||||
|
|
||||||
pub struct Foo<T> { field: T }
|
pub struct Foo<T: Clone + Sync> { field: T }
|
||||||
|
|
||||||
//@ has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \
|
//@ has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \
|
||||||
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
|
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
|
|
||||||
// `T = Test, F = ()`, all bounds are true, making both impls applicable.
|
|
||||||
// `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
|
|
||||||
// `Is<Test>: NotNil` is true because of `auto trait` and lack of negative impl.
|
|
||||||
|
|
||||||
#![feature(negative_impls)]
|
|
||||||
#![feature(auto_traits)]
|
|
||||||
|
|
||||||
struct Nil;
|
|
||||||
struct Cons<H>(H);
|
|
||||||
struct Test;
|
|
||||||
|
|
||||||
trait Fold<F> {}
|
|
||||||
|
|
||||||
impl<T, F> Fold<F> for Cons<T>
|
|
||||||
// 0
|
|
||||||
where
|
|
||||||
T: Fold<Nil>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Fold<F> for Cons<T>
|
|
||||||
// 1
|
|
||||||
where
|
|
||||||
T: Fold<F>,
|
|
||||||
private::Is<T>: private::NotNil,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> Fold<F> for Test {} // 2
|
|
||||||
|
|
||||||
mod private {
|
|
||||||
use crate::Nil;
|
|
||||||
|
|
||||||
pub struct Is<T>(T);
|
|
||||||
pub auto trait NotNil {}
|
|
||||||
|
|
||||||
impl !NotNil for Is<Nil> {}
|
|
||||||
//~^ ERROR `!NotNil` impls cannot be specialized
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,16 +0,0 @@
|
||||||
error[E0366]: `!NotNil` impls cannot be specialized
|
|
||||||
--> $DIR/coherence-overlap-negative-impls.rs:38:5
|
|
||||||
|
|
|
||||||
LL | impl !NotNil for Is<Nil> {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `Nil` is not a generic parameter
|
|
||||||
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
|
||||||
--> $DIR/coherence-overlap-negative-impls.rs:35:5
|
|
||||||
|
|
|
||||||
LL | pub struct Is<T>(T);
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0366`.
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#![feature(auto_traits, negative_impls)]
|
||||||
|
|
||||||
|
auto trait Foo {}
|
||||||
|
|
||||||
|
struct AdditionalLt<'a, T>(&'a (), T);
|
||||||
|
impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {}
|
||||||
|
//~^ ERROR `!Foo` impl requires `T: 'a` but the struct it is implemented for does not
|
||||||
|
|
||||||
|
struct AdditionalBound<T>(T);
|
||||||
|
trait Bound {}
|
||||||
|
impl<T: Bound> !Foo for AdditionalBound<T> {}
|
||||||
|
//~^ ERROR `!Foo` impl requires `T: Bound` but the struct it is implemented for does not
|
||||||
|
|
||||||
|
struct TwoParam<T, U>(T, U);
|
||||||
|
impl<T> !Foo for TwoParam<T, T> {}
|
||||||
|
//~^ ERROR `!Foo` impls cannot be specialized
|
||||||
|
|
||||||
|
struct ConcreteParam<T>(T);
|
||||||
|
impl !Foo for ConcreteParam<i32> {}
|
||||||
|
//~^ ERROR `!Foo` impls cannot be specialized
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,54 @@
|
||||||
|
error[E0367]: `!Foo` impl requires `T: 'a` but the struct it is implemented for does not
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:6:13
|
||||||
|
|
|
||||||
|
LL | impl<'a, T: 'a> !Foo for AdditionalLt<'a, T> {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:5:1
|
||||||
|
|
|
||||||
|
LL | struct AdditionalLt<'a, T>(&'a (), T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0367]: `!Foo` impl requires `T: Bound` but the struct it is implemented for does not
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:11:9
|
||||||
|
|
|
||||||
|
LL | impl<T: Bound> !Foo for AdditionalBound<T> {}
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
note: the implementor must specify the same requirement
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:9:1
|
||||||
|
|
|
||||||
|
LL | struct AdditionalBound<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0366]: `!Foo` impls cannot be specialized
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:15:1
|
||||||
|
|
|
||||||
|
LL | impl<T> !Foo for TwoParam<T, T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `T` is mentioned multiple times
|
||||||
|
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:14:1
|
||||||
|
|
|
||||||
|
LL | struct TwoParam<T, U>(T, U);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0366]: `!Foo` impls cannot be specialized
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:19:1
|
||||||
|
|
|
||||||
|
LL | impl !Foo for ConcreteParam<i32> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `i32` is not a generic parameter
|
||||||
|
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
|
||||||
|
--> $DIR/negated-auto-traits-validity-error.rs:18:1
|
||||||
|
|
|
||||||
|
LL | struct ConcreteParam<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0366, E0367.
|
||||||
|
For more information about an error, try `rustc --explain E0366`.
|
|
@ -0,0 +1,22 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(auto_traits, negative_impls)]
|
||||||
|
|
||||||
|
auto trait Foo {}
|
||||||
|
auto trait Bar {}
|
||||||
|
|
||||||
|
struct NeedsOutlives<'a, T>(&'a T);
|
||||||
|
|
||||||
|
impl<'a, T: 'a> !Foo for NeedsOutlives<'a, T> {}
|
||||||
|
|
||||||
|
// Leaving out the lifetime bound
|
||||||
|
impl<'a, T> !Bar for NeedsOutlives<'a, T> {}
|
||||||
|
|
||||||
|
struct NeedsSend<T: Send>(T);
|
||||||
|
|
||||||
|
impl<T: Send> !Foo for NeedsSend<T> {}
|
||||||
|
|
||||||
|
// Leaving off the trait bound
|
||||||
|
impl<T> !Bar for NeedsSend<T> {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue