Skip to content

Commit c7cd1b3

Browse files
committed
Do not consider a T: !Sized candidate to satisfy a T: !MetaSized obligation.
1 parent 2e2642e commit c7cd1b3

File tree

5 files changed

+117
-7
lines changed

5 files changed

+117
-7
lines changed

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_type_ir::inherent::*;
66
use rustc_type_ir::lang_items::TraitSolverLangItem;
77
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
88
use rustc_type_ir::{
9-
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
10-
Upcast as _, elaborate,
9+
self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
10+
TypeVisitableExt as _, TypingMode, Upcast as _, elaborate,
1111
};
1212
use tracing::{debug, instrument, trace};
1313

@@ -133,19 +133,26 @@ where
133133
cx: I,
134134
clause_def_id: I::DefId,
135135
goal_def_id: I::DefId,
136+
polarity: PredicatePolarity,
136137
) -> bool {
137138
clause_def_id == goal_def_id
138139
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
139140
// check for a `MetaSized` supertrait being matched against a `Sized` assumption.
140141
//
141142
// `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this.
142-
|| (cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized)
143+
|| (polarity == PredicatePolarity::Positive
144+
&& cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized)
143145
&& cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized))
144146
}
145147

146148
if let Some(trait_clause) = assumption.as_trait_clause()
147149
&& trait_clause.polarity() == goal.predicate.polarity
148-
&& trait_def_id_matches(ecx.cx(), trait_clause.def_id(), goal.predicate.def_id())
150+
&& trait_def_id_matches(
151+
ecx.cx(),
152+
trait_clause.def_id(),
153+
goal.predicate.def_id(),
154+
goal.predicate.polarity,
155+
)
149156
&& DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
150157
goal.predicate.trait_ref.args,
151158
trait_clause.skip_binder().trait_ref.args,
@@ -168,6 +175,8 @@ where
168175
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
169176
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
170177
// are syntactic sugar for a lack of bounds so don't need this.
178+
// We don't need to check polarity, `fast_reject_assumption` already rejected non-`Positive`
179+
// polarity `Sized` assumptions as matching non-`Positive` `MetaSized` goals.
171180
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
172181
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
173182
{

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pub use rustc_infer::traits::util::*;
99
use rustc_middle::bug;
1010
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
1111
use rustc_middle::ty::{
12-
self, PolyTraitPredicate, SizedTraitKind, TraitPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
13-
TypeFolder, TypeSuperFoldable, TypeVisitableExt,
12+
self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
13+
TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
1414
};
1515
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
1616
use rustc_span::Span;
@@ -427,7 +427,9 @@ pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
427427
return candidate;
428428
}
429429

430-
if obligation.predicate.polarity() != candidate.polarity() {
430+
if obligation.predicate.polarity() != PredicatePolarity::Positive
431+
|| candidate.polarity() != PredicatePolarity::Positive
432+
{
431433
return candidate;
432434
}
433435

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0277]: the trait bound `T: !MetaSized` is not satisfied
2+
--> $DIR/negative-metasized.rs:12:11
3+
|
4+
LL | foo::<T>();
5+
| ^ the trait bound `T: !MetaSized` is not satisfied
6+
|
7+
note: required by a bound in `foo`
8+
--> $DIR/negative-metasized.rs:9:11
9+
|
10+
LL | fn foo<T: !MetaSized>() {}
11+
| ^^^^^^^^^^ required by this bound in `foo`
12+
13+
error[E0277]: the trait bound `(): !MetaSized` is not satisfied
14+
--> $DIR/negative-metasized.rs:17:11
15+
|
16+
LL | foo::<()>();
17+
| ^^ the trait bound `(): !MetaSized` is not satisfied
18+
|
19+
note: required by a bound in `foo`
20+
--> $DIR/negative-metasized.rs:9:11
21+
|
22+
LL | fn foo<T: !MetaSized>() {}
23+
| ^^^^^^^^^^ required by this bound in `foo`
24+
25+
error[E0277]: the trait bound `str: !MetaSized` is not satisfied
26+
--> $DIR/negative-metasized.rs:19:11
27+
|
28+
LL | foo::<str>();
29+
| ^^^ the trait bound `str: !MetaSized` is not satisfied
30+
|
31+
note: required by a bound in `foo`
32+
--> $DIR/negative-metasized.rs:9:11
33+
|
34+
LL | fn foo<T: !MetaSized>() {}
35+
| ^^^^^^^^^^ required by this bound in `foo`
36+
37+
error: aborting due to 3 previous errors
38+
39+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0277]: the trait bound `T: !MetaSized` is not satisfied
2+
--> $DIR/negative-metasized.rs:12:11
3+
|
4+
LL | foo::<T>();
5+
| ^ the trait bound `T: !MetaSized` is not satisfied
6+
|
7+
note: required by a bound in `foo`
8+
--> $DIR/negative-metasized.rs:9:11
9+
|
10+
LL | fn foo<T: !MetaSized>() {}
11+
| ^^^^^^^^^^ required by this bound in `foo`
12+
13+
error[E0277]: the trait bound `(): !MetaSized` is not satisfied
14+
--> $DIR/negative-metasized.rs:17:11
15+
|
16+
LL | foo::<()>();
17+
| ^^ the trait bound `(): !MetaSized` is not satisfied
18+
|
19+
note: required by a bound in `foo`
20+
--> $DIR/negative-metasized.rs:9:11
21+
|
22+
LL | fn foo<T: !MetaSized>() {}
23+
| ^^^^^^^^^^ required by this bound in `foo`
24+
25+
error[E0277]: the trait bound `str: !MetaSized` is not satisfied
26+
--> $DIR/negative-metasized.rs:19:11
27+
|
28+
LL | foo::<str>();
29+
| ^^^ the trait bound `str: !MetaSized` is not satisfied
30+
|
31+
note: required by a bound in `foo`
32+
--> $DIR/negative-metasized.rs:9:11
33+
|
34+
LL | fn foo<T: !MetaSized>() {}
35+
| ^^^^^^^^^^ required by this bound in `foo`
36+
37+
error: aborting due to 3 previous errors
38+
39+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
#![feature(negative_bounds)]
5+
#![feature(sized_hierarchy)]
6+
7+
use std::marker::MetaSized;
8+
9+
fn foo<T: !MetaSized>() {}
10+
11+
fn bar<T: !Sized + MetaSized>() {
12+
foo::<T>();
13+
//~^ ERROR the trait bound `T: !MetaSized` is not satisfied
14+
}
15+
16+
fn main() {
17+
foo::<()>();
18+
//~^ ERROR the trait bound `(): !MetaSized` is not satisfied
19+
foo::<str>();
20+
//~^ ERROR the trait bound `str: !MetaSized` is not satisfied
21+
}

0 commit comments

Comments
 (0)