Do not consider a T: !Sized candidate to satisfy a T: !MetaSized obligation.

This commit is contained in:
Zachary S
2025-08-09 23:16:19 -05:00
parent 2e2642e641
commit c7cd1b3b9d
5 changed files with 117 additions and 7 deletions

View File

@@ -6,8 +6,8 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::{
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
Upcast as _, elaborate,
self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
TypeVisitableExt as _, TypingMode, Upcast as _, elaborate,
};
use tracing::{debug, instrument, trace};
@@ -133,19 +133,26 @@ where
cx: I,
clause_def_id: I::DefId,
goal_def_id: I::DefId,
polarity: PredicatePolarity,
) -> bool {
clause_def_id == goal_def_id
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `MetaSized` supertrait being matched against a `Sized` assumption.
//
// `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this.
|| (cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized)
|| (polarity == PredicatePolarity::Positive
&& cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized)
&& cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized))
}
if let Some(trait_clause) = assumption.as_trait_clause()
&& trait_clause.polarity() == goal.predicate.polarity
&& trait_def_id_matches(ecx.cx(), trait_clause.def_id(), goal.predicate.def_id())
&& trait_def_id_matches(
ecx.cx(),
trait_clause.def_id(),
goal.predicate.def_id(),
goal.predicate.polarity,
)
&& DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
goal.predicate.trait_ref.args,
trait_clause.skip_binder().trait_ref.args,
@@ -168,6 +175,8 @@ where
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
// are syntactic sugar for a lack of bounds so don't need this.
// We don't need to check polarity, `fast_reject_assumption` already rejected non-`Positive`
// polarity `Sized` assumptions as matching non-`Positive` `MetaSized` goals.
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
{

View File

@@ -9,8 +9,8 @@ pub use rustc_infer::traits::util::*;
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{
self, PolyTraitPredicate, SizedTraitKind, TraitPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
use rustc_span::Span;
@@ -427,7 +427,9 @@ pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
return candidate;
}
if obligation.predicate.polarity() != candidate.polarity() {
if obligation.predicate.polarity() != PredicatePolarity::Positive
|| candidate.polarity() != PredicatePolarity::Positive
{
return candidate;
}

View File

@@ -0,0 +1,39 @@
error[E0277]: the trait bound `T: !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:12:11
|
LL | foo::<T>();
| ^ the trait bound `T: !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error[E0277]: the trait bound `(): !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:17:11
|
LL | foo::<()>();
| ^^ the trait bound `(): !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error[E0277]: the trait bound `str: !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:19:11
|
LL | foo::<str>();
| ^^^ the trait bound `str: !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@@ -0,0 +1,39 @@
error[E0277]: the trait bound `T: !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:12:11
|
LL | foo::<T>();
| ^ the trait bound `T: !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error[E0277]: the trait bound `(): !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:17:11
|
LL | foo::<()>();
| ^^ the trait bound `(): !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error[E0277]: the trait bound `str: !MetaSized` is not satisfied
--> $DIR/negative-metasized.rs:19:11
|
LL | foo::<str>();
| ^^^ the trait bound `str: !MetaSized` is not satisfied
|
note: required by a bound in `foo`
--> $DIR/negative-metasized.rs:9:11
|
LL | fn foo<T: !MetaSized>() {}
| ^^^^^^^^^^ required by this bound in `foo`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@@ -0,0 +1,21 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![feature(negative_bounds)]
#![feature(sized_hierarchy)]
use std::marker::MetaSized;
fn foo<T: !MetaSized>() {}
fn bar<T: !Sized + MetaSized>() {
foo::<T>();
//~^ ERROR the trait bound `T: !MetaSized` is not satisfied
}
fn main() {
foo::<()>();
//~^ ERROR the trait bound `(): !MetaSized` is not satisfied
foo::<str>();
//~^ ERROR the trait bound `str: !MetaSized` is not satisfied
}