Skip to content

Commit 27c2465

Browse files
committed
Auto merge of #144064 - davidtwco:prefer-alias-over-env-for-sizedness, r=lcnr
prefer alias candidates for sizedness + auto trait goals Fixes #143992 - abd07de: Reverts #144016 so that `MetaSized` bounds are checked properly, and updates all the tests accordingly, including making `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs` fail when it shouldn't - 90e61db: Prefer alias candidates over parameter environment candidates for sizedness, auto and default traits. `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs` passes again, but `tests/ui/generic-associated-types/issue-93262.rs` starts failing when it shouldn't - e412062: No longer require that predicates of aliases hold in well-formedness checking of the alias. `tests/ui/generic-associated-types/issue-93262.rs` passes again Each commit updates all the tests to their new output so it should be easy enough to see what the impact of each change individually is. After all of the changes, tests that pass when they didn't before or vice versa: - `tests/ui/extern/extern-types-size_of_val.rs` - Previously passing, but only because of #144016, now correctly errors - `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs` - Previously failing on next solver, only because #144016 only applied to the old solver, passing now with 90e61db - `tests/ui/sized-hierarchy/overflow.rs` - Previously passing, but only because of #144016, now correctly errors - `tests/ui/generic-associated-types/issue-92096.rs` - Previously passing, due to e412062 - Fails to prove `C::Connecting<'placeholder>: Send` which is required when proving that the generator is `Send`. This is an instance of #110338. - `tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs` - Previously passing, now failing in the next solver, due to 03e0fda - Expected that this test now fails as ambigious, see [Zulip](https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/sizedness.20bounds.20in.20explicit_implied_predicates_of.20.28.23142712.29/near/526987384) This had a crater run in #142712 (comment) alongside some other changes. r? `@lcnr` cc #142712 (this extracts part of that change)
2 parents 235a4c0 + 8287fb0 commit 27c2465

File tree

53 files changed

+557
-303
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+557
-303
lines changed

compiler/rustc_middle/src/traits/select.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed;
66
use rustc_hir::def_id::DefId;
77
use rustc_macros::{HashStable, TypeVisitable};
88
use rustc_query_system::cache::Cache;
9+
use rustc_type_ir::solve::AliasBoundKind;
910

1011
use self::EvaluationResult::*;
1112
use super::{SelectionError, SelectionResult};
@@ -116,8 +117,13 @@ pub enum SelectionCandidate<'tcx> {
116117

117118
/// This is a trait matching with a projected type as `Self`, and we found
118119
/// an applicable bound in the trait definition. The `usize` is an index
119-
/// into the list returned by `tcx.item_bounds`.
120-
ProjectionCandidate(usize),
120+
/// into the list returned by `tcx.item_bounds` and the `AliasBoundKind`
121+
/// is whether this is candidate from recursion on the self type of a
122+
/// projection.
123+
ProjectionCandidate {
124+
idx: usize,
125+
kind: AliasBoundKind,
126+
},
121127

122128
/// Implementation of a `Fn`-family trait by one of the anonymous types
123129
/// generated for an `||` expression.

compiler/rustc_middle/src/ty/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
521521
self.is_default_trait(def_id)
522522
}
523523

524+
fn is_sizedness_trait(self, def_id: DefId) -> bool {
525+
self.is_sizedness_trait(def_id)
526+
}
527+
524528
fn as_lang_item(self, def_id: DefId) -> Option<SolverLangItem> {
525529
lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?)
526530
}
@@ -1787,6 +1791,10 @@ impl<'tcx> TyCtxt<'tcx> {
17871791
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
17881792
}
17891793

