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::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::Certainty;
|
use rustc_middle::traits::solve::Certainty;
|
||||||
use rustc_middle::ty::{
|
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 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)]
|
#[repr(transparent)]
|
||||||
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
|
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 {
|
if trait_pred.polarity() == ty::PredicatePolarity::Positive {
|
||||||
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
|
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
|
||||||
Some(LangItem::Sized)
|
Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
|
||||||
if self
|
let predicate = self.resolve_vars_if_possible(goal.predicate);
|
||||||
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
|
if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
|
||||||
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::Sized) =>
|
|
||||||
{
|
|
||||||
return Some(Certainty::Yes);
|
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) => {
|
Some(LangItem::Copy | LangItem::Clone) => {
|
||||||
let self_ty =
|
let self_ty =
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||||||
|
|
||||||
let infcx = self.selcx.infcx;
|
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![]);
|
return ProcessResult::Changed(thin_vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: &ParamEnvAnd<'tcx, Self>,
|
key: &ParamEnvAnd<'tcx, Self>,
|
||||||
) -> Option<Self::QueryResponse> {
|
) -> Option<Self::QueryResponse> {
|
||||||
if sizedness_fast_path(tcx, key.value.predicate) {
|
if sizedness_fast_path(tcx, key.value.predicate, key.param_env) {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -597,7 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
None => self.check_recursion_limit(&obligation, &obligation)?,
|
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);
|
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
|
// 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
|
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
|
||||||
// canonicalize and all that for such cases.
|
// 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");
|
debug!("fast path -- trivial sizedness");
|
||||||
return true;
|
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
|
false
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>(
|
|||||||
debug!("evaluate_obligation: goal={:#?}", goal);
|
debug!("evaluate_obligation: goal={:#?}", goal);
|
||||||
let ParamEnvAnd { param_env, value: predicate } = 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);
|
return Ok(EvaluationResult::EvaluatedToOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error[E0308]: mismatched types
|
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(());
|
LL | let _x = T::Assoc::new(());
|
||||||
| ------------- ^^ expected `[u32; 1]`, found `()`
|
| ------------- ^^ expected `[u32; 1]`, found `()`
|
||||||
@@ -7,7 +7,7 @@ LL | let _x = T::Assoc::new(());
|
|||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
note: associated function defined here
|
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 {
|
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
|
//@ compile-flags: --crate-type=lib
|
||||||
//@ revisions: current next
|
//@ revisions: current next current_sized_hierarchy next_sized_hierarchy
|
||||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
//@[current] check-pass
|
//@[current] check-pass
|
||||||
|
//@[next] check-pass
|
||||||
//@[next] compile-flags: -Znext-solver
|
//@[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,
|
// Test that we avoid incomplete inference when normalizing. Without this,
|
||||||
// `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
|
// `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
|
||||||
@@ -25,5 +28,6 @@ where
|
|||||||
T::Assoc<[u32; 1]>: Clone,
|
T::Assoc<[u32; 1]>: Clone,
|
||||||
{
|
{
|
||||||
let _x = T::Assoc::new(());
|
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
|
| 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
|
error[E0277]: the trait bound `Foo: Bound` is not satisfied
|
||||||
--> $DIR/normalizes-to-is-not-productive.rs:47:19
|
--> $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>,
|
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`
|
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
|
||||||
--> $DIR/normalize-param-env-2.rs:24:22
|
--> $DIR/normalize-param-env-2.rs:24:22
|
||||||
|
|
|
|
||||||
@@ -63,6 +46,6 @@ LL | where
|
|||||||
LL | Self::Assoc: A<T>,
|
LL | Self::Assoc: A<T>,
|
||||||
| ^^^^ required by this bound in `A::f`
|
| ^^^^ 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`.
|
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,
|
LL | <T as Trait>::Assoc: Trait,
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
|
error: aborting due to 1 previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0275`.
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
fn dbl<T>(x: T) -> <T as Add>::Output
|
fn dbl<T>(x: T) -> <T as Add>::Output
|
||||||
//~^ ERROR type annotations needed
|
|
||||||
where
|
where
|
||||||
T: Copy + Add,
|
T: Copy + Add,
|
||||||
UUU: Copy,
|
UUU: Copy,
|
||||||
//~^ ERROR cannot find type `UUU` in this scope
|
//~^ ERROR cannot find type `UUU` in this scope
|
||||||
{
|
{
|
||||||
x + x
|
x + x
|
||||||
|
//~^ ERROR use of moved value: `x`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|||||||
@@ -1,16 +1,33 @@
|
|||||||
error[E0412]: cannot find type `UUU` in this scope
|
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,
|
LL | UUU: Copy,
|
||||||
| ^^^ not found in this scope
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/ignore-err-clauses.rs:3:14
|
--> $DIR/ignore-err-clauses.rs:9:9
|
||||||
|
|
|
|
||||||
LL | fn dbl<T>(x: T) -> <T as Add>::Output
|
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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0412.
|
Some errors have detailed explanations: E0382, E0412.
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
For more information about an error, try `rustc --explain E0382`.
|
||||||
|
|||||||
Reference in New Issue
Block a user