Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent specialized negative impls #74648

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::check::regionck::RegionCtxt;
use crate::hir;
use crate::hir::def_id::{DefId, LocalDefId};
use rustc_errors::{struct_span_err, ErrorReported};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
Expand All @@ -9,6 +8,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
Expand All @@ -32,6 +32,9 @@ use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
check_restricted_impl(tcx, drop_impl_did)
}
pub fn check_restricted_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
let dtor_self_type = tcx.type_of(drop_impl_did);
let dtor_predicates = tcx.predicates_of(drop_impl_did);
match dtor_self_type.kind {
Expand All @@ -45,21 +48,25 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro

ensure_drop_predicates_are_implied_by_item_defn(
tcx,
drop_impl_did.expect_local(),
dtor_predicates,
adt_def.did.expect_local(),
adt_def.did,
self_to_impl_substs,
)
}
_ => {
// Destructors only work on nominal types. This was
// already checked by coherence, but compilation may
// not have been terminated.
let span = tcx.def_span(drop_impl_did);
tcx.sess.delay_span_bug(
span,
&format!("should have been rejected by coherence check: {}", dtor_self_type),
);
Err(ErrorReported)
// Destructors only work on nominal types. This was
// already checked by coherence, for auto impls we
// simply check that there are no bounds here.
if dtor_predicates.predicates.is_empty() {
Ok(())
} else {
tcx.sess.span_err(
tcx.def_span(drop_impl_did),
"auto traits must not contain where bounds",
);
Err(ErrorReported)
}
}
}
}
Expand Down Expand Up @@ -94,11 +101,13 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
Err(_) => {
let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
let trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap();
struct_span_err!(
tcx.sess,
drop_impl_span,
E0366,
"`Drop` impls cannot be specialized"
"`{}` impls cannot be specialized",
trait_ref.print_only_trait_path()
)
.span_note(
item_span,
Expand Down Expand Up @@ -142,8 +151,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
/// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_did: LocalDefId,
dtor_predicates: ty::GenericPredicates<'tcx>,
self_type_did: LocalDefId,
self_type_did: DefId,
self_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorReported> {
let mut result = Ok(());
Expand Down Expand Up @@ -183,8 +193,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// absent. So we report an error that the Drop impl injected a
// predicate that is not present on the struct definition.

let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did);

// We can assume the predicates attached to struct/enum definition
// hold.
let generic_assumptions = tcx.predicates_of(self_type_did);
Expand Down Expand Up @@ -238,13 +246,15 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
};

if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
let item_span = tcx.hir().span(self_type_hir_id);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
let item_span = tcx.def_span(self_type_did);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
let trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap();
struct_span_err!(
tcx.sess,
predicate_sp,
E0367,
"`Drop` impl requires `{}` but the {} it is implemented for does not",
"`{}` impl requires `{}` but the {} it is implemented for does not",
trait_ref.print_only_trait_path(),
predicate,
self_descr,
)
Expand Down
9 changes: 6 additions & 3 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::check::{FnCtxt, Inherited};
use crate::check::{dropck::check_restricted_impl, FnCtxt, Inherited};
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};

use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
Expand Down Expand Up @@ -123,7 +123,10 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_impl(tcx, item, self_ty, of_trait);
}
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
if let Err(ErrorReported) = check_restricted_impl(tcx, def_id.to_def_id()) {
return;
}

