Skip to content

Commit 6b3da17

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 5557f8c + 3ffdd7f commit 6b3da17

File tree

8 files changed

+103
-76
lines changed

8 files changed

+103
-76
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 74 additions & 32 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};
@@ -1397,8 +1398,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13971398
let impl_bounds =
13981399
self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args);
13991400
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(
1401+
for obligation in traits::predicates_for_generics(
14021402
|idx, span| {
14031403
let code = if span.is_dummy() {
14041404
traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
@@ -1414,7 +1414,31 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14141414
},
14151415
self.param_env,
14161416
impl_bounds,
1417-
));
1417+
) {
1418+
if self.infcx.next_trait_solver() {
1419+
ocx.register_obligation(obligation);
1420+
} else {
1421+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1422+
EvaluationResult::EvaluatedToOk => {
1423+
// No side-effects, no need to register obligations.
1424+
}
1425+
EvaluationResult::EvaluatedToOkModuloRegions
1426+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1427+
| EvaluationResult::EvaluatedToAmbig
1428+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1429+
ocx.register_obligation(obligation);
1430+
}
1431+
EvaluationResult::EvaluatedToErr => {
1432+
result = ProbeResult::NoMatch;
1433+
possibly_unsatisfied_predicates.push((
1434+
self.resolve_vars_if_possible(obligation.predicate),
1435+
None,
1436+
Some(obligation.cause.clone()),
1437+
));
1438+
}
1439+
}
1440+
}
1441+
}
14181442
}
14191443
TraitCandidate(poly_trait_ref) => {
14201444
// Some trait methods are excluded for arrays before 2021.
@@ -1458,21 +1482,36 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14581482
ty::Binder::dummy(trait_ref),
14591483
);
14601484

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-
{
1485+
if self.infcx.next_trait_solver() {
14651486
ocx.register_obligation(obligation);
14661487
} 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-
));
1488+
match self.infcx.evaluate_obligation_no_overflow(&obligation) {
1489+
EvaluationResult::EvaluatedToOk => {
1490+
// No side-effects, no need to register obligations.
1491+
}
1492+
EvaluationResult::EvaluatedToOkModuloRegions
1493+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
1494+
| EvaluationResult::EvaluatedToAmbig
1495+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
1496+
ocx.register_obligation(obligation);
1497+
}
1498+
EvaluationResult::EvaluatedToErr => {
1499+
result = ProbeResult::NoMatch;
1500+
if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref)
1501+
{
1502+
for nested_obligation in candidate.nested_obligations() {
1503+
if !self.infcx.predicate_may_hold(&nested_obligation) {
1504+
possibly_unsatisfied_predicates.push((
1505+
self.resolve_vars_if_possible(
1506+
nested_obligation.predicate,
1507+
),
1508+
Some(self.resolve_vars_if_possible(
1509+
obligation.predicate,
1510+
)),
1511+
Some(nested_obligation.cause),
1512+
));
1513+
}
1514+
}
14761515
}
14771516
}
14781517
}
@@ -1507,22 +1546,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15071546
}
15081547

15091548
// 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-
));
1549+
if let ProbeResult::Match = result {
1550+
for error in ocx.select_where_possible() {
1551+
result = ProbeResult::NoMatch;
1552+
let nested_predicate =
1553+
self.resolve_vars_if_possible(error.obligation.predicate);
1554+
if let Some(trait_predicate) = trait_predicate
1555+
&& nested_predicate == self.resolve_vars_if_possible(trait_predicate)
1556+
{
1557+
// Don't report possibly unsatisfied predicates if the root
1558+
// trait obligation from a `TraitCandidate` is unsatisfied.
1559+
// That just means the candidate doesn't hold.
1560+
} else {
1561+
possibly_unsatisfied_predicates.push((
1562+
nested_predicate,
1563+
Some(self.resolve_vars_if_possible(error.root_obligation.predicate))
1564+
.filter(|root_predicate| *root_predicate != nested_predicate),
1565+
Some(error.obligation.cause),
1566+
));
1567+
}
15261568
}
15271569
}
15281570

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)