Skip to content

Commit aeb7743

Browse files
committed
Auto merge of #124303 - compiler-errors:fulfill-slowdown, r=<try>
[perf] Make fulfill in method probe less bad r? `@lcnr`
2 parents 7bb4f08 + b4427cd commit aeb7743

File tree

8 files changed

+170
-78
lines changed

8 files changed

+170
-78
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 141 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
1515
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
1616
use rustc_infer::infer::DefineOpaqueTypes;
1717
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
18+
use rustc_infer::traits::EvaluationResult;
1819
use rustc_middle::middle::stability;
1920
use rustc_middle::query::Providers;
2021
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
@@ -37,6 +38,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
3738
CandidateStep, MethodAutoderefStepsResult,
3839
};
3940
use rustc_trait_selection::traits::query::CanonicalTyGoal;
41+
use rustc_trait_selection::traits::NormalizeExt;
4042
use rustc_trait_selection::traits::ObligationCtxt;
4143
use rustc_trait_selection::traits::{self, ObligationCause};
4244
use std::cell::RefCell;
@@ -1375,7 +1377,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13751377
let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args);
13761378
(xform_self_ty, xform_ret_ty) =
13771379
self.xform_self_ty(probe.item, impl_ty, impl_args);
1378-
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1380+
let InferOk { value: normalized, mut obligations } =
1381+
self.at(cause, self.param_env).normalize(xform_self_ty);
1382+
xform_self_ty = normalized;
13791383
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
13801384
match self.at(cause, self.param_env).sup(
13811385
DefineOpaqueTypes::No,
@@ -1397,8 +1401,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13971401
let impl_bounds =
13981402
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
13991403
let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds);
1400-
// Convert the bounds into obligations.
1401-
ocx.register_obligations(traits::predicates_for_generics(
1404+
obligations.extend(traits::predicates_for_generics(
14021405
|idx, span| {
14031406
let code = if span.is_dummy() {
14041407
traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
@@ -1415,6 +1418,32 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14151418
self.param_env,
14161419
impl_bounds,
14171420
));
1421+
1422+
for obligation in obligations {
1423+
if self.infcx.next_trait_solver() {
1424+
ocx.register_obligation(obligation);
1425+
} else {
1426+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1427+
EvaluationResult::EvaluatedToOk => {
1428+
// No side-effects, no need to register obligations.
1429+
}
1430+
EvaluationResult::EvaluatedToOkModuloRegions
1431+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1432+
| EvaluationResult::EvaluatedToAmbig
1433+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1434+
ocx.register_obligation(obligation);
1435+
}
1436+
EvaluationResult::EvaluatedToErr => {
1437+
result = ProbeResult::NoMatch;
1438+
possibly_unsatisfied_predicates.push((
1439+
self.resolve_vars_if_possible(obligation.predicate),
1440+
None,
1441+
Some(obligation.cause.clone()),
1442+
));
1443+
}
1444+
}
1445+
}
1446+
}
14181447
}
14191448
TraitCandidate(poly_trait_ref) => {
14201449
// Some trait methods are excluded for arrays before 2021.
@@ -1436,7 +1465,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14361465
let trait_ref = ocx.normalize(cause, self.param_env, trait_ref);
14371466
(xform_self_ty, xform_ret_ty) =
14381467
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
1439-
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1468+
1469+
let InferOk { value: normalized, obligations: normalize_obligations } =
1470+
self.at(cause, self.param_env).normalize(xform_self_ty);
1471+
xform_self_ty = normalized;
1472+
14401473
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
14411474
match self.at(cause, self.param_env).sup(
14421475
DefineOpaqueTypes::No,
@@ -1451,28 +1484,70 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14511484
return ProbeResult::NoMatch;
14521485
}
14531486
}
1487+
1488+
for obligation in normalize_obligations {
1489+
if self.infcx.next_trait_solver() {
1490+
ocx.register_obligation(obligation);
1491+
} else {
1492+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1493+
EvaluationResult::EvaluatedToOk => {
1494+
// No side-effects, no need to register obligations.
1495+
}
1496+
EvaluationResult::EvaluatedToOkModuloRegions
1497+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1498+
| EvaluationResult::EvaluatedToAmbig
1499+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1500+
ocx.register_obligation(obligation);
1501+
}
1502+
EvaluationResult::EvaluatedToErr => {
1503+
result = ProbeResult::NoMatch;
1504+
possibly_unsatisfied_predicates.push((
1505+
self.resolve_vars_if_possible(obligation.predicate),
1506+
None,
1507+
Some(obligation.cause.clone()),
1508+
));
1509+
}
1510+
}
1511+
}
1512+
}
1513+
14541514
let obligation = traits::Obligation::new(
14551515
self.tcx,
14561516
cause.clone(),
14571517
self.param_env,
14581518
ty::Binder::dummy(trait_ref),
14591519
);
14601520

