Skip to content

Commit 0026d96

Browse files
committed
Revert "stop special-casing 'static in evaluate"
This reverts commit 73c79cd.
1 parent 516a6d3 commit 0026d96

File tree

7 files changed

+102
-151
lines changed

7 files changed

+102
-151
lines changed

compiler/rustc_infer/src/infer/freshen.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,18 @@ pub struct TypeFreshener<'a, 'tcx> {
4343
const_freshen_count: u32,
4444
ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
4545
const_freshen_map: FxHashMap<ty::InferConst<'tcx>, ty::Const<'tcx>>,
46+
keep_static: bool,
4647
}
4748

4849
impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
49-
pub fn new(infcx: &'a InferCtxt<'tcx>) -> TypeFreshener<'a, 'tcx> {
50+
pub fn new(infcx: &'a InferCtxt<'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> {
5051
TypeFreshener {
5152
infcx,
5253
ty_freshen_count: 0,
5354
const_freshen_count: 0,
5455
ty_freshen_map: Default::default(),
5556
const_freshen_map: Default::default(),
57+
keep_static,
5658
}
5759
}
5860

@@ -119,9 +121,18 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
119121
| ty::ReFree(_)
120122
| ty::ReVar(_)
121123
| ty::RePlaceholder(..)
122-
| ty::ReStatic
123124
| ty::ReError(_)
124-
| ty::ReErased => self.interner().lifetimes.re_erased,
125+
| ty::ReErased => {
126+
// replace all free regions with 'erased
127+
self.interner().lifetimes.re_erased
128+
}
129+
ty::ReStatic => {
130+
if self.keep_static {
131+
r
132+
} else {
133+
self.interner().lifetimes.re_erased
134+
}
135+
}
125136
}
126137
}
127138

compiler/rustc_infer/src/infer/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,12 @@ impl<'tcx> InferCtxt<'tcx> {
713713
}
714714

715715
pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
716-
freshen::TypeFreshener::new(self)
716+
freshen::TypeFreshener::new(self, false)
717+
}
718+
719+
/// Like `freshener`, but does not replace `'static` regions.
720+
pub fn freshener_keep_static<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
721+
freshen::TypeFreshener::new(self, true)
717722
}
718723

719724
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {

compiler/rustc_trait_selection/src/traits/select/mod.rs

+78-86
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
210210
pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
211211
SelectionContext {
212212
infcx,
213-
freshener: infcx.freshener(),
213+
freshener: infcx.freshener_keep_static(),
214214
intercrate_ambiguity_causes: None,
215215
query_mode: TraitQueryMode::Standard,
216216
}
@@ -769,16 +769,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
769769
}
770770

