Skip to content

Commit eae6d99

Browse files
committed
upstream: rust-lang#144064
1 parent f8f6997 commit eae6d99

33 files changed

+402
-158
lines changed

compiler/rustc_middle/src/ty/context.rs

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

496+
fn is_sizedness_trait(self, def_id: DefId) -> bool {
497+
self.is_sizedness_trait(def_id)
498+
}
499+
496500
fn as_lang_item(self, def_id: DefId) -> Option<TraitSolverLangItem> {
497501
lang_item_to_trait_lang_item(self.lang_items().from_def_id(def_id)?)
498502
}
@@ -1652,6 +1656,10 @@ impl<'tcx> TyCtxt<'tcx> {
16521656
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
16531657
}
16541658

1659+
pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
1660+
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
1661+
}
1662+
16551663
/// Returns a range of the start/end indices specified with the
16561664
/// `rustc_layout_scalar_valid_range` attribute.
16571665
// 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/trait_goals.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ 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::TraitSolverLangItem;
7-
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
7+
use rustc_type_ir::solve::{CandidatePreferenceMode, CanonicalResponse, SizedTraitKind};
88
use rustc_type_ir::{
99
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
1010
Upcast as _, elaborate,
@@ -1343,6 +1343,7 @@ where
13431343
#[instrument(level = "debug", skip(self), ret)]
13441344
pub(super) fn merge_trait_candidates(
13451345
&mut self,
1346+
candidate_preference_mode: CandidatePreferenceMode,
13461347
mut candidates: Vec<Candidate<I>>,
13471348
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
13481349
if let TypingMode::Coherence = self.typing_mode() {
@@ -1368,6 +1369,26 @@ where
13681369
return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
13691370
}
13701371

1372+
let potential_alias_bound_response =
1373+
candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)).then(|| {
1374+
let alias_bounds: Vec<_> = candidates
1375+
.iter()
1376+
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
1377+
.map(|c| c.result)
1378+
.collect();
1379+
if let Some(response) = self.try_merge_responses(&alias_bounds) {
1380+
(response, Some(TraitGoalProvenVia::AliasBound))
1381+
} else {
1382+
(self.bail_with_ambiguity(&alias_bounds), None)
1383+
}
1384+
});
1385+
1386+
if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1387+
&& let Some(alias_bound_response) = potential_alias_bound_response
1388+
{
1389+
return Ok(alias_bound_response);
1390+
}
1391+
13711392
// If there are non-global where-bounds, prefer where-bounds
13721393
// (including global ones) over everything else.
13731394
let has_non_global_where_bounds = candidates
@@ -1386,17 +1407,8 @@ where
13861407
};
13871408
}
13881409

1389-
if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) {
1390-
let alias_bounds: Vec<_> = candidates
1391-
.iter()
1392-
.filter(|c| matches!(c.source, CandidateSource::AliasBound))
1393-
.map(|c| c.result)
1394-
.collect();
1395-
return if let Some(response) = self.try_merge_responses(&alias_bounds) {
1396-
Ok((response, Some(TraitGoalProvenVia::AliasBound)))
1397-
} else {
1398-
Ok((self.bail_with_ambiguity(&alias_bounds), None))
1399-
};
1410+
if let Some(response) = potential_alias_bound_response {
1411+
return Ok(response);
14001412
}
14011413

14021414
self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
@@ -1431,7 +1443,10 @@ where
14311443
goal: Goal<I, TraitPredicate<I>>,
14321444
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
14331445
let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1434-
self.merge_trait_candidates(candidates)
1446+
1447+
let candidate_preference_mode =
1448+
CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
1449+
self.merge_trait_candidates(candidate_preference_mode, candidates)
14351450
}
14361451

14371452
fn try_stall_coroutine_witness(

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

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,6 @@ 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());
@@ -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

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

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
2727
use rustc_middle::ty::error::TypeErrorToStringExt;
2828
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
2929
use rustc_middle::ty::{
30-
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
31-
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature,
30+
self, CandidatePreferenceMode, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate,
31+
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
32+
may_use_unstable_feature,
3233
};
3334
use rustc_span::{Symbol, sym};
3435
use tracing::{debug, instrument, trace};
@@ -473,7 +474,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
473474
}
474475
} else {
475476
let has_non_region_infer = stack.obligation.predicate.has_non_region_infer();
476-
if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) {
477+
let candidate_preference_mode =
478+
CandidatePreferenceMode::compute(self.tcx(), stack.obligation.predicate.def_id());
479+
if let Some(candidate) =
480+
self.winnow_candidates(has_non_region_infer, candidate_preference_mode, candidates)
481+
{
477482
self.filter_reservation_impls(candidate)
478483
} else {
479484
Ok(None)
@@ -1822,6 +1827,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18221827
fn winnow_candidates(
18231828
&mut self,
18241829
has_non_region_infer: bool,
1830+
candidate_preference_mode: CandidatePreferenceMode,
18251831
mut candidates: Vec<EvaluatedCandidate<'tcx>>,
18261832
) -> Option<SelectionCandidate<'tcx>> {
18271833
if candidates.len() == 1 {
@@ -1875,6 +1881,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18751881
break;
18761882
}
18771883

1884+
let alias_bound = candidates
1885+
.iter()
1886+
.filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None })
1887+
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
1888+
1889+
if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) {
1890+
match alias_bound {
1891+
Some(Some(index)) => return Some(ProjectionCandidate(index)),
1892+
Some(None) => {}
1893+
None => return None,
1894+
}
1895+
}
1896+
18781897
// The next highest priority is for non-global where-bounds. However, while we don't
18791898
// prefer global where-clauses here, we do bail with ambiguity when encountering both
18801899
// a global and a non-global where-clause.
@@ -1908,10 +1927,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19081927
// fairly arbitrary but once again necessary for backwards compatibility.
19091928
// If there are multiple applicable candidates which don't affect type inference,
19101929
// choose the one with the lowest index.
1911-
let alias_bound = candidates
1912-
.iter()
1913-
.filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None })
1914-
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
19151930
match alias_bound {
19161931
Some(Some(index)) => return Some(ProjectionCandidate(index)),
19171932
Some(None) => {}

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,6 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
379379
_ => return false,
380380
};
381381

