Skip to content

Consider param-env for sizedness fast path #143309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions compiler/rustc_trait_selection/src/solve/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>);
Expand Down Expand Up @@ -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) =>
{
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::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::Copy | LangItem::Clone) => {
let self_ty =
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,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![]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,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);
}

Expand Down
27 changes: 23 additions & 4 deletions compiler/rustc_trait_selection/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,23 +364,42 @@ 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.
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
predicate.kind().skip_binder()
&& trait_pred.polarity == ty::PredicatePolarity::Positive
{
let sizedness = match tcx.as_lang_item(trait_ref.def_id()) {
let sizedness = match tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized) => SizedTraitKind::Sized,
Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
_ => return false,
};

if trait_ref.self_ty().has_trivial_sizedness(tcx, sizedness) {
if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
let mut selcx = SelectionContext::new(&infcx);

if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) {
if sizedness_fast_path(tcx, trait_ref.upcast(tcx), key.typing_env.param_env) {
return Ok(&*tcx.arena.alloc(ImplSource::Builtin(
ty::solve::BuiltinImplSource::Trivial,
Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_traits/src/evaluate_obligation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/where-clauses/ignore-err-clauses.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
29 changes: 23 additions & 6 deletions tests/ui/where-clauses/ignore-err-clauses.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading