@@ -434,87 +434,11 @@ attached to the `ParameterEnvironment` and the global cache attached
434
434
to the `tcx`. We use the local cache whenever the result might depend
435
435
on the where clauses that are in scope. The determination of which
436
436
cache to use is done by the method `pick_candidate_cache` in
437
- `select.rs`.
438
-
439
- There are two cases where we currently use the local cache. The
440
- current rules are probably more conservative than necessary.
441
-
442
- ### Trait references that involve parameter types
443
-
444
- The most obvious case where you need the local environment is
445
- when the trait reference includes parameter types. For example,
446
- consider the following function:
447
-
448
- impl<T> Vec<T> {
449
- fn foo(x: T)
450
- where T : Foo
451
- { ... }
452
-
453
- fn bar(x: T)
454
- { ... }
455
- }
456
-
457
- If there is an obligation `T : Foo`, or `int : Bar<T>`, or whatever,
458
- clearly the results from `foo` and `bar` are potentially different,
459
- since the set of where clauses in scope are different.
460
-
461
- ### Trait references with unbound variables when where clauses are in scope
462
-
463
- There is another less obvious interaction which involves unbound variables
464
- where *only* where clauses are in scope (no impls). This manifested as
465
- issue #18209 (`run-pass/trait-cache-issue-18209.rs`). Consider
466
- this snippet:
467
-
468
- ```
469
- pub trait Foo {
470
- fn load_from() -> Box<Self>;
471
- fn load() -> Box<Self> {
472
- Foo::load_from()
473
- }
474
- }
475
- ```
476
-
477
- The default method will incur an obligation `$0 : Foo` from the call
478
- to `load_from`. If there are no impls, this can be eagerly resolved to
479
- `VtableParam(Self : Foo)` and cached. Because the trait reference
480
- doesn't involve any parameters types (only the resolution does), this
481
- result was stored in the global cache, causing later calls to
482
- `Foo::load_from()` to get nonsense.
483
-
484
- To fix this, we always use the local cache if there are unbound
485
- variables and where clauses in scope. This is more conservative than
486
- necessary as far as I can tell. However, it still seems to be a simple
487
- rule and I observe ~99% hit rate on rustc, so it doesn't seem to hurt
488
- us in particular.
489
-
490
- Here is an example of the kind of subtle case that I would be worried
491
- about with a more complex rule (although this particular case works
492
- out ok). Imagine the trait reference doesn't directly reference a
493
- where clause, but the where clause plays a role in the winnowing
494
- phase. Something like this:
495
-
496
- ```
497
- pub trait Foo<T> { ... }
498
- pub trait Bar { ... }
499
- impl<U,T:Bar> Foo<U> for T { ... } // Impl A
500
- impl Foo<char> for uint { ... } // Impl B
501
- ```
502
-
503
- Now, in some function, we have no where clauses in scope, and we have
504
- an obligation `$1 : Foo<$0>`. We might then conclude that `$0=char`
505
- and `$1=uint`: this is because for impl A to apply, `uint:Bar` would
506
- have to hold, and we know it does not or else the coherence check
507
- would have failed. So we might enter into our global cache: `$1 :
508
- Foo<$0> => Impl B`. Then we come along in a different scope, where a
509
- generic type `A` is around with the bound `A:Bar`. Now suddenly the
510
- impl is viable.
511
-
512
- The flaw in this imaginary DOOMSDAY SCENARIO is that we would not
513
- currently conclude that `$1 : Foo<$0>` implies that `$0 == uint` and
514
- `$1 == char`, even though it is true that (absent type parameters)
515
- there is no other type the user could enter. However, it is not
516
- *completely* implausible that we *could* draw this conclusion in the
517
- future; we wouldn't have to guess types, in particular, we could be
518
- led by the impls.
437
+ `select.rs`. At the moment, we use a very simple, conservative rule:
438
+ if there are any where-clauses in scope, then we use the local cache.
439
+ We used to try and draw finer-grained distinctions, but that led to a
440
+ serious of annoying and weird bugs like #22019 and #18290. This simple
441
+ rule seems to be pretty clearly safe and also still retains a very
442
+ high hit rate (~95% when compiling rustc).
519
443
520
444
*/
0 commit comments