1794+
pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
1795+
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
1796+
}
1797+
17901798
/// Returns a range of the start/end indices specified with the
17911799
/// `rustc_layout_scalar_valid_range` attribute.
17921800
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
5959
)]
6060
use rustc_type_ir::inherent;
6161
pub use rustc_type_ir::relate::VarianceDiagInfo;
62-
pub use rustc_type_ir::solve::SizedTraitKind;
62+
pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind};
6363
pub use rustc_type_ir::*;
6464
#[allow(hidden_glob_reexports, unused_imports)]
6565
use rustc_type_ir::{InferCtxtLike, Interner};

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use derive_where::derive_where;
99
use rustc_type_ir::inherent::*;
1010
use rustc_type_ir::lang_items::SolverTraitLangItem;
1111
use rustc_type_ir::search_graph::CandidateHeadUsages;
12-
use rustc_type_ir::solve::SizedTraitKind;
12+
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
1313
use rustc_type_ir::{
1414
self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
1515
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
@@ -27,11 +27,6 @@ use crate::solve::{
2727
has_no_inference_or_external_constraints,
2828
};
2929

30-
enum AliasBoundKind {
31-
SelfBounds,
32-
NonSelfBounds,
33-
}
34-
3530
/// A candidate is a possible way to prove a goal.
3631
///
3732
/// It consists of both the `source`, which describes how that goal would be proven,
@@ -451,7 +446,7 @@ where
451446
matches!(
452447
c.source,
453448
CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)
454-
| CandidateSource::AliasBound
449+
| CandidateSource::AliasBound(_)
455450
) && has_no_inference_or_external_constraints(c.result)
456451
})
457452
{
@@ -711,7 +706,7 @@ where
711706
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
712707
{
713708
candidates.push(Candidate {
714-
source: CandidateSource::AliasBound,
709+
source: CandidateSource::AliasBound(consider_self_bounds),
715710
result,
716711
head_usages: CandidateHeadUsages::default(),
717712
});
@@ -735,7 +730,7 @@ where
735730
{
736731
candidates.extend(G::probe_and_consider_implied_clause(
737732
self,
738-
CandidateSource::AliasBound,
733+
CandidateSource::AliasBound(consider_self_bounds),
739734
goal,
740735
assumption,
741736
[],
@@ -750,7 +745,7 @@ where
750745
{
751746
candidates.extend(G::probe_and_consider_implied_clause(
752747
self,
753-
CandidateSource::AliasBound,
748+
CandidateSource::AliasBound(consider_self_bounds),
754749
goal,
755750
assumption,
756751
[],
@@ -1030,7 +1025,7 @@ where
10301025
item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty });
10311026
candidates.extend(G::probe_and_match_goal_against_assumption(
10321027
self,
1033-
CandidateSource::AliasBound,
1028+
CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
10341029
goal,
10351030
assumption,
10361031
|ecx| {

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
use rustc_type_ir::fast_reject::DeepRejectCtxt;
55
use rustc_type_ir::inherent::*;
66
use rustc_type_ir::lang_items::SolverTraitLangItem;
7-
use rustc_type_ir::solve::SizedTraitKind;
87
use rustc_type_ir::solve::inspect::ProbeKind;
8+
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
99
use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate};
1010
use tracing::instrument;
1111

@@ -96,7 +96,7 @@ where
9696
) {
9797
candidates.extend(Self::probe_and_match_goal_against_assumption(
9898
ecx,
99-
CandidateSource::AliasBound,
99+
CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
100100
goal,
101101
clause,
102102
|ecx| {

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use rustc_type_ir::data_structures::IndexSet;
44
use rustc_type_ir::fast_reject::DeepRejectCtxt;
55
use rustc_type_ir::inherent::*;
66
use rustc_type_ir::lang_items::SolverTraitLangItem;
7-
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
7+
use rustc_type_ir::solve::{
8+
AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, SizedTraitKind,
9+
};
810
use rustc_type_ir::{
911
self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef,
1012
TypeVisitableExt as _, TypingMode, Upcast as _, elaborate,
@@ -1355,6 +1357,7 @@ where
13551357
#[instrument(level = "debug", skip(self), ret)]
13561358
pub(super) fn merge_trait_candidates(
13571359
&mut self,
1360+
candidate_preference_mode: CandidatePreferenceMode,
13581361
mut candidates: Vec<Candidate<I>>,
13591362
failed_candidate_info: FailedCandidateInfo,
13601363
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
@@ -1380,6 +1383,23 @@ where
13801383
return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
13811384
}
13821385

1386+
// Extract non-nested alias bound candidates, will be preferred over where bounds if
1387+
// we're proving an auto-trait, sizedness trait or default trait.
1388+
if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1389+
&& candidates.iter().any(|c| {
1390+
matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1391+
})
1392+
{
1393+
let alias_bounds: Vec<_> = candidates
1394+
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1395+
.collect();
1396+
return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
1397+
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1398+
} else {
1399+
Ok((self.bail_with_ambiguity(&alias_bounds), None))
1400+
};
1401+
}
1402+
13831403
// If there are non-global where-bounds, prefer where-bounds
13841404
// (including global ones) over everything else.
13851405
let has_non_global_where_bounds = candidates
@@ -1427,9 +1447,10 @@ where
14271447
};
14281448
}
14291449

1430-
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) {
1450+
// Next, prefer any alias bound (nested or otherwise).
1451+
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
14311452
let alias_bounds: Vec<_> = candidates
1432-
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound))
1453+
.extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
14331454
.collect();
14341455
return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) {
14351456
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
@@ -1470,7 +1491,9 @@ where
14701491
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
14711492
let (candidates, failed_candidate_info) =
14721493
self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1473-
self.merge_trait_candidates(candidates, failed_candidate_info)
1494+
let candidate_preference_mode =
1495+
CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1496+
self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
14741497
}
14751498

14761499
fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {

compiler/rustc_trait_selection/src/solve/select.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>(
126126
// Prefer dyn candidates over non-dyn candidates. This is necessary to
127127
// handle the unsoundness between `impl<T: ?Sized> Any for T` and `dyn Any: Any`.
128128
(
129-
CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound,
129+
CandidateSource::Impl(_)
130+
| CandidateSource::ParamEnv(_)
131+
| CandidateSource::AliasBound(_),
130132
CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }),
131133
) => true,
132134

@@ -175,7 +177,9 @@ fn to_selection<'tcx>(
175177
})
176178
}
177179
CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested),
178-
CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested),
180+
CandidateSource::ParamEnv(_) | CandidateSource::AliasBound(_) => {
181+
ImplSource::Param(nested)
182+
}
179183
CandidateSource::CoherenceUnknowable => {
180184
span_bug!(span, "didn't expect to select an unknowable candidate")
181185
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
741741
let mut ambiguous = false;
742742
let _ = selcx.for_each_item_bound(
743743
obligation.predicate.self_ty(),
744-
|selcx, clause, _| {
744+
|selcx, clause, _, _| {
745745
let Some(clause) = clause.as_projection_clause() else {
746746
return ControlFlow::Continue(());
747747
};

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
208208
let mut distinct_normalized_bounds = FxHashSet::default();
209209
let _ = self.for_each_item_bound::<!>(
210210
placeholder_trait_predicate.self_ty(),
211-
|selcx, bound, idx| {
211+
|selcx, bound, idx, alias_bound_kind| {
212212
let Some(bound) = bound.as_trait_clause() else {
213213
return ControlFlow::Continue(());
214214
};
@@ -230,12 +230,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
230230
bound.map_bound(|pred| pred.trait_ref),
231231
) {
232232
Ok(None) => {
233-
candidates.vec.push(ProjectionCandidate(idx));
233+
candidates
234+
.vec
235+
.push(ProjectionCandidate { idx, kind: alias_bound_kind });
234236
}
235237
Ok(Some(normalized_trait))
236238
if distinct_normalized_bounds.insert(normalized_trait) =>
237239
{
238-
candidates.vec.push(ProjectionCandidate(idx));
240+
candidates
241+
.vec
242+
.push(ProjectionCandidate { idx, kind: alias_bound_kind });
239243
}
240244
_ => {}
241245
}
@@ -825,7 +829,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
825829
}
826830

827831
ty::Alias(ty::Opaque, alias) => {
828-
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
832+
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) {
829833
// We do not generate an auto impl candidate for `impl Trait`s which already
830834
// reference our auto trait.
831835
//

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

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
6767
ImplSource::Builtin(BuiltinImplSource::Misc, data)
6868
}
6969

70-
ProjectionCandidate(idx) => {
70+
ProjectionCandidate { idx, .. } => {
7171
let obligations = self.confirm_projection_candidate(obligation, idx)?;
7272
ImplSource::Param(obligations)
7373
}
@@ -144,15 +144,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
144144
obligation: &PolyTraitObligation<'tcx>,
145145
idx: usize,
146146
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
147-
let tcx = self.tcx();
148-
149147
let placeholder_trait_predicate =
150148
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
151149
let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty());
152150
let candidate_predicate = self
153151
.for_each_item_bound(
154152
placeholder_self_ty,
155-
|_, clause, clause_idx| {
153+
|_, clause, clause_idx, _| {
156154
if clause_idx == idx {
157155
ControlFlow::Break(clause)
158156
} else {
@@ -194,28 +192,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
194192
.map_err(|_| SelectionError::Unimplemented)?,
195193
);
196194

197-
// FIXME(compiler-errors): I don't think this is needed.
198-
if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() {
199-
let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args);
200-
for (predicate, _) in predicates {
201-
let normalized = normalize_with_depth_to(
202-
self,
203-
obligation.param_env,
204-
obligation.cause.clone(),
205-
obligation.recursion_depth + 1,
206-
predicate,
207-
&mut obligations,
208-
);
209-
obligations.push(Obligation::with_depth(
210-
self.tcx(),
211-
obligation.cause.clone(),
212-
obligation.recursion_depth + 1,
213-
obligation.param_env,
214-
normalized,
215-
));
216-
}
217-
}
218-
219195
Ok(obligations)
220196
}
221197

0 commit comments

Comments
 (0)