Skip to content

Commit 0f30dd5

Browse files
committed
upstream: rust-lang#142712
1 parent 9e64506 commit 0f30dd5

27 files changed

+220
-206
lines changed

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,14 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
660660
| PredicateFilter::SelfOnly
661661
| PredicateFilter::SelfTraitThatDefines(_)
662662
| PredicateFilter::SelfAndAssociatedTypeBounds => {
663+
icx.lowerer().add_sizedness_bounds(
664+
&mut bounds,
665+
self_param_ty,
666+
superbounds,
667+
None,
668+
Some(trait_def_id),
669+
item.span,
670+
);
663671
icx.lowerer().add_default_super_traits(
664672
trait_def_id,
665673
&mut bounds,

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6464

6565
self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
6666

67-
let (elaborated_trait_bounds, elaborated_projection_bounds) =
67+
let (mut elaborated_trait_bounds, elaborated_projection_bounds) =
6868
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
69+
70+
// FIXME(sized-hierarchy): https://github.com/rust-lang/rust/pull/142712#issuecomment-3013231794
71+
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
72+
elaborated_trait_bounds.retain(|(pred, _)| pred.def_id() != meta_sized_did);
73+
6974
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
7075
.into_iter()
7176
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));

compiler/rustc_middle/src/ty/context.rs

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

495+
fn is_sizedness_trait(self, def_id: DefId) -> bool {
496+
self.is_sizedness_trait(def_id)
497+
}
498+
495499
fn as_lang_item(self, def_id: DefId) -> Option<TraitSolverLangItem> {
496500
lang_item_to_trait_lang_item(self.lang_items().from_def_id(def_id)?)
497501
}
@@ -1644,6 +1648,10 @@ impl<'tcx> TyCtxt<'tcx> {
16441648
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
16451649
}
16461650

1651+
pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
1652+
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
1653+
}
1654+
16471655
/// Returns a range of the start/end indices specified with the
16481656
/// `rustc_layout_scalar_valid_range` attribute.
16491657
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,7 @@ where
13431343
#[instrument(level = "debug", skip(self), ret)]
13441344
pub(super) fn merge_trait_candidates(
13451345
&mut self,
1346+
prefer_alias_over_param_candidates: bool,
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 prefer_alias_over_param_candidates
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,12 @@ 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 did = goal.predicate.def_id();
1448+
let is_sizedness_or_auto_or_default_goal = self.cx().is_sizedness_trait(did)
1449+
|| self.cx().trait_is_auto(did)
1450+
|| self.cx().is_default_trait(did);
1451+
self.merge_trait_candidates(is_sizedness_or_auto_or_default_goal, candidates)
14351452
}
14361453

