Make rustdoc tests use always applicable negative auto impls

This commit is contained in:
Michael Goulet 2025-02-28 02:43:12 +00:00
parent 3d62b279dd
commit 05a80608b3
8 changed files with 102 additions and 62 deletions

View file

@ -140,7 +140,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
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 self_descr = tcx.def_descr(adt_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"));
let mut err = struct_span_code_err!(
tcx.dcx(),
drop_impl_span,
impl_span,
E0366,
"`{polarity}{trait_name}` impls cannot be specialized",
);

View file

@ -5,7 +5,7 @@
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
// aren't stripped by the processing script and we can't check for the

View file

@ -3,7 +3,7 @@
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"]' \
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}