Consider param-env for fast path

This commit is contained in:
Michael Goulet
2025-07-20 17:44:55 +00:00
parent 0864097cd3
commit 1e96d7a553
14 changed files with 82 additions and 72 deletions

View File

@@ -12,11 +12,11 @@ use rustc_infer::traits::solve::Goal;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::{
self, SizedTraitKind, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph};
#[repr(transparent)]
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
@@ -76,19 +76,11 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
if trait_pred.polarity() == ty::PredicatePolarity::Positive {
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized)
if self
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::Sized) =>
{
Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
let predicate = self.resolve_vars_if_possible(goal.predicate);
if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
return Some(Certainty::Yes);
}
Some(LangItem::MetaSized)
if self
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::MetaSized) =>
{
return Some(Certainty::Yes);
}
Some(LangItem::Copy | LangItem::Clone) => {
let self_ty =

View File

@@ -363,7 +363,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let infcx = self.selcx.infcx;
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) {
return ProcessResult::Changed(thin_vec![]);
}

View File

@@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
if sizedness_fast_path(tcx, key.value.predicate) {
if sizedness_fast_path(tcx, key.value.predicate, key.param_env) {
return Some(());
}

View File

@@ -597,7 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
None => self.check_recursion_limit(&obligation, &obligation)?,
}
if sizedness_fast_path(self.tcx(), obligation.predicate) {
if sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) {
return Ok(EvaluatedToOk);
}

View File

@@ -365,7 +365,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
}
}
pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
pub fn sizedness_fast_path<'tcx>(
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
// canonicalize and all that for such cases.
@@ -390,6 +394,20 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
debug!("fast path -- trivial sizedness");
return true;
}
if matches!(trait_pred.self_ty().kind(), ty::Param(_) | ty::Placeholder(_)) {
for clause in param_env.caller_bounds() {
if let ty::ClauseKind::Trait(clause_pred) = clause.kind().skip_binder()
&& clause_pred.polarity == ty::PredicatePolarity::Positive
&& clause_pred.self_ty() == trait_pred.self_ty()
&& (clause_pred.def_id() == trait_pred.def_id()
|| (sizedness == SizedTraitKind::MetaSized
&& tcx.is_lang_item(clause_pred.def_id(), LangItem::Sized)))
{
return true;
}
}
}
}
false

View File

@@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>(
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd { param_env, value: predicate } = goal;
if sizedness_fast_path(tcx, predicate) {
if sizedness_fast_path(tcx, predicate, param_env) {
return Ok(EvaluationResult::EvaluatedToOk);
}

View File

@@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/incomplete-inference-issue-143992.rs:27:28
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
LL | let _x = T::Assoc::new(());
| ------------- ^^ expected `[u32; 1]`, found `()`
@@ -7,7 +7,7 @@ LL | let _x = T::Assoc::new(());
| arguments to this function are incorrect
|
note: associated function defined here
--> $DIR/incomplete-inference-issue-143992.rs:18:8
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
LL | fn new(r: R) -> R {
| ^^^ ----

View File

@@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
LL | let _x = T::Assoc::new(());
| ------------- ^^ expected `[u32; 1]`, found `()`
| |
| arguments to this function are incorrect
|
note: associated function defined here
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
LL | fn new(r: R) -> R {
| ^^^ ----
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@@ -1,9 +1,12 @@
//@ compile-flags: --crate-type=lib
//@ revisions: current next
//@ revisions: current next current_sized_hierarchy next_sized_hierarchy
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[current] check-pass
//@[next] check-pass
//@[next] compile-flags: -Znext-solver
//@[next] check-fail
//@[next_sized_hierarchy] compile-flags: -Znext-solver
#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))]
// Test that we avoid incomplete inference when normalizing. Without this,
// `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
@@ -25,5 +28,6 @@ where
T::Assoc<[u32; 1]>: Clone,
{
let _x = T::Assoc::new(());
//[next]~^ ERROR mismatched types
//[next_sized_hierarchy]~^ ERROR mismatched types
//[current_sized_hierarchy]~^^ ERROR mismatched types
}

View File

@@ -12,13 +12,6 @@ LL | impl<T: Bound, U> Trait<U> for T {
| ----- ^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `Bound`
--> $DIR/normalizes-to-is-not-productive.rs:8:1
|
LL | / trait Bound {
LL | | fn method();
LL | | }
| |_^ required by this bound in `Bound`
error[E0277]: the trait bound `Foo: Bound` is not satisfied
--> $DIR/normalizes-to-is-not-productive.rs:47:19

View File

@@ -19,23 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
LL | Self::Assoc: A<T>,
| ^^^^
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: MetaSized`
--> $DIR/normalize-param-env-2.rs:24:22
|
LL | Self::Assoc: A<T>,
| ^^^^
|
note: required by a bound in `A`
--> $DIR/normalize-param-env-2.rs:9:1
|
LL | / trait A<T> {
LL | | type Assoc;
LL | |
LL | | fn f()
... |
LL | | }
| |_^ required by this bound in `A`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
--> $DIR/normalize-param-env-2.rs:24:22
|
@@ -63,6 +46,6 @@ LL | where
LL | Self::Assoc: A<T>,
| ^^^^ required by this bound in `A::f`
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.

View File

@@ -4,20 +4,6 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
LL | <T as Trait>::Assoc: Trait,
| ^^^^^
error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
--> $DIR/normalize-param-env-4.rs:19:26
|
LL | <T as Trait>::Assoc: Trait,
| ^^^^^
|
note: required by a bound in `Trait`
--> $DIR/normalize-param-env-4.rs:7:1
|
LL | / trait Trait {
LL | | type Assoc;
LL | | }
| |_^ required by this bound in `Trait`
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View File

@@ -1,13 +1,13 @@
use std::ops::Add;
fn dbl<T>(x: T) -> <T as Add>::Output
//~^ ERROR type annotations needed
where
T: Copy + Add,
UUU: Copy,
//~^ ERROR cannot find type `UUU` in this scope
{
x + x
//~^ ERROR use of moved value: `x`
}
fn main() {

View File

@@ -1,16 +1,33 @@
error[E0412]: cannot find type `UUU` in this scope
--> $DIR/ignore-err-clauses.rs:7:5
--> $DIR/ignore-err-clauses.rs:6:5
|
LL | UUU: Copy,
| ^^^ not found in this scope
error[E0282]: type annotations needed
--> $DIR/ignore-err-clauses.rs:3:14
error[E0382]: use of moved value: `x`
--> $DIR/ignore-err-clauses.rs:9:9
|
LL | fn dbl<T>(x: T) -> <T as Add>::Output
| ^ cannot infer type for type parameter `T`
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
...
LL | x + x
| ----^
| | |
| | value used here after move
| `x` moved due to usage in operator
|
help: if `T` implemented `Clone`, you could clone the value
--> $DIR/ignore-err-clauses.rs:3:8
|
LL | fn dbl<T>(x: T) -> <T as Add>::Output
| ^ consider constraining this type parameter with `Clone`
...
LL | x + x
| - you could clone this value
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0412.
For more information about an error, try `rustc --explain E0282`.
Some errors have detailed explanations: E0382, E0412.
For more information about an error, try `rustc --explain E0382`.