14371454
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
@@ -146,8 +146,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
146146
obligation: &PolyTraitObligation<'tcx>,
147147
idx: usize,
148148
) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
149-
let tcx = self.tcx();
150-
151149
let placeholder_trait_predicate =
152150
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref;
153151
let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty());
@@ -196,28 +194,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
196194
.map_err(|_| SelectionError::Unimplemented)?,
197195
);
198196

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

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
485485
}
486486
} else {
487487
let has_non_region_infer = stack.obligation.predicate.has_non_region_infer();
488-
if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) {
488+
let did = stack.obligation.predicate.def_id();
489+
let is_sizedness_or_auto_or_default_predicate = self.tcx().is_sizedness_trait(did)
490+
|| self.tcx().trait_is_auto(did)
491+
|| self.tcx().is_default_trait(did);
492+
if let Some(candidate) = self.winnow_candidates(
493+
has_non_region_infer,
494+
is_sizedness_or_auto_or_default_predicate,
495+
candidates,
496+
) {
489497
self.filter_reservation_impls(candidate)
490498
} else {
491499
Ok(None)
@@ -1826,6 +1834,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18261834
fn winnow_candidates(
18271835
&mut self,
18281836
has_non_region_infer: bool,
1837+
prefer_alias_over_param_candidates: bool,
18291838
mut candidates: Vec<EvaluatedCandidate<'tcx>>,
18301839
) -> Option<SelectionCandidate<'tcx>> {
18311840
if candidates.len() == 1 {
@@ -1879,6 +1888,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18791888
break;
18801889
}
18811890

1891+
let alias_bound = candidates
1892+
.iter()
1893+
.filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None })
1894+
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
1895+
1896+
if prefer_alias_over_param_candidates {
1897+
match alias_bound {
1898+
Some(Some(index)) => return Some(ProjectionCandidate(index)),
1899+
Some(None) => {}
1900+
None => return None,
1901+
}
1902+
}
1903+
18821904
// The next highest priority is for non-global where-bounds. However, while we don't
18831905
// prefer global where-clauses here, we do bail with ambiguity when encountering both
18841906
// a global and a non-global where-clause.
@@ -1912,10 +1934,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19121934
// fairly arbitrary but once again necessary for backwards compatibility.
19131935
// If there are multiple applicable candidates which don't affect type inference,
19141936
// choose the one with the lowest index.
1915-
let alias_bound = candidates
1916-
.iter()
1917-
.filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None })
1918-
.try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });
19191937
match alias_bound {
19201938
Some(Some(index)) => return Some(ProjectionCandidate(index)),
19211939
Some(None) => {}

compiler/rustc_type_ir/src/interner.rs

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

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

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

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

tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ trait Bop {
99

1010
fn bop<T: Bop + ?Sized>() {
1111
let _ = <T as Bop>::Bar::default();
12-
//~^ ERROR: trait bounds were not satisfied
12+
//~^ ERROR: the size for values of type `T` cannot be known at compilation time
13+
//~| ERROR: the size for values of type `T` cannot be known at compilation time
1314
//~| ERROR: the size for values of type `T` cannot be known at compilation time
1415
}
1516

tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,58 @@ help: consider relaxing the implicit `Sized` restriction
2424
LL | type Bar: Default + ?Sized
2525
| ++++++++
2626

27-
error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied
28-
--> $DIR/assoc_type_bounds_sized_used.rs:11:30
27+
error[E0277]: the size for values of type `T` cannot be known at compilation time
28+
--> $DIR/assoc_type_bounds_sized_used.rs:11:13
2929
|
30+
LL | fn bop<T: Bop + ?Sized>() {
31+
| - this type parameter needs to be `Sized`
3032
LL | let _ = <T as Bop>::Bar::default();
31-
| ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
34+
|
35+
note: required by a bound in `Bop::Bar`
36+
--> $DIR/assoc_type_bounds_sized_used.rs:7:15
37+
|
38+
LL | type Bar: Default
39+
| --- required by a bound in this associated type
40+
LL | where
41+
LL | Self: Sized;
42+
| ^^^^^ required by this bound in `Bop::Bar`
43+
help: consider removing the `?Sized` bound to make the type parameter `Sized`
44+
|
45+
LL - fn bop<T: Bop + ?Sized>() {
46+
LL + fn bop<T: Bop>() {
3247
|
33-
= note: the following trait bounds were not satisfied:
34-
`T: Sized`
35-
which is required by `<T as Bop>::Bar: Default`
36-
help: consider restricting the type parameter to satisfy the trait bound
48+
help: consider relaxing the implicit `Sized` restriction
49+
|
50+
LL | type Bar: Default + ?Sized
51+
| ++++++++
52+
53+
error[E0277]: the size for values of type `T` cannot be known at compilation time
54+
--> $DIR/assoc_type_bounds_sized_used.rs:11:13
3755
|
38-
LL | fn bop<T: Bop + ?Sized>() where T: Sized {
39-
| ++++++++++++++
56+
LL | fn bop<T: Bop + ?Sized>() {
57+
| - this type parameter needs to be `Sized`
58+
LL | let _ = <T as Bop>::Bar::default();
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
60+
|
61+
note: required by a bound in `Bop::Bar`
62+
--> $DIR/assoc_type_bounds_sized_used.rs:7:15
63+
|
64+
LL | type Bar: Default
65+
| --- required by a bound in this associated type
66+
LL | where
67+
LL | Self: Sized;
68+
| ^^^^^ required by this bound in `Bop::Bar`
69+
help: consider removing the `?Sized` bound to make the type parameter `Sized`
70+
|
71+
LL - fn bop<T: Bop + ?Sized>() {
72+
LL + fn bop<T: Bop>() {
73+
|
74+
help: consider relaxing the implicit `Sized` restriction
75+
|
76+
LL | type Bar: Default + ?Sized
77+
| ++++++++
4078

41-
error: aborting due to 2 previous errors
79+
error: aborting due to 3 previous errors
4280

43-
Some errors have detailed explanations: E0277, E0599.
44-
For more information about an error, try `rustc --explain E0277`.
81+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,3 @@
1-
error: lifetime bound not satisfied
2-
--> $DIR/issue-100013.rs:15:5
3-
|
4-
LL | / async { // a coroutine checked for autotrait impl `Send`
5-
LL | | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
6-
LL | | async {}.await; // a yield point
7-
LL | | }
8-
| |_____^
9-
|
10-
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
11-
12-
error: lifetime bound not satisfied
13-
--> $DIR/issue-100013.rs:22:5
14-
|
15-
LL | / async { // a coroutine checked for autotrait impl `Send`
16-
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
17-
LL | | async {}.await; // a yield point
18-
LL | | }
19-
| |_____^
20-
|
21-
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
22-
231
error: lifetime may not live long enough
242
--> $DIR/issue-100013.rs:23:17
253
|
@@ -33,16 +11,5 @@ LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
3311
|
3412
= help: consider adding the following bound: `'a: 'b`
3513

36-
error: lifetime bound not satisfied
37-
--> $DIR/issue-100013.rs:29:5
38-
|
39-
LL | / async { // a coroutine checked for autotrait impl `Send`
40-
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
41-
LL | | async {}.await; // a yield point
42-
LL | | }
43-
| |_____^
44-
|
45-
= note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
46-
47-
error: aborting due to 4 previous errors
14+
error: aborting due to 1 previous error
4815

0 commit comments

Comments
 (0)