Skip to content

Commit 03469c3

Browse files
Make negative trait bounds work with the old trait solver
1 parent 40a63cb commit 03469c3

File tree

5 files changed

+36
-14
lines changed

5 files changed

+36
-14
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
701701

702702
let mut dup_bindings = FxHashMap::default();
703703
for binding in &assoc_bindings {
704+
// Don't register additional associated type bounds for negative bounds,
705+
// since we should have emitten an error for them earlier, and they will
706+
// not be well-formed!
707+
if polarity == ty::ImplPolarity::Negative {
708+
self.tcx()
709+
.sess
710+
.delay_span_bug(binding.span, "negative trait bounds should not have bindings");
711+
continue;
712+
}
713+
704714
// Specify type to assert that error was already reported in `Err` case.
705715
let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding(
706716
hir_id,

compiler/rustc_infer/src/traits/util.rs

+4
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
200200
let bound_predicate = elaboratable.predicate().kind();
201201
match bound_predicate.skip_binder() {
202202
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
203+
// Negative trait bounds do not imply any supertrait bounds
204+
if data.polarity == ty::ImplPolarity::Negative {
205+
return;
206+
}
203207
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
204208
let predicates = if self.only_self {
205209
tcx.super_predicates_of(data.def_id())

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
5757
if obligation.polarity() == ty::ImplPolarity::Negative {
5858
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
5959
self.assemble_candidates_from_impls(obligation, &mut candidates);
60+
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
6061
} else {
6162
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
6263

@@ -187,6 +188,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
187188

188189
// Keep only those bounds which may apply, and propagate overflow if it occurs.
189190
for bound in matching_bounds {
191+
if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity {
192+
continue;
193+
}
194+
190195
// FIXME(oli-obk): it is suspicious that we are dropping the constness and
191196
// polarity here.
192197
let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;

compiler/rustc_trait_selection/src/traits/wf.rs

+15
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,13 @@ impl<'tcx> WfPredicates<'tcx> {
328328
let tcx = self.tcx;
329329
let trait_ref = &trait_pred.trait_ref;
330330

331+
// Negative trait predicates don't require supertraits to hold, just
332+
// that their substs are WF.
333+
if trait_pred.polarity == ty::ImplPolarity::Negative {
334+
self.compute_negative_trait_pred(trait_ref);
335+
return;
336+
}
337+
331338
// if the trait predicate is not const, the wf obligations should not be const as well.
332339
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
333340
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
@@ -393,6 +400,14 @@ impl<'tcx> WfPredicates<'tcx> {
393400
);
394401
}
395402

403+
// Compute the obligations that are required for `trait_ref` to be WF,
404+
// given that it is a *negative* trait predicate.
405+
fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
406+
for arg in trait_ref.substs {
407+
self.compute(arg);
408+
}
409+
}
410+
396411
/// Pushes the obligations required for `trait_ref::Item` to be WF
397412
/// into `self.out`.
398413
fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {

tests/ui/traits/negative-bounds/simple.stderr

+2-14
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,7 @@ LL | #![feature(negative_bounds, negative_impls)]
77
= note: `#[warn(incomplete_features)]` on by default
88

99
error[E0277]: the trait bound `T: !Copy` is not satisfied
10-
--> $DIR/simple.rs:6:16
11-
|
12-
LL | not_copy::<T>();
13-
| ^ the trait `!Copy` is not implemented for `T`
14-
|
15-
note: required by a bound in `not_copy`
16-
--> $DIR/simple.rs:3:16
17-
|
18-
LL | fn not_copy<T: !Copy>() {}
19-
| ^^^^^ required by this bound in `not_copy`
20-
21-
error[E0277]: the trait bound `T: !Copy` is not satisfied
22-
--> $DIR/simple.rs:10:16
10+
--> $DIR/simple.rs:11:16
2311
|
2412
LL | not_copy::<T>();
2513
| ^ the trait `!Copy` is not implemented for `T`
@@ -77,6 +65,6 @@ LL + #[derive(Copy)]
7765
LL | struct NotNecessarilyCopyable;
7866
|
7967

80-
error: aborting due to 5 previous errors
68+
error: aborting due to 4 previous errors; 1 warning emitted
8169

8270
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)