Consider param-env for fast path
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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![]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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(());
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
| ^^^ ----
|
||||
@@ -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`.
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user