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::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind}; use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::{ use rustc_type_ir::{
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
Upcast as _, elaborate, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate,
}; };
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
@@ -133,19 +133,26 @@ where
cx: I, cx: I,
clause_def_id: I::DefId, clause_def_id: I::DefId,
goal_def_id: I::DefId, goal_def_id: I::DefId,
polarity: PredicatePolarity,
) -> bool { ) -> bool {
clause_def_id == goal_def_id clause_def_id == goal_def_id
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `MetaSized` supertrait being matched against a `Sized` assumption. // 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. // `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)) && cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized))
} }
if let Some(trait_clause) = assumption.as_trait_clause() if let Some(trait_clause) = assumption.as_trait_clause()
&& trait_clause.polarity() == goal.predicate.polarity && 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( && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
goal.predicate.trait_ref.args, goal.predicate.trait_ref.args,
trait_clause.skip_binder().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 // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
// are syntactic sugar for a lack of bounds so don't need this. // 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) if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized) && 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::bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, PolyTraitPredicate, SizedTraitKind, TraitPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
TypeFolder, TypeSuperFoldable, TypeVisitableExt, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
}; };
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer; pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
use rustc_span::Span; use rustc_span::Span;
@@ -427,7 +427,9 @@ pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
return candidate; return candidate;
} }
if obligation.predicate.polarity() != candidate.polarity() { if obligation.predicate.polarity() != PredicatePolarity::Positive
|| candidate.polarity() != PredicatePolarity::Positive
{
return candidate; 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
}