771771
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(pred)) => {
772-
// A global type with no free lifetimes or generic parameters
773-
// outlives anything.
774-
if pred.0.has_free_regions()
775-
|| pred.0.has_late_bound_regions()
776-
|| pred.0.has_non_region_infer()
777-
|| pred.0.has_non_region_infer()
778-
{
779-
Ok(EvaluatedToOkModuloRegions)
780-
} else {
772+
// A global type with no late-bound regions can only
773+
// contain the "'static" lifetime (any other lifetime
774+
// would either be late-bound or local), so it is guaranteed
775+
// to outlive any other lifetime
776+
if pred.0.is_global() && !pred.0.has_late_bound_vars() {
781777
Ok(EvaluatedToOk)
778+
} else {
779+
Ok(EvaluatedToOkModuloRegions)
782780
}
783781
}
784782

@@ -1826,12 +1824,6 @@ enum DropVictim {
18261824
No,
18271825
}
18281826

1829-
impl DropVictim {
1830-
fn drop_if(should_drop: bool) -> DropVictim {
1831-
if should_drop { DropVictim::Yes } else { DropVictim::No }
1832-
}
1833-
}
1834-
18351827
/// ## Winnowing
18361828
///
18371829
/// Winnowing is the process of attempting to resolve ambiguity by
@@ -1897,7 +1889,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18971889
// or the current one if tied (they should both evaluate to the same answer). This is
18981890
// probably best characterized as a "hack", since we might prefer to just do our
18991891
// best to *not* create essentially duplicate candidates in the first place.
1900-
DropVictim::drop_if(other.bound_vars().len() <= victim.bound_vars().len())
1892+
if other.bound_vars().len() <= victim.bound_vars().len() {
1893+
DropVictim::Yes
1894+
} else {
1895+
DropVictim::No
1896+
}
19011897
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
19021898
&& victim.skip_binder().constness == ty::BoundConstness::NotConst
19031899
&& other.skip_binder().polarity == victim.skip_binder().polarity
@@ -1927,13 +1923,17 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19271923
| ObjectCandidate(_)
19281924
| ProjectionCandidate(..),
19291925
) => {
1930-
// We have a where clause so don't go around looking
1931-
// for impls. Arbitrarily give param candidates priority
1932-
// over projection and object candidates.
1933-
//
1934-
// Global bounds from the where clause should be ignored
1935-
// here (see issue #50825).
1936-
DropVictim::drop_if(!is_global(other_cand))
1926+
if is_global(other_cand) {
1927+
DropVictim::No
1928+
} else {
1929+
// We have a where clause so don't go around looking
1930+
// for impls. Arbitrarily give param candidates priority
1931+
// over projection and object candidates.
1932+
//
1933+
// Global bounds from the where clause should be ignored
1934+
// here (see issue #50825).
1935+
DropVictim::Yes
1936+
}
19371937
}
19381938
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
19391939
// Prefer these to a global where-clause bound
@@ -1955,16 +1955,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19551955
) => {
19561956
// Prefer these to a global where-clause bound
19571957
// (see issue #50825).
1958-
DropVictim::drop_if(
1959-
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(),
1960-
)
1958+
if is_global(victim_cand) && other.evaluation.must_apply_modulo_regions() {
1959+
DropVictim::Yes
1960+
} else {
1961+
DropVictim::No
1962+
}
19611963
}
19621964

19631965
(ProjectionCandidate(i, _), ProjectionCandidate(j, _))
19641966
| (ObjectCandidate(i), ObjectCandidate(j)) => {
19651967
// Arbitrarily pick the lower numbered candidate for backwards
19661968
// compatibility reasons. Don't let this affect inference.
1967-
DropVictim::drop_if(i < j && !needs_infer)
1969+
if i < j && !needs_infer { DropVictim::Yes } else { DropVictim::No }
19681970
}
19691971
(ObjectCandidate(_), ProjectionCandidate(..))
19701972
| (ProjectionCandidate(..), ObjectCandidate(_)) => {
@@ -2015,65 +2017,55 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
20152017
}
20162018
}
20172019