1461-
// FIXME(-Znext-solver): We only need this hack to deal with fatal
1462-
// overflow in the old solver.
1463-
if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation)
1464-
{
1521+
if self.infcx.next_trait_solver() {
14651522
ocx.register_obligation(obligation);
14661523
} else {
1467-
result = ProbeResult::NoMatch;
1468-
if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref) {
1469-
for nested_obligation in candidate.nested_obligations() {
1470-
if !self.infcx.predicate_may_hold(&nested_obligation) {
1471-
possibly_unsatisfied_predicates.push((
1472-
self.resolve_vars_if_possible(nested_obligation.predicate),
1473-
Some(self.resolve_vars_if_possible(obligation.predicate)),
1474-
Some(nested_obligation.cause),
1475-
));
1524+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1525+
EvaluationResult::EvaluatedToOk => {
1526+
// No side-effects, no need to register obligations.
1527+
}
1528+
EvaluationResult::EvaluatedToOkModuloRegions
1529+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1530+
| EvaluationResult::EvaluatedToAmbig
1531+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1532+
ocx.register_obligation(obligation);
1533+
}
1534+
EvaluationResult::EvaluatedToErr => {
1535+
result = ProbeResult::NoMatch;
1536+
if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref)
1537+
{
1538+
for nested_obligation in candidate.nested_obligations() {
1539+
if !self.infcx.predicate_may_hold(&nested_obligation) {
1540+
possibly_unsatisfied_predicates.push((
1541+
self.resolve_vars_if_possible(
1542+
nested_obligation.predicate,
1543+
),
1544+
Some(self.resolve_vars_if_possible(
1545+
obligation.predicate,
1546+
)),
1547+
Some(nested_obligation.cause),
1548+
));
1549+
}
1550+
}
14761551
}
14771552
}
14781553
}
@@ -1488,7 +1563,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14881563
);
14891564
(xform_self_ty, xform_ret_ty) =
14901565
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
1491-
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1566+
let InferOk { value: normalized, obligations: normalize_obligations } =
1567+
self.at(cause, self.param_env).normalize(xform_self_ty);
1568+
xform_self_ty = normalized;
1569+
14921570
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
14931571
match self.at(cause, self.param_env).sup(
14941572
DefineOpaqueTypes::No,
@@ -1503,26 +1581,55 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15031581
return ProbeResult::NoMatch;
15041582
}
15051583
}
1584+
1585+
for obligation in normalize_obligations {
1586+
if self.infcx.next_trait_solver() {
1587+
ocx.register_obligation(obligation);
1588+
} else {
1589+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1590+
EvaluationResult::EvaluatedToOk => {
1591+
// No side-effects, no need to register obligations.
1592+
}
1593+
EvaluationResult::EvaluatedToOkModuloRegions
1594+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1595+
| EvaluationResult::EvaluatedToAmbig
1596+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1597+
ocx.register_obligation(obligation);
1598+
}
1599+
EvaluationResult::EvaluatedToErr => {
1600+
result = ProbeResult::NoMatch;
1601+
possibly_unsatisfied_predicates.push((
1602+
self.resolve_vars_if_possible(obligation.predicate),
1603+
None,
1604+
Some(obligation.cause.clone()),
1605+
));
1606+
}
1607+
}
1608+
}
1609+
}
15061610
}
15071611
}
15081612

15091613
// Evaluate those obligations to see if they might possibly hold.
1510-
for error in ocx.select_where_possible() {
1511-
result = ProbeResult::NoMatch;
1512-
let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate);
1513-
if let Some(trait_predicate) = trait_predicate
1514-
&& nested_predicate == self.resolve_vars_if_possible(trait_predicate)
1515-
{
1516-
// Don't report possibly unsatisfied predicates if the root
1517-
// trait obligation from a `TraitCandidate` is unsatisfied.
1518-
// That just means the candidate doesn't hold.
1519-
} else {
1520-
possibly_unsatisfied_predicates.push((
1521-
nested_predicate,
1522-
Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
1523-
.filter(|root_predicate| *root_predicate != nested_predicate),
1524-
Some(error.obligation.cause),
1525-
));
1614+
if let ProbeResult::Match = result {
1615+
for error in ocx.select_where_possible() {
1616+
result = ProbeResult::NoMatch;
1617+
let nested_predicate =
1618+
self.resolve_vars_if_possible(error.obligation.predicate);
1619+
if let Some(trait_predicate) = trait_predicate
1620+
&& nested_predicate == self.resolve_vars_if_possible(trait_predicate)
1621+
{
1622+
// Don't report possibly unsatisfied predicates if the root
1623+
// trait obligation from a `TraitCandidate` is unsatisfied.
1624+
// That just means the candidate doesn't hold.
1625+
} else {
1626+
possibly_unsatisfied_predicates.push((
1627+
nested_predicate,
1628+
Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
1629+
.filter(|root_predicate| *root_predicate != nested_predicate),
1630+
Some(error.obligation.cause),
1631+
));
1632+
}
15261633
}
15271634
}
15281635

tests/ui/impl-trait/issues/issue-84073.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0275]: overflow assigning `_` to `Option<_>`
2-
--> $DIR/issue-84073.rs:32:27
2+
--> $DIR/issue-84073.rs:32:22
33
|
44
LL | Race::new(|race| race.when());
5-
| ^^^^
5+
| ^^^^
66