382-
// FIXME(sized_hierarchy): this temporarily reverts the `sized_hierarchy` feature
383-
// while a proper fix for `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs`
384-
// is pending a proper fix
385-
if !tcx.features().sized_hierarchy() && matches!(sizedness, SizedTraitKind::MetaSized) {
386-
return true;
387-
}
388-
389382
if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
390383
debug!("fast path -- trivial sizedness");
391384
return true;

compiler/rustc_type_ir/src/interner.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ pub trait Interner:
301301

302302
fn is_default_trait(self, def_id: Self::DefId) -> bool;
303303

304+
fn is_sizedness_trait(self, def_id: Self::DefId) -> bool;
305+
304306
fn as_lang_item(self, def_id: Self::DefId) -> Option<TraitSolverLangItem>;
305307

306308
fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator<Item = Self::DefId>;

compiler/rustc_type_ir/src/solve/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ pub struct PredefinedOpaquesData<I: Interner> {
125125
pub opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
126126
}
127127

128+
/// Which trait candidates should be preferred over other candidates? By default, prefer where
129+
/// bounds over alias bounds. For marker traits, prefer alias bounds over where bounds.
130+
#[derive(Clone, Copy, Debug)]
131+
pub enum CandidatePreferenceMode {
132+
/// Prefers where bounds over alias bounds
133+
Default,
134+
/// Prefers alias bounds over where bounds
135+
Marker,
136+
}
137+
138+
impl CandidatePreferenceMode {
139+
/// Given `trait_def_id`, which candidate preference mode should be used?
140+
pub fn compute<I: Interner>(cx: I, trait_def_id: I::DefId) -> CandidatePreferenceMode {
141+
let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_def_id)
142+
|| cx.trait_is_auto(trait_def_id)
143+
|| cx.is_default_trait(trait_def_id);
144+
if is_sizedness_or_auto_or_default_goal {
145+
CandidatePreferenceMode::Marker
146+
} else {
147+
CandidatePreferenceMode::Default
148+
}
149+
}
150+
}
151+
128152
/// Possible ways the given goal can be proven.
129153
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
130154
pub enum CandidateSource<I: Interner> {

tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extern "C" {
88
}
99

1010
const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
11-
//~^ ERROR `extern type` does not have known layout
11+
//~^ ERROR: the size for values of type `Opaque` cannot be known
1212
const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) };
13-
//~^ ERROR `extern type` does not have known layout
13+
//~^ ERROR: the size for values of type `Opaque` cannot be known
1414

1515
fn main() {}
Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,39 @@
1-
error[E0080]: `extern type` does not have known layout
2-
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31
1+
error[E0277]: the size for values of type `Opaque` cannot be known
2+
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:43
33
|
44
LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_SIZE` failed here
5+
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= note: the trait bound `Opaque: MetaSized` is not satisfied
10+
note: required by a bound in `std::intrinsics::size_of_val`
11+
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
12+
help: consider borrowing here
13+
|
14+
LL | const _SIZE: usize = unsafe { size_of_val(&(&4 as *const i32 as *const Opaque)) };
15+
| ++ +
16+
LL | const _SIZE: usize = unsafe { size_of_val(&mut (&4 as *const i32 as *const Opaque)) };
17+
| ++++++ +
618

7-
error[E0080]: `extern type` does not have known layout
8-
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
19+
error[E0277]: the size for values of type `Opaque` cannot be known
20+
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:45
921
|
1022
LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) };
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here
23+
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque`
24+
| |
25+
| required by a bound introduced by this call
26+
|
27+
= note: the trait bound `Opaque: MetaSized` is not satisfied
28+
note: required by a bound in `std::intrinsics::align_of_val`
29+
--> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
30+
help: consider borrowing here
31+
|
32+
LL | const _ALIGN: usize = unsafe { align_of_val(&(&4 as *const i32 as *const Opaque)) };
33+
| ++ +
34+
LL | const _ALIGN: usize = unsafe { align_of_val(&mut (&4 as *const i32 as *const Opaque)) };
35+
| ++++++ +
1236

1337
error: aborting due to 2 previous errors
1438

15-
For more information about this error, try `rustc --explain E0080`.
39+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)