2018-
match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
2019-
// For #33140 the impl headers must be exactly equal, the trait must not have
2020-
// any associated items and there are no where-clauses.
2021-
//
2022-
// We can just arbitrarily drop one of the impls.
2023-
Some(ty::ImplOverlapKind::Issue33140) => {
2024-
assert_eq!(other.evaluation, victim.evaluation);
2025-
DropVictim::Yes
2026-
}
2027-
// For candidates which already reference errors it doesn't really
2028-
// matter what we do 🤷
2029-
Some(ty::ImplOverlapKind::Permitted { marker: false }) => {
2030-
DropVictim::drop_if(other.evaluation.must_apply_considering_regions())
2031-
}
2032-
Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
2033-
// Subtle: If the predicate we are evaluating has inference
2034-
// variables, do *not* allow discarding candidates due to
2035-
// marker trait impls.
2036-
//
2037-
// Without this restriction, we could end up accidentally
2038-
// constraining inference variables based on an arbitrarily
2039-
// chosen trait impl.
2040-
//
2041-
// Imagine we have the following code:
2042-
//
2043-
// ```rust
2044-
// #[marker] trait MyTrait {}
2045-
// impl MyTrait for u8 {}
2046-
// impl MyTrait for bool {}
2047-
// ```
2048-
//
2049-
// And we are evaluating the predicate `<_#0t as MyTrait>`.
2050-
//
2051-
// During selection, we will end up with one candidate for each
2052-
// impl of `MyTrait`. If we were to discard one impl in favor
2053-
// of the other, we would be left with one candidate, causing
2054-
// us to "successfully" select the predicate, unifying
2055-
// _#0t with (for example) `u8`.
2056-
//
2057-
// However, we have no reason to believe that this unification
2058-
// is correct - we've essentially just picked an arbitrary
2059-
// *possibility* for _#0t, and required that this be the *only*
2060-
// possibility.
2061-
//
2062-
// Eventually, we will either:
2063-
// 1) Unify all inference variables in the predicate through
2064-
// some other means (e.g. type-checking of a function). We will
2065-
// then be in a position to drop marker trait candidates
2066-
// without constraining inference variables (since there are
2067-
// none left to constrain)
2068-
// 2) Be left with some unconstrained inference variables. We
2069-
// will then correctly report an inference error, since the
2070-
// existence of multiple marker trait impls tells us nothing
2071-
// about which one should actually apply.
2072-
DropVictim::drop_if(
2073-
!needs_infer && other.evaluation.must_apply_considering_regions(),
2074-
)
2020+
if other.evaluation.must_apply_considering_regions() {
2021+
match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
2022+
Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
2023+
// Subtle: If the predicate we are evaluating has inference
2024+
// variables, do *not* allow discarding candidates due to
2025+
// marker trait impls.
2026+
//
2027+
// Without this restriction, we could end up accidentally
2028+
// constraining inference variables based on an arbitrarily
2029+
// chosen trait impl.
2030+
//
2031+
// Imagine we have the following code:
2032+
//
2033+
// ```rust
2034+
// #[marker] trait MyTrait {}
2035+
// impl MyTrait for u8 {}
2036+
// impl MyTrait for bool {}
2037+
// ```
2038+
//
2039+
// And we are evaluating the predicate `<_#0t as MyTrait>`.
2040+
//
2041+
// During selection, we will end up with one candidate for each
2042+
// impl of `MyTrait`. If we were to discard one impl in favor
2043+
// of the other, we would be left with one candidate, causing
2044+
// us to "successfully" select the predicate, unifying
2045+
// _#0t with (for example) `u8`.
2046+
//
2047+
// However, we have no reason to believe that this unification
2048+
// is correct - we've essentially just picked an arbitrary
2049+
// *possibility* for _#0t, and required that this be the *only*
2050+
// possibility.
2051+
//
2052+
// Eventually, we will either:
2053+
// 1) Unify all inference variables in the predicate through
2054+
// some other means (e.g. type-checking of a function). We will
2055+
// then be in a position to drop marker trait candidates
2056+
// without constraining inference variables (since there are
2057+
// none left to constrain)
2058+
// 2) Be left with some unconstrained inference variables. We
2059+
// will then correctly report an inference error, since the
2060+
// existence of multiple marker trait impls tells us nothing
2061+
// about which one should actually apply.
2062+
if needs_infer { DropVictim::No } else { DropVictim::Yes }
2063+
}
2064+
Some(_) => DropVictim::Yes,
2065+
None => DropVictim::No,
20752066
}
2076-
None => DropVictim::No,
2067+
} else {
2068+
DropVictim::No
20772069
}
20782070
}
20792071

tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
// known-bug: #89515
2-
//
3-
// The trait solver cannot deal with ambiguous marker trait impls
4-
// if there are lifetimes involved. As we must not special-case any
5-
// regions this does not work, even with 'static
1+
// check-pass
62
#![feature(marker_trait_attr)]
73

84
#[marker]

tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.stderr

-31
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
1-
// known-bug: #109481
2-
//
3-
// While the `T: Copy` is always applicable when checking
4-
// that the impl `impl<T: Copy> F for T {}` is well formed,
5-
// the old trait solver can only approximate this by checking
6-
// that there are no inference variables in the obligation and
7-
// no region constraints in the evaluation result.
8-
//
9-
// Because of this we end up with ambiguity here.
1+
// check-pass
102
#![feature(marker_trait_attr)]
113

124
#[marker]
135
pub trait F {}
14-
impl<T: Copy> F for T {}
15-
impl<T: 'static> F for T {}
6+
impl<T> F for T where T: Copy {}
7+
impl<T> F for T where T: 'static {}
168

179
fn main() {}

tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr

-14
This file was deleted.

0 commit comments

Comments
 (0)