77
error: aborting due to 1 previous error
88

tests/ui/missing-trait-bounds/issue-35677.fixed

Lines changed: 0 additions & 11 deletions
This file was deleted.

tests/ui/missing-trait-bounds/issue-35677.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//@ run-rustfix
21
#![allow(dead_code)]
32
use std::collections::HashSet;
43
use std::hash::Hash;

tests/ui/missing-trait-bounds/issue-35677.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0599]: the method `is_subset` exists for reference `&HashSet<T>`, but its trait bounds were not satisfied
2-
--> $DIR/issue-35677.rs:7:10
2+
--> $DIR/issue-35677.rs:6:10
33
|
44
LL | this.is_subset(other)
55
| ^^^^^^^^^ method cannot be called on `&HashSet<T>` due to unsatisfied trait bounds

tests/ui/suggestions/derive-trait-for-method-call.stderr

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,30 +74,22 @@ LL | struct Struct {
7474
error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
7575
--> $DIR/derive-trait-for-method-call.rs:40:15
7676
|
77-
LL | enum Enum {
78-
| --------- doesn't satisfy `Enum: Clone`
79-
...
8077
LL | struct Foo<X, Y> (X, Y);
8178
| ---------------- method `test` not found for this struct
8279
...
8380
LL | let y = x.test();
8481
| ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
8582
|
86-
note: trait bound `Instant: Default` was not satisfied
87-
--> $DIR/derive-trait-for-method-call.rs:20:40
83+
note: the following trait bounds were not satisfied:
84+
`Instant: Default`
85+
`Vec<Enum>: Clone`
86+
--> $DIR/derive-trait-for-method-call.rs:20:9
8887
|
8988
LL | impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
90-
| ^^^^^^^ ---------
91-
| |
92-
| unsatisfied trait bound introduced here
93-
= note: the following trait bounds were not satisfied:
94-
`Enum: Clone`
95-
which is required by `Vec<Enum>: Clone`
96-
help: consider annotating `Enum` with `#[derive(Clone)]`
97-
|
98-
LL + #[derive(Clone)]
99-
LL | enum Enum {
100-
|
89+
| ^^^^^ ^^^^^^^ ---------
90+
| | |
91+
| | unsatisfied trait bound introduced here
92+
| unsatisfied trait bound introduced here
10193

10294
error: aborting due to 3 previous errors
10395

tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ LL | struct Foo<I>(I);
77
LL | Foo::<()>::f()
88
| ^ function or associated item cannot be called on `Foo<()>` due to unsatisfied trait bounds
99
|
10-
note: trait bound `(): Iterator` was not satisfied
11-
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:5:23
10+
note: trait bound `(): IteratorAlias` was not satisfied
11+
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
1212
|
13-
LL | trait IteratorAlias = Iterator;
14-
| ------------- ^^^^^^^^ unsatisfied trait bound introduced here
13+
LL | impl<I: IteratorAlias> Foo<I> {
14+
| ^^^^^^^^^^^^^ ------
15+
| |
16+
| unsatisfied trait bound introduced here
1517

1618
error: aborting due to 1 previous error
1719

tests/ui/traits/track-obligations.stderr

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,26 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b
44
LL | struct ALayer<C>(C);
55
| ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
66
...
7-
LL | struct AService;
8-
| --------------- doesn't satisfy `<AService as Service<Req>>::Response = Res`
9-
...
107
LL | struct Client<C>(C);
118
| ---------------- method `check` not found for this struct
129
...
1310
LL | Client(()).check();
1411
| ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
1512
|
16-
note: trait bound `<AService as Service<Req>>::Response = Res` was not satisfied
17-
--> $DIR/track-obligations.rs:24:21
13+
note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
14+
--> $DIR/track-obligations.rs:71:16
1815
|
19-
LL | impl<T> ParticularService for T
20-
| ----------------- -
16+
LL | impl<C> Client<C>
17+
| ---------
2118
LL | where
22-
LL | T: Service<Req, Response = Res>,
23-
| ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
19+
LL | ALayer<C>: ParticularServiceLayer<C>,
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
21+
note: the trait `ParticularServiceLayer` must be implemented
22+
--> $DIR/track-obligations.rs:34:1
23+
|
24+
LL | / pub trait ParticularServiceLayer<C>:
25+
LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
26+
| |____________________________________________________________________^
2427

2528
error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
2629
--> $DIR/track-obligations.rs:87:11

0 commit comments

Comments
 (0)