if let hir::Defaultness::Default { .. } = defaultness {
let mut spans = vec![span];
spans.extend(defaultness_span);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

auto trait MyTrait {}

impl<T> !MyTrait for *mut T {}
impl<T: ?Sized> !MyTrait for *mut T {}

struct MyS;

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17959.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct G<T: ?Sized> {
}

impl<T> Drop for G<T> {
//~^ ERROR `Drop` impl requires `T: std::marker::Sized`
//~^ ERROR `std::ops::Drop` impl requires `T: std::marker::Sized`
fn drop(&mut self) {
if !self._ptr.is_null() {
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-17959.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0367]: `Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `T: std::marker::Sized` but the struct it is implemented for does not
--> $DIR/issue-17959.rs:11:6
|
LL | impl<T> Drop for G<T> {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-29516.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// check-pass
#![feature(optin_builtin_traits)]
#![feature(negative_impls)]

auto trait NotSame {}

impl<A> !NotSame for (A, A) {}
impl<A> !NotSame for (A, A) {} //~ ERROR auto traits must not contain where bounds
// FIXME: Consider allowing (A, B) with `A: Sized`.

trait OneOfEach {}

Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/issues/issue-29516.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: auto traits must not contain where bounds
lcnr marked this conversation as resolved.
Show resolved Hide resolved
--> $DIR/issue-29516.rs:6:1
|
LL | impl<A> !NotSame for (A, A) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-38868.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0366]: `Drop` impls cannot be specialized
error[E0366]: `std::ops::Drop` impls cannot be specialized
--> $DIR/issue-38868.rs:5:1
|
LL | / impl Drop for List<i32> {
Expand Down
14 changes: 7 additions & 7 deletions src/test/ui/issues/issue-41974.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#[derive(Copy, Clone)]
struct Flags;

trait A {
}
trait A {}

impl<T> Drop for T where T: A { //~ ERROR E0119
//~^ ERROR E0120
//~| ERROR E0210
fn drop(&mut self) {
}
impl<T> Drop for T where T: A {
//~^ ERROR auto traits must not contain where bounds
lcnr marked this conversation as resolved.
Show resolved Hide resolved
//~| ERROR E0119
//~| ERROR E0120
//~| ERROR E0210
fn drop(&mut self) {}
}

fn main() {}
26 changes: 19 additions & 7 deletions src/test/ui/issues/issue-41974.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_>`:
--> $DIR/issue-41974.rs:7:1
--> $DIR/issue-41974.rs:6:1
|
LL | impl<T> Drop for T where T: A {
LL | impl<T> Drop for T where T: A {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `alloc`:
Expand All @@ -10,21 +10,33 @@ LL | impl<T> Drop for T where T: A {
= note: downstream crates may implement trait `A` for type `std::boxed::Box<_>`

error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
--> $DIR/issue-41974.rs:7:18
--> $DIR/issue-41974.rs:6:18
|
LL | impl<T> Drop for T where T: A {
LL | impl<T> Drop for T where T: A {
| ^ must be a struct, enum, or union

error: auto traits must not contain where bounds
--> $DIR/issue-41974.rs:6:1
|
LL | / impl<T> Drop for T where T: A {
LL | |
LL | |
LL | |
LL | |
LL | | fn drop(&mut self) {}
LL | | }
| |_^

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> $DIR/issue-41974.rs:7:6
--> $DIR/issue-41974.rs:6:6
|
LL | impl<T> Drop for T where T: A {
LL | impl<T> Drop for T where T: A {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

error: aborting due to 3 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0119, E0120, E0210.
For more information about an error, try `rustc --explain E0119`.
18 changes: 9 additions & 9 deletions src/test/ui/reject-specialized-drops-8142.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ struct TupleStruct<T>(T);
union Union<T: Copy> { f: T }

impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT
//~^ ERROR `Drop` impl requires `'adds_bnd: 'al`
//~^ ERROR `std::ops::Drop` impl requires `'adds_bnd: 'al`
fn drop(&mut self) { } }

impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT
//~^ ERROR `Drop` impl requires `'adds_bnd: 'al`
//~^ ERROR `std::ops::Drop` impl requires `'adds_bnd: 'al`
fn drop(&mut self) { } }

impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT
Expand All @@ -38,13 +38,13 @@ impl Drop for N<'static> { fn drop(&mut self) { } } // RE
impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT

impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impls cannot be specialized
//~^ ERROR `std::ops::Drop` impls cannot be specialized

impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound`

impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd`
//~^ ERROR `std::ops::Drop` impl requires `AddsRBnd: 'rbnd`

impl<Bs:Bound> Drop for S<Bs> { fn drop(&mut self) { } } // ACCEPT

Expand All @@ -53,18 +53,18 @@ impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT
impl Drop for U { fn drop(&mut self) { } } // ACCEPT

impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impls cannot be specialized
//~^ ERROR `std::ops::Drop` impls cannot be specialized

impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw`

impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound`

impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound`

impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
//~^ ERROR `std::ops::Drop` impl requires `AddsBnd: Bound`

pub fn main() { }
18 changes: 9 additions & 9 deletions src/test/ui/reject-specialized-drops-8142.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:67:21
|
LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
Expand All @@ -10,7 +10,7 @@ note: the implementor must specify the same requirement
LL | union Union<T: Copy> { f: T }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:23:20
|
LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT
Expand All @@ -22,7 +22,7 @@ note: the implementor must specify the same requirement
LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:27:67
|
LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT
Expand All @@ -49,7 +49,7 @@ LL | struct N<'n> { x: &'n i8 }
| ^^
= note: ...does not necessarily outlive the static lifetime

error[E0366]: `Drop` impls cannot be specialized
error[E0366]: `std::ops::Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:40:1
|
LL | impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
Expand All @@ -61,7 +61,7 @@ note: use the same sequence of generic type, lifetime and const parameters as th
LL | struct P<Tp> { x: *const Tp }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:43:14
|
LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
Expand All @@ -73,7 +73,7 @@ note: the implementor must specify the same requirement
LL | struct Q<Tq> { x: *const Tq }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:46:21
|
LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
Expand All @@ -85,7 +85,7 @@ note: the implementor must specify the same requirement
LL | struct R<Tr> { x: *const Tr }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0366]: `Drop` impls cannot be specialized
error[E0366]: `std::ops::Drop` impls cannot be specialized
--> $DIR/reject-specialized-drops-8142.rs:55:1
|
LL | impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
Expand Down Expand Up @@ -121,7 +121,7 @@ LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJ
= note: expected `W<'l1, 'l2>`
found `W<'_, '_>`

error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:61:14
|
LL | impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
Expand All @@ -133,7 +133,7 @@ note: the implementor must specify the same requirement
LL | enum Enum<T> { Variant(T) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
error[E0367]: `std::ops::Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
--> $DIR/reject-specialized-drops-8142.rs:64:14
|
LL | impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
Expand